Currently, the IOVA and its mapping (to physical doorbell address) is done by the dma-iommu via the iommu_cookie in the struct msi_desc, which is the structure used by three parties: genirq, irqchip and dma-iommu. However, when dealing with a nested translation on ARM64, the MSI doorbell address is behind the SMMU (IOMMU on ARM64), thus HW needs to be programed with the stage-1 IOVA, i.e. guest-level IOVA, rather than asking dma-iommu to allocate one. To support a guest-programmable pathway, first we need to make sure struct msi_desc will allow a preset IOVA v.s. using iommu_cookie. Add an msi_iova to the structure and init its value to PHYS_ADDR_MAX. And provide a helper for drivers to get the msi_iova out of an msi_desc object. A following patch will change msi_setup_msi_descs and msix_setup_msi_descs to call msi_domain_insert_msi_desc and finish the actual value forwarding. Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx> --- include/linux/msi.h | 11 +++++++++++ kernel/irq/msi.c | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/include/linux/msi.h b/include/linux/msi.h index b10093c4d00e..873094743065 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -185,6 +185,7 @@ struct msi_desc { struct irq_affinity_desc *affinity; #ifdef CONFIG_IRQ_MSI_IOMMU const void *iommu_cookie; + dma_addr_t msi_iova; #endif #ifdef CONFIG_SYSFS struct device_attribute *sysfs_attrs; @@ -296,6 +297,11 @@ static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, { desc->iommu_cookie = iommu_cookie; } + +static inline dma_addr_t msi_desc_get_iova(struct msi_desc *desc) +{ + return desc->msi_iova; +} #else static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) { @@ -306,6 +312,11 @@ static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, const void *iommu_cookie) { } + +static inline dma_addr_t msi_desc_get_iova(struct msi_desc *desc) +{ + return PHYS_ADDR_MAX; +} #endif int msi_domain_insert_msi_desc(struct device *dev, unsigned int domid, diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 3a24d6b5f559..f3159ec0f036 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -81,6 +81,9 @@ static struct msi_desc *msi_alloc_desc(struct device *dev, int nvec, desc->dev = dev; desc->nvec_used = nvec; +#ifdef CONFIG_IRQ_MSI_IOMMU + desc->msi_iova = PHYS_ADDR_MAX; +#endif if (affinity) { desc->affinity = kmemdup_array(affinity, nvec, sizeof(*desc->affinity), GFP_KERNEL); if (!desc->affinity) { @@ -158,6 +161,9 @@ int msi_domain_insert_msi_desc(struct device *dev, unsigned int domid, /* Copy type specific data to the new descriptor. */ desc->pci = init_desc->pci; +#ifdef CONFIG_IRQ_MSI_IOMMU + desc->msi_iova = init_desc->msi_iova; +#endif return msi_insert_desc(dev, desc, domid, init_desc->msi_index); } -- 2.43.0