IOMMU drivers can use this to implement their .get_resv_regions callback for any RMR address regions specific to a device. As per ACPI IORT E.b spec, a check is added to make sure OS has preserved the PCIe configuration done by boot firmware. Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@xxxxxxxxxx> --- drivers/iommu/dma-iommu.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/dma-iommu.h | 7 +++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index a942cc04eee1..c624000bf230 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -191,6 +191,41 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list) } EXPORT_SYMBOL(iommu_dma_get_resv_regions); +void iommu_dma_get_rmr_resv_regions(struct device *dev, struct iommu_rmr *rmr, + struct list_head *list) +{ + int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; + struct iommu_resv_region *region; + enum iommu_resv_type type; + + /* + * For ACPI, please make sure the OS has preserved the PCIe configuration + * performed by the boot firmware(See IORT revision E.b). + */ + if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode) && + dev_is_pci(dev)) { + struct pci_dev *pdev = to_pci_dev(dev); + struct pci_host_bridge *host = pci_find_host_bridge(pdev->bus); + + if (!host->preserve_config) + return; + } + + if (rmr->flags & IOMMU_RMR_REMAP_PERMITTED) + type = IOMMU_RESV_DIRECT_RELAXABLE; + else + type = IOMMU_RESV_DIRECT; + + region = iommu_alloc_resv_region(rmr->base_address, + rmr->length, prot, + type); + if (!region) + return; + + list_add_tail(®ion->list, list); +} +EXPORT_SYMBOL(iommu_dma_get_rmr_resv_regions); + /** * iommu_dma_get_rmrs - Retrieve Reserved Memory Regions(RMRs) associated * with a given IOMMU diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h index beb84c4fe5b1..dbad5073c9e0 100644 --- a/include/linux/dma-iommu.h +++ b/include/linux/dma-iommu.h @@ -40,6 +40,8 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list); void iommu_dma_free_cpu_cached_iovas(unsigned int cpu, struct iommu_domain *domain); +void iommu_dma_get_rmr_resv_regions(struct device *dev, struct iommu_rmr *rmr, + struct list_head *list); int iommu_dma_get_rmrs(struct fwnode_handle *iommu, struct list_head *list); struct iommu_rmr *iommu_dma_alloc_rmr(u64 base, u64 length, u32 sid, u32 flags); @@ -89,6 +91,11 @@ static inline void iommu_dma_free_cpu_cached_iovas(unsigned int cpu, { } +static void iommu_dma_get_rmr_resv_regions(struct device *dev, struct iommu_rmr *rmr, + struct list_head *list) +{ +} + int iommu_dma_get_rmrs(struct fwnode_handle *iommu, struct list_head *list); { return 0; -- 2.17.1