> From: Nicolin Chen <nicolinc@xxxxxxxxxx> > Sent: Saturday, August 3, 2024 8:32 AM > > From: Robin Murphy <robin.murphy@xxxxxxx> > > Currently, iommu-dma is the only place outside of IOMMUFD and drivers > which might need to be aware of the stage 2 domain encapsulated within > a nested domain. This would be in the legacy-VFIO-style case where we're why is it a legacy-VFIO-style? We only support nested in IOMMUFD. > using host-managed MSIs with an identity mapping at stage 1, where it is > the underlying stage 2 domain which owns an MSI cookie and holds the > corresponding dynamic mappings. Hook up the new op to resolve what we > need from a nested domain. > > Signed-off-by: Robin Murphy <robin.murphy@xxxxxxx> > Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx> > --- > drivers/iommu/dma-iommu.c | 18 ++++++++++++++++-- > include/linux/iommu.h | 4 ++++ > 2 files changed, 20 insertions(+), 2 deletions(-) > > diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c > index 7b1dfa0665df6..05e04934a5f81 100644 > --- a/drivers/iommu/dma-iommu.c > +++ b/drivers/iommu/dma-iommu.c > @@ -1799,6 +1799,20 @@ static struct iommu_dma_msi_page > *iommu_dma_get_msi_page(struct device *dev, > return NULL; > } > > +/* > + * Nested domains may not have an MSI cookie or accept mappings, but > they may > + * be related to a domain which does, so we let them tell us what they need. > + */ > +static struct iommu_domain > *iommu_dma_get_msi_mapping_domain(struct device *dev) > +{ > + struct iommu_domain *domain = iommu_get_domain_for_dev(dev); > + > + if (domain && domain->type == IOMMU_DOMAIN_NESTED && > + domain->ops->get_msi_mapping_domain) I'm not sure the core should restrict it to the NESTED type. Given there is a new domain ops any type restriction can be handled inside the callback. Anyway the driver should register the op for a domain only when there is a need. > + domain = domain->ops->get_msi_mapping_domain(domain); > + return domain; > +} > + > /** > * iommu_dma_prepare_msi() - Map the MSI page in the IOMMU domain > * @desc: MSI descriptor, will store the MSI page > @@ -1809,7 +1823,7 @@ static struct iommu_dma_msi_page > *iommu_dma_get_msi_page(struct device *dev, > int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) > { > struct device *dev = msi_desc_to_dev(desc); > - struct iommu_domain *domain = iommu_get_domain_for_dev(dev); > + struct iommu_domain *domain = > iommu_dma_get_msi_mapping_domain(dev); > struct iommu_dma_msi_page *msi_page; > static DEFINE_MUTEX(msi_prepare_lock); /* see below */ > > @@ -1842,7 +1856,7 @@ int iommu_dma_prepare_msi(struct msi_desc > *desc, phys_addr_t msi_addr) > void iommu_dma_compose_msi_msg(struct msi_desc *desc, struct msi_msg > *msg) > { > struct device *dev = msi_desc_to_dev(desc); > - const struct iommu_domain *domain = > iommu_get_domain_for_dev(dev); > + const struct iommu_domain *domain = > iommu_dma_get_msi_mapping_domain(dev); > const struct iommu_dma_msi_page *msi_page; > > msi_page = msi_desc_get_iommu_cookie(desc); > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > index 4d47f2c333118..69ed76f9c3ec4 100644 > --- a/include/linux/iommu.h > +++ b/include/linux/iommu.h > @@ -638,6 +638,8 @@ struct iommu_ops { > * @enable_nesting: Enable nesting > * @set_pgtable_quirks: Set io page table quirks (IO_PGTABLE_QUIRK_*) > * @free: Release the domain after use. > + * @get_msi_mapping_domain: Return the related iommu_domain that > should hold the > + * MSI cookie and accept mapping(s). > */ > struct iommu_domain_ops { > int (*attach_dev)(struct iommu_domain *domain, struct device *dev); > @@ -668,6 +670,8 @@ struct iommu_domain_ops { > unsigned long quirks); > > void (*free)(struct iommu_domain *domain); > + struct iommu_domain * > + (*get_msi_mapping_domain)(struct iommu_domain > *domain); > }; > > /** > -- > 2.43.0 >