On Thu, Jan 23, 2025 at 06:10:47PM +0100, Eric Auger wrote: > Hi, > > > On 1/11/25 4:32 AM, Nicolin Chen wrote: > > From: Jason Gunthorpe <jgg@xxxxxxxxxx> > > > > SW_MSI supports IOMMU to translate an MSI message before the MSI message > > is delivered to the interrupt controller. On such systems the iommu_domain > > must have a translation for the MSI message for interrupts to work. > > > > The IRQ subsystem will call into IOMMU to request that a physical page be > > setup to receive MSI message, and the IOMMU then sets an IOVA that maps to > > that physical page. Ultimately the IOVA is programmed into the device via > > the msi_msg. > > > > Generalize this to allow the iommu_domain owner to provide its own > > implementation of this mapping. Add a function pointer to struct > > iommu_domain to allow the domain owner to provide an implementation. > > > > Have dma-iommu supply its implementation for IOMMU_DOMAIN_DMA types during > > the iommu_get_dma_cookie() path. For IOMMU_DOMAIN_UNMANAGED types used by > > VFIO (and iommufd for now), have the same iommu_dma_sw_msi set as well in > > the iommu_get_msi_cookie() path. > > > > Hold the group mutex while in iommu_dma_prepare_msi() to ensure the domain > > doesn't change or become freed while running. Races with IRQ operations > > from VFIO and domain changes from iommufd are possible here. > this was my question in previous comments Ah, well there is the answer :) > > Rreplace the msi_prepare_lock with a lockdep assertion for the group mutex > Replace > > as documentation. For the dma_iommu.c each iommu_domain unique to a > is? > > group. Yes Replace the msi_prepare_lock with a lockdep assertion for the group mutex as documentation. For the dmau_iommu.c each iommu_domain is unique to a group. > > @@ -443,6 +449,9 @@ void iommu_put_dma_cookie(struct iommu_domain *domain) > > struct iommu_dma_cookie *cookie = domain->iova_cookie; > > struct iommu_dma_msi_page *msi, *tmp; > > > > + if (domain->sw_msi != iommu_dma_sw_msi) > > + return; > > + > I don't get the above check. It is because of this: void iommu_domain_free(struct iommu_domain *domain) { if (domain->type == IOMMU_DOMAIN_SVA) mmdrop(domain->mm); iommu_put_dma_cookie(domain); iommufd may be using domain->sw_msi so iommu_put_dma_cookie() needs to be a NOP. Also, later we move cookie into a union so it is not reliably NULL anymore. > The comment says this is also called for a > cookie prepared with iommu_get_dma_cookie(). Don't you need to do some > cleanup for this latter? That seems seems OK, only two places set domain->iova_cookie: int iommu_get_dma_cookie(struct iommu_domain *domain) { domain->iova_cookie = cookie_alloc(IOMMU_DMA_IOVA_COOKIE); iommu_domain_set_sw_msi(domain, iommu_dma_sw_msi); and int iommu_get_msi_cookie(struct iommu_domain *domain, dma_addr_t base) { domain->iova_cookie = cookie; iommu_domain_set_sw_msi(domain, iommu_dma_sw_msi); So (domain->sw_msi == iommu_dma_sw_msi) in iommu_put_dma_cookie() for both cases.. Jason