From 00a6fb4cd1d22dceabd8fb12bc7ab6a841879b79 Mon Sep 17 00:00:00 2001 From: LeoLiu-oc Date: Fri, 4 Jul 2025 10:31:43 +0800 Subject: [PATCH] iommu: Add support for ACPI device direct mapping zhaoxin inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICGAMX CVE: NA -------------------- When an ACPI device has a corresponding PCI device, create a direct mapping on the PCI device. If no corresponding PCI device is found, create a direct mapping on the ACPI device. Refactor code (get iommu and pci_device) to reduce unnecessary operations during physical_node_list traversal. Suggested-by: Jason Zeng Signed-off-by: LeoLiu-oc Signed-off-by: YeeLi-oc --- drivers/iommu/intel/iommu.c | 88 ++++++++++++++++--------------------- include/linux/iommu.h | 11 +++++ 2 files changed, 48 insertions(+), 51 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index ef2623257a71..a68d1bfc7444 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -4985,7 +4985,8 @@ static int __init platform_optin_force_iommu(void) return 1; } -static int acpi_device_create_direct_mappings(struct device *pn_dev, struct device *acpi_device) +static int __init acpi_device_create_direct_mappings(struct device *pn_dev, + struct device *acpi_device) { struct iommu_group *group; @@ -5001,6 +5002,28 @@ static int acpi_device_create_direct_mappings(struct device *pn_dev, struct devi return 0; } +static int __init zhaoxin_acpi_rmrr_andd_configure(struct device *dev) +{ + struct device_domain_info *info; + struct intel_iommu *iommu; + struct pci_dev *pdev; + u8 bus, devfn; + + iommu = device_to_iommu(dev, &bus, &devfn); + if (!iommu) + return -ENODEV; + + pdev = pci_get_domain_bus_and_slot(iommu->segment, bus, devfn); + if (!pdev) + return -ENODEV; + + info = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn); + if (!info) + return acpi_device_create_direct_mappings(&pdev->dev, dev); + + return acpi_device_create_direct_mappings(info->dev, dev); +} + static int __init probe_acpi_namespace_devices(void) { struct dmar_drhd_unit *drhd; @@ -5008,72 +5031,35 @@ static int __init probe_acpi_namespace_devices(void) struct intel_iommu *iommu __maybe_unused; struct device *dev; int i, ret = 0; - u8 bus, devfn; for_each_active_iommu(iommu, drhd) { for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) { struct acpi_device_physical_node *pn; + struct iommu_group *group; struct acpi_device *adev; - struct device *pn_dev = NULL; - struct device_domain_info *info = NULL; - struct pci_dev *pci_device = NULL; if (dev->bus != &acpi_bus_type) continue; adev = to_acpi_device(dev); mutex_lock(&adev->physical_node_lock); - list_for_each_entry(pn, - &adev->physical_node_list, node) { - iommu = device_to_iommu(dev, &bus, &devfn); - if (!iommu) { - ret = -ENODEV; - goto unlock; + list_for_each_entry(pn, &adev->physical_node_list, node) { + group = iommu_group_get(pn->dev); + if (group) { + iommu_group_put(group); + continue; } - pci_device = pci_get_domain_bus_and_slot(iommu->segment, - bus, devfn); - if (!pci_device) { - pr_info("cannot get the corresponding pci_device\n"); - ret = -ENODEV; + pn->dev->bus->iommu_ops = &intel_iommu_ops; + ret = iommu_probe_device(pn->dev); + if (ret) goto unlock; - } - - info = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn); - if (!info) { - pn->dev->bus->iommu_ops = &intel_iommu_ops; - ret = iommu_probe_device(pn->dev); - if (ret) { - pr_err("pn->dev:%s probe fail! ret:%d\n", - dev_name(pn->dev), ret); - goto unlock; - } - } - pn_dev = pn->dev; } - if (!pn_dev) { - iommu = device_to_iommu(dev, &bus, &devfn); - if (!iommu) { - ret = -ENODEV; - goto unlock; - } - info = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn); - if (!info) { - dev->bus->iommu_ops = &intel_iommu_ops; - ret = iommu_probe_device(dev); - if (ret) { - pr_err("dev:%s probe fail! ret:%d\n", - dev_name(dev), ret); - goto unlock; - } - goto unlock; - } - } - if (!info) - ret = acpi_device_create_direct_mappings(&pci_device->dev, dev); - else - ret = acpi_device_create_direct_mappings(info->dev, dev); + + if (need_config_zhaoxin_rmrr_andd()) + ret = zhaoxin_acpi_rmrr_andd_configure(dev); + unlock: mutex_unlock(&adev->physical_node_lock); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 355f4e437d67..99ccff6230c8 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -613,6 +613,17 @@ extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev, extern void __acpi_device_create_direct_mappings(struct iommu_group *group, struct device *acpi_device); +static inline bool need_config_zhaoxin_rmrr_andd(void) +{ +#if defined(CONFIG_CPU_SUP_ZHAOXIN) || defined(CONFIG_CPU_SUP_CENTAUR) + if (((boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR) || + (boot_cpu_data.x86_vendor == X86_VENDOR_ZHAOXIN)) && + ((boot_cpu_data.x86 == 7) && (boot_cpu_data.x86_model == 0x3b))) + return true; +#endif + return false; +} + static inline void iommu_flush_iotlb_all(struct iommu_domain *domain) { if (domain->ops->flush_iotlb_all) -- Gitee