在 2021/6/16 17:03, Xiongfeng Wang 写道:
On 2021/6/4 17:36, LeoLiuoc wrote:
When using ACPI device to create identity mapping, if the physical node of
the ACPI device is a pci device, domain_1 will be created for these two
devices. But if the pci device and other pci devices belong to another
domain_2, this will happen conflict and destroy another domain. Such as
I think it may be caused by a BIOS flaw. The pci device and the corresponding
acpi device are both listed in Device Scope ? I'm not sure whether it's a flaw.
Can we fix this by only modifying DMAR table ? Have we sent this patch to the
mainline ?

Thanks,
Xiongfeng
This is not a problem reported by BIOS.In fact,some ACPI devices use the SID of
the pci device to work. The BIOS only need to report the ACPI device in RMRR,
but the reported SID belongs to a pci device.So there is a domain conflict.This
patch increases the handing of domain conflicts.
This patch is base on a previously submitted patch which has been received by 
openEuler-1.0-LTS(0f7d0c8b66a415734cbd2c8a7afc586c4a1d61cc).But the previous patch
has not been received by the mainline,so this patch will not be submitted
to the mainline.

BRs
Leo
PCI devices under the PCIE-to-PCI bridge. Therefore, when the physical
node of the ACPI device is a PCI device, this patch uses the PCI device to
create the domain. In this way, there is only one domain.

Signed-off-by: LeoLiu-oc <LeoLiu-oc@zhaoxin.com>
---
 drivers/iommu/intel-iommu.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index e111e5d6d269..cf0dc4c80183 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2736,12 +2736,32 @@ static int domain_prepare_identity_map(struct device *dev,
     return iommu_domain_identity_map(domain, start, end);
 }

+static struct device *acpi_dev_find_pci_dev(struct device *dev)
+{
+    struct acpi_device_physical_node *pn;
+    struct acpi_device *adev;
+
+    if (dev->bus == &acpi_bus_type) {
+        adev = to_acpi_device(dev);
+        mutex_lock(&adev->physical_node_lock);
+        list_for_each_entry(pn, &adev->physical_node_list, node) {
+            if (dev_is_pci(pn->dev)) {
+                return pn->dev;
+            }
+        }
+        mutex_unlock(&adev->physical_node_lock);
+    }
+
+    return dev;
+}
+
 static int iommu_prepare_identity_map(struct device *dev,
                       unsigned long long start,
                       unsigned long long end)
 {
     struct dmar_domain *domain;
     int ret;
+    dev = acpi_dev_find_pci_dev(dev);

     domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
     if (!domain)
.