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 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)
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
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)
在 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-ocLeoLiu-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)
.
On 2021/6/17 17:57, LeoLiuoc wrote:
在 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.
Could you share your DMAR and DSDT table ?
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)
.
在 2021/6/17 21:05, Xiongfeng Wang 写道:
On 2021/6/17 17:57, LeoLiuoc wrote:
在 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.
Could you share your DMAR and DSDT table ?
Please see the attachments.
BRs Leo
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)
.
.
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 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)) {
Needs 'mutex_unlock' here
+ 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)
在 2021/6/17 19:34, 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 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)) {
Needs 'mutex_unlock' here
Yes, you are right. We will submit a new version(v2) of this patch soon.
BRs Leo
+ 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)
.