Hi Jason, On 1/23/25 7:16 PM, Jason Gunthorpe wrote: > 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. OK > >> 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.. makes sense. Thanks Eric > > Jason >