IOMMU Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
@ 2020-07-28 10:06 FelixCuioc
  2020-07-31  9:06 ` kernel test robot
  0 siblings, 1 reply; 14+ messages in thread
From: FelixCuioc @ 2020-07-28 10:06 UTC (permalink / raw)
  To: Joerg Roedel, iommu, linux-kernel, David Woodhouse, Lu Baolu
  Cc: CobeChen, RaymondPang

Some ACPI devices require access to the specified reserved memory
region.BIOS report the specified reserved memory region through
RMRR structures.Add analysis of ACPI device in RMRR and establish
identity mapping for ACPI device.

Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
---
 drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
 drivers/iommu/intel/iommu.c | 47 ++++++++++++++++++++++-
 drivers/iommu/iommu.c       |  5 +++
 include/linux/dmar.h        | 12 ++++--
 include/linux/iommu.h       |  3 ++
 5 files changed, 102 insertions(+), 39 deletions(-)

diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index 93e6345f3414..024ca38dba12 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
 }
 
 /* Return: > 0 if match found, 0 if no match found, < 0 if error happens */
-int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
+int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
 			  void *start, void*end, u16 segment,
 			  struct dmar_dev_scope *devices,
 			  int devices_cnt)
@@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct dmar_pci_notify_info *info)
 
 		drhd = container_of(dmaru->hdr,
 				    struct acpi_dmar_hardware_unit, header);
-		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
+		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
 				((void *)drhd) + drhd->header.length,
 				dmaru->segment,
 				dmaru->devices, dmaru->devices_cnt);
@@ -696,48 +696,56 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
 
 	return dmaru;
 }
-
-static void __init dmar_acpi_insert_dev_scope(u8 device_number,
-					      struct acpi_device *adev)
+int dmar_acpi_insert_dev_scope(u8 device_number,
+				struct acpi_device *adev,
+				void *start, void *end,
+				struct dmar_dev_scope *devices,
+				int devices_cnt)
 {
-	struct dmar_drhd_unit *dmaru;
-	struct acpi_dmar_hardware_unit *drhd;
 	struct acpi_dmar_device_scope *scope;
 	struct device *tmp;
 	int i;
 	struct acpi_dmar_pci_path *path;
 
+	for (; start < end; start += scope->length) {
+		scope = start;
+		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
+			continue;
+		if (scope->enumeration_id != device_number)
+			continue;
+		path = (void *)(scope + 1);
+		for_each_dev_scope(devices, devices_cnt, i, tmp)
+			if (tmp == NULL) {
+				devices[i].bus = scope->bus;
+				devices[i].devfn = PCI_DEVFN(path->device, path->function);
+				rcu_assign_pointer(devices[i].dev,
+						   get_device(&adev->dev));
+				return 1;
+			}
+		WARN_ON(i >= devices_cnt);
+	}
+	return 0;
+}
+static int dmar_acpi_bus_add_dev(u8 device_number, struct acpi_device *adev)
+{
+	struct dmar_drhd_unit *dmaru;
+	struct acpi_dmar_hardware_unit *drhd;
+	int ret = 0;
+
 	for_each_drhd_unit(dmaru) {
 		drhd = container_of(dmaru->hdr,
 				    struct acpi_dmar_hardware_unit,
 				    header);
+		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
+						((void *)drhd)+drhd->header.length,
+						dmaru->devices, dmaru->devices_cnt);
+		if (ret)
+			break;
+	}
+	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
 
-		for (scope = (void *)(drhd + 1);
-		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
-		     scope = ((void *)scope) + scope->length) {
-			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
-				continue;
-			if (scope->enumeration_id != device_number)
-				continue;
+	return ret;
 
-			path = (void *)(scope + 1);
-			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
-				dev_name(&adev->dev), dmaru->reg_base_addr,
-				scope->bus, path->device, path->function);
-			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
-				if (tmp == NULL) {
-					dmaru->devices[i].bus = scope->bus;
-					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
-									    path->function);
-					rcu_assign_pointer(dmaru->devices[i].dev,
-							   get_device(&adev->dev));
-					return;
-				}
-			BUG_ON(i >= dmaru->devices_cnt);
-		}
-	}
-	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
-		device_number, dev_name(&adev->dev));
 }
 
 static int __init dmar_acpi_dev_scope_init(void)
@@ -766,7 +774,7 @@ static int __init dmar_acpi_dev_scope_init(void)
 				       andd->device_name);
 				continue;
 			}
-			dmar_acpi_insert_dev_scope(andd->device_number, adev);
+			dmar_acpi_bus_add_dev(andd->device_number, adev);
 		}
 	}
 	return 0;
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 0c2d582ff8cd..62cb993e3bbe 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4508,6 +4508,25 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)
 	return ret;
 }
 
+int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev)
+{
+	int ret;
+	struct dmar_rmrr_unit *rmrru;
+	struct acpi_dmar_reserved_memory *rmrr;
+
+	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
+		rmrr = container_of(rmrru->hdr,
+				struct acpi_dmar_reserved_memory,
+				header);
+		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
+						((void *)rmrr) + rmrr->header.length,
+						rmrru->devices, rmrru->devices_cnt);
+		if (ret)
+			break;
+	}
+	return 0;
+}
+
 int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
 {
 	int ret;
@@ -4523,7 +4542,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
 		rmrr = container_of(rmrru->hdr,
 				    struct acpi_dmar_reserved_memory, header);
 		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
-			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
+			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
 				((void *)rmrr) + rmrr->header.length,
 				rmrr->segment, rmrru->devices,
 				rmrru->devices_cnt);
@@ -4541,7 +4560,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
 
 		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
 		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
-			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
+			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
 					(void *)atsr + atsr->header.length,
 					atsr->segment, atsru->devices,
 					atsru->devices_cnt);
@@ -4779,6 +4798,26 @@ 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)
+{
+	int ret;
+	struct iommu_group *group;
+
+	if (pn_dev == NULL) {
+		acpi_device->bus->iommu_ops = &intel_iommu_ops;
+		ret = iommu_probe_device(acpi_device);
+		if (ret) {
+			pr_err("acpi_device probe fail! ret:%d\n", ret);
+			return ret;
+		}
+		return 0;
+	}
+	acpi_device->bus->iommu_ops = &intel_iommu_ops;
+	group = iommu_group_get(pn_dev);
+	__acpi_device_create_direct_mappings(group, acpi_device);
+
+	return 0;
+}
 
 static int __init probe_acpi_namespace_devices(void)
 {
@@ -4794,6 +4833,7 @@ static int __init probe_acpi_namespace_devices(void)
 			struct acpi_device_physical_node *pn;
 			struct iommu_group *group;
 			struct acpi_device *adev;
+			struct device *pn_dev = NULL;
 
 			if (dev->bus != &acpi_bus_type)
 				continue;
@@ -4804,6 +4844,7 @@ static int __init probe_acpi_namespace_devices(void)
 					    &adev->physical_node_list, node) {
 				group = iommu_group_get(pn->dev);
 				if (group) {
+					pn_dev = pn->dev;
 					iommu_group_put(group);
 					continue;
 				}
@@ -4812,7 +4853,9 @@ static int __init probe_acpi_namespace_devices(void)
 				ret = iommu_probe_device(pn->dev);
 				if (ret)
 					break;
+				pn_dev = pn->dev;
 			}
+			ret = acpi_device_create_direct_mappings(pn_dev, dev);
 			mutex_unlock(&adev->physical_node_lock);
 
 			if (ret)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index d43120eb1dc5..d504d2ab96e8 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -778,6 +778,11 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
 
 	return false;
 }
+void __acpi_device_create_direct_mappings(struct iommu_group *group, struct device *acpi_device)
+{
+	iommu_create_device_direct_mappings(group, acpi_device);
+}
+EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
 
 /**
  * iommu_group_add_device - add a device to an iommu group
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 65565820328a..c3e29e252266 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -113,13 +113,17 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
 				struct dmar_dev_scope **devices, u16 segment);
 extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
 extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt);
-extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
+extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
 				 void *start, void*end, u16 segment,
 				 struct dmar_dev_scope *devices,
 				 int devices_cnt);
-extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
-				 u16 segment, struct dmar_dev_scope *devices,
-				 int count);
+extern int dmar_acpi_insert_dev_scope(u8 device_number,
+				struct acpi_device *adev, void *start, void *end,
+				struct dmar_dev_scope *devices, int devices_cnt);
+extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev);
+
+extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info, u16 segment,
+				struct dmar_dev_scope *devices, int count);
 /* Intel IOMMU detection */
 extern int detect_intel_iommu(void);
 extern int enable_drhd_fault_handling(void);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 5f0b7859d2eb..f639bf94b466 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -536,6 +536,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
 extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
 			      unsigned long iova, int flags);
 
+extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
+						struct device *acpi_device);
+
 static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
 {
 	if (domain->ops->flush_iotlb_all)
-- 
2.17.1

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-07-28 10:06 [PATCH] iommu/vt-d:Add support for ACPI device in RMRR FelixCuioc
@ 2020-07-31  9:06 ` kernel test robot
  0 siblings, 0 replies; 14+ messages in thread
From: kernel test robot @ 2020-07-31  9:06 UTC (permalink / raw)
  To: FelixCuioc, Joerg Roedel, iommu, linux-kernel, David Woodhouse, Lu Baolu
  Cc: CobeChen, kbuild-all, RaymondPang


[-- Attachment #1: Type: text/plain, Size: 3686 bytes --]

Hi FelixCuioc,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on iommu/next]
[also build test ERROR on linux/master linus/master v5.8-rc7 next-20200730]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/FelixCuioc/iommu-vt-d-Add-support-for-ACPI-device-in-RMRR/20200728-182409
base:   https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: x86_64-randconfig-a014-20200731 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-14) 9.3.0
reproduce (this is a W=1 build):
        # save the attached .config to linux build tree
        make W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   ld: drivers/iommu/intel/dmar.o: in function `dmar_acpi_bus_add_dev':
>> drivers/iommu/intel/dmar.c:745: undefined reference to `dmar_rmrr_add_acpi_dev'

vim +745 drivers/iommu/intel/dmar.c

   670	
   671	struct dmar_drhd_unit *
   672	dmar_find_matched_drhd_unit(struct pci_dev *dev)
   673	{
   674		struct dmar_drhd_unit *dmaru;
   675		struct acpi_dmar_hardware_unit *drhd;
   676	
   677		dev = pci_physfn(dev);
   678	
   679		rcu_read_lock();
   680		for_each_drhd_unit(dmaru) {
   681			drhd = container_of(dmaru->hdr,
   682					    struct acpi_dmar_hardware_unit,
   683					    header);
   684	
   685			if (dmaru->include_all &&
   686			    drhd->segment == pci_domain_nr(dev->bus))
   687				goto out;
   688	
   689			if (dmar_pci_device_match(dmaru->devices,
   690						  dmaru->devices_cnt, dev))
   691				goto out;
   692		}
   693		dmaru = NULL;
   694	out:
   695		rcu_read_unlock();
   696	
   697		return dmaru;
   698	}
   699	int dmar_acpi_insert_dev_scope(u8 device_number,
   700					struct acpi_device *adev,
   701					void *start, void *end,
   702					struct dmar_dev_scope *devices,
   703					int devices_cnt)
   704	{
   705		struct acpi_dmar_device_scope *scope;
   706		struct device *tmp;
   707		int i;
   708		struct acpi_dmar_pci_path *path;
   709	
   710		for (; start < end; start += scope->length) {
   711			scope = start;
   712			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
   713				continue;
   714			if (scope->enumeration_id != device_number)
   715				continue;
   716			path = (void *)(scope + 1);
   717			for_each_dev_scope(devices, devices_cnt, i, tmp)
   718				if (tmp == NULL) {
   719					devices[i].bus = scope->bus;
   720					devices[i].devfn = PCI_DEVFN(path->device, path->function);
   721					rcu_assign_pointer(devices[i].dev,
   722							   get_device(&adev->dev));
   723					return 1;
   724				}
   725			WARN_ON(i >= devices_cnt);
   726		}
   727		return 0;
   728	}
   729	static int dmar_acpi_bus_add_dev(u8 device_number, struct acpi_device *adev)
   730	{
   731		struct dmar_drhd_unit *dmaru;
   732		struct acpi_dmar_hardware_unit *drhd;
   733		int ret = 0;
   734	
   735		for_each_drhd_unit(dmaru) {
   736			drhd = container_of(dmaru->hdr,
   737					    struct acpi_dmar_hardware_unit,
   738					    header);
   739			ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
   740							((void *)drhd)+drhd->header.length,
   741							dmaru->devices, dmaru->devices_cnt);
   742			if (ret)
   743				break;
   744		}
 > 745		ret = dmar_rmrr_add_acpi_dev(device_number, adev);
   746	
   747		return ret;
   748	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36919 bytes --]

[-- Attachment #3: Type: text/plain, Size: 156 bytes --]

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* 答复: 答复: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-05  2:56                 ` Lu Baolu
@ 2020-08-05  7:37                   ` FelixCui-oc
  0 siblings, 0 replies; 14+ messages in thread
From: FelixCui-oc @ 2020-08-05  7:37 UTC (permalink / raw)
  To: Lu Baolu, Joerg Roedel, iommu, linux-kernel, David Woodhouse; +Cc: CobeChen-oc

Hi baolu,
		Let me talk about why acpi_device_create_direct_mappings() is needed and please tell me if there is an error.

		In the probe_acpi_namespace_devices() function, only the device in the addev->physical_node_list is probed,
		but we need to establish identity mapping for the namespace device in RMRR. These are two different devices.
		Therefore, the namespace device in RMRR is not mapped in probe_acpi_namespace_devices(). 
		acpi_device_create_direct_mappings() is to create direct mappings for namespace devices in RMRR.

Best regards
Felix cui-oc




-----邮件原件-----
发件人: Lu Baolu <baolu.lu@linux.intel.com> 
发送时间: 2020年8月5日 10:57
收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
抄送: baolu.lu@linux.intel.com; RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
主题: Re: 答复: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR

Hi,

On 8/4/20 11:11 AM, FelixCui-oc wrote:
> Hi  baolu ,
> 		When creating a identity mapping for a namespace device in RMRR, you need to add the namespace device to the rmrr->device[] , right?

Yes. You are right.

> 		The dmar_acpi_bus_add_dev() in patch adds the enumeration of the 
> namespace device in RMRR. This is similar to > enumerating pci 
> devices. Do you think this is unreasonable? If it is
unreasonable, please tell me why it is unreasonable.

It looks reasonable. Thanks for the explanation.

But I don't think we need to add acpi_device_create_direct_mappings()
since the rmrr identity mapping is already done in the iommu core.

Best regards,
baolu

> 			
> Best regards
> Felix cui-oc
> 
> 
> 
> -----邮件原件-----
> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
> 发送时间: 2020年8月4日 9:12
> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc 
> <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
> 主题: Re: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in 
> RMRR
> 
> Hi Felix,
> 
> On 2020/8/3 17:41, FelixCui-oc wrote:
>> Hi baolu,
>> 		 dmar_acpi_dev_scope_init() parse ANDD structure and enumerated namespaces device in DRHD.
> 
> Yes.
> 
>> 		 But the namespace device in RMRR is not enumerated, right?
> 
> It should be probed in probe_acpi_namespace_devices().
> 
> Best regards,
> baolu
> 
>>
>> Best regards
>> Felix cui-oc
>>
>>
>>
>>
>> -----邮件原件-----
>> 发件人: FelixCui-oc
>> 发送时间: 2020年8月3日 17:02
>> 收件人: 'Lu Baolu' <baolu.lu@linux.intel.com>; Joerg Roedel 
>> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>> 抄送: RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc 
>> <CobeChen-oc@zhaoxin.com>
>> 主题: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in 
>> RMRR
>>
>> Hi  baolu:
>> 		"The namespace devices are enumerated in probe_acpi_namespace_devices().
>> 		It calls iommu_probe_device() to process the enumeration and setup the identity mappings."
>> 		
>> 		This situation only applies to the physical node of the namespaces device as the pci device.
>> 		In fact, the physical node of the namespaces device can be a platform device or NULL.
>> 		If the physical node of the namespaces is a platform device or NULL, it has not actually been enumerated.
>> 		So it is necessary to increase the analysis of the namespaces device in RMRR and establish an identity mapping.
>>
>> Best regards
>> Felix cui
>>
>>
>>
>>
>> -----邮件原件-----
>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>> 发送时间: 2020年8月3日 16:26
>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
>> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc 
>> <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
>> 主题: Re: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in 
>> RMRR
>>
>> On 2020/8/3 14:52, FelixCui-oc wrote:
>>> Hi  baolu ,
>>> 		Yes ,that's right.
>>> 		This patch is to achieve acpi namespace devices to access the RMRR region.
>>
>> The namespace devices are enumerated in probe_acpi_namespace_devices().
>> It calls iommu_probe_device() to process the enumeration and setup the identity mappings. Can you please check why that code doesn't work for you?
>>
>> Best regards,
>> baolu
>>
>>>
>>> Best regards
>>> Felix cui
>>>
>>>
>>>
>>>
>>> -----邮件原件-----
>>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>>> 发送时间: 2020年8月3日 14:19
>>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
>>> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
>>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>>> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc 
>>> <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
>>> 主题: Re: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>>
>>> Hi,
>>>
>>> On 2020/8/3 12:40, FelixCui-oc wrote:
>>>> Hi baolu:
>>>> 		Some ACPI devices need to issue dma requests to access the reserved memory area.
>>>> 		So bios uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
>>>> 		At present, there is no analysis in the kernel that the device scope type in RMRR is ACPI_NAMESPACE_DEVICE.
>>>> 		This patch is mainly to add the analysis of the device scope type ACPI_NAMESPACE_DEVICE in RMRR structure and establish identity mapping for > these ACPI devices.
>>>
>>> So the problem is "although namespace devices in RMRR have been parsed, but the identity map for those devices aren't created. As the result, the namespace devices fail to access the RMRR region."
>>>
>>> Do I understand it right?
>>>
>>> Best regards,
>>> baolu
>>>
>>>> In addition, some naming changes have been made in patch in order to distinguish acpi device from pci device.
>>>> 		You can refer to the description of type in 8.3.1 device scope in vt-d spec.
>>>>
>>>> Best regards
>>>> FelixCui-oc
>>>>
>>>>
>>>>
>>>> -----邮件原件-----
>>>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>>>> 发送时间: 2020年8月3日 10:32
>>>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
>>>> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
>>>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>>>> 抄送: baolu.lu@linux.intel.com; Cobe Chen(BJ-RD) 
>>>> <CobeChen@zhaoxin.com>; Raymond Pang(BJ-RD) 
>>>> <RaymondPang@zhaoxin.com>
>>>> 主题: Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>>>
>>>> Hi,
>>>>
>>>> On 8/2/20 6:07 PM, FelixCuioc wrote:
>>>>> Some ACPI devices require access to the specified reserved memory 
>>>>> region.BIOS report the specified reserved memory region through 
>>>>> RMRR structures.Add analysis of ACPI device in RMRR and establish 
>>>>> identity mapping for ACPI device.
>>>>
>>>> Can you please add more words about the problem you want to solve? Do you mean some RMRRs are not enumerated correctly? Or, enumerated, but not identity mapped?
>>>>
>>>> Nit: add version and change log once you refreshed your patch.
>>>>
>>>>>
>>>>> Reported-by: kernel test robot <lkp@intel.com>
>>>>
>>>> No need to add this. The problem you want to solve through this patch is not reported by lkp.
>>>>
>>>> Best regards,
>>>> baolu
>>>>
>>>>> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
>>>>> ---
>>>>>       drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>>>>>       drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>>>>>       drivers/iommu/iommu.c       |  6 +++
>>>>>       include/linux/dmar.h        | 12 +++++-
>>>>>       include/linux/iommu.h       |  3 ++
>>>>>       5 files changed, 105 insertions(+), 36 deletions(-)
>>>>>
>>>>> diff --git a/drivers/iommu/intel/dmar.c 
>>>>> b/drivers/iommu/intel/dmar.c index 93e6345f3414..024ca38dba12
>>>>> 100644
>>>>> --- a/drivers/iommu/intel/dmar.c
>>>>> +++ b/drivers/iommu/intel/dmar.c
>>>>> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>>>>>       }
>>>>>       
>>>>>       /* Return: > 0 if match found, 0 if no match found, < 0 if 
>>>>> error happens */ -int dmar_insert_dev_scope(struct 
>>>>> dmar_pci_notify_info *info,
>>>>> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>>>>>       			  void *start, void*end, u16 segment,
>>>>>       			  struct dmar_dev_scope *devices,
>>>>>       			  int devices_cnt)
>>>>> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct 
>>>>> dmar_pci_notify_info *info)
>>>>>       
>>>>>       		drhd = container_of(dmaru->hdr,
>>>>>       				    struct acpi_dmar_hardware_unit, header);
>>>>> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
>>>>> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>>>>>       				((void *)drhd) + drhd->header.length,
>>>>>       				dmaru->segment,
>>>>>       				dmaru->devices, dmaru->devices_cnt); @@ -696,48 +696,56 
>>>>> @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
>>>>>       
>>>>>       	return dmaru;
>>>>>       }
>>>>> -
>>>>> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
>>>>> -					      struct acpi_device *adev)
>>>>> +int dmar_acpi_insert_dev_scope(u8 device_number,
>>>>> +				struct acpi_device *adev,
>>>>> +				void *start, void *end,
>>>>> +				struct dmar_dev_scope *devices,
>>>>> +				int devices_cnt)
>>>>>       {
>>>>> -	struct dmar_drhd_unit *dmaru;
>>>>> -	struct acpi_dmar_hardware_unit *drhd;
>>>>>       	struct acpi_dmar_device_scope *scope;
>>>>>       	struct device *tmp;
>>>>>       	int i;
>>>>>       	struct acpi_dmar_pci_path *path;
>>>>>       
>>>>> +	for (; start < end; start += scope->length) {
>>>>> +		scope = start;
>>>>> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>>>> +			continue;
>>>>> +		if (scope->enumeration_id != device_number)
>>>>> +			continue;
>>>>> +		path = (void *)(scope + 1);
>>>>> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
>>>>> +			if (tmp == NULL) {
>>>>> +				devices[i].bus = scope->bus;
>>>>> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
>>>>> +				rcu_assign_pointer(devices[i].dev,
>>>>> +						   get_device(&adev->dev));
>>>>> +				return 1;
>>>>> +			}
>>>>> +		WARN_ON(i >= devices_cnt);
>>>>> +	}
>>>>> +	return 0;
>>>>> +}
>>>>> +static int dmar_acpi_bus_add_dev(u8 device_number, struct 
>>>>> +acpi_device
>>>>> +*adev) {
>>>>> +	struct dmar_drhd_unit *dmaru;
>>>>> +	struct acpi_dmar_hardware_unit *drhd;
>>>>> +	int ret = 0;
>>>>> +
>>>>>       	for_each_drhd_unit(dmaru) {
>>>>>       		drhd = container_of(dmaru->hdr,
>>>>>       				    struct acpi_dmar_hardware_unit,
>>>>>       				    header);
>>>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
>>>>> +						((void *)drhd)+drhd->header.length,
>>>>> +						dmaru->devices, dmaru->devices_cnt);
>>>>> +		if (ret)
>>>>> +			break;
>>>>> +	}
>>>>> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>>>>>       
>>>>> -		for (scope = (void *)(drhd + 1);
>>>>> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
>>>>> -		     scope = ((void *)scope) + scope->length) {
>>>>> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>>>> -				continue;
>>>>> -			if (scope->enumeration_id != device_number)
>>>>> -				continue;
>>>>> +	return ret;
>>>>>       
>>>>> -			path = (void *)(scope + 1);
>>>>> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
>>>>> -				dev_name(&adev->dev), dmaru->reg_base_addr,
>>>>> -				scope->bus, path->device, path->function);
>>>>> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
>>>>> -				if (tmp == NULL) {
>>>>> -					dmaru->devices[i].bus = scope->bus;
>>>>> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
>>>>> -									    path->function);
>>>>> -					rcu_assign_pointer(dmaru->devices[i].dev,
>>>>> -							   get_device(&adev->dev));
>>>>> -					return;
>>>>> -				}
>>>>> -			BUG_ON(i >= dmaru->devices_cnt);
>>>>> -		}
>>>>> -	}
>>>>> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
>>>>> -		device_number, dev_name(&adev->dev));
>>>>>       }
>>>>>       
>>>>>       static int __init dmar_acpi_dev_scope_init(void) @@ -766,7
>>>>> +774,7 @@ static int __init dmar_acpi_dev_scope_init(void)
>>>>>       				       andd->device_name);
>>>>>       				continue;
>>>>>       			}
>>>>> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
>>>>> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>>>>>       		}
>>>>>       	}
>>>>>       	return 0;
>>>>> diff --git a/drivers/iommu/intel/iommu.c 
>>>>> b/drivers/iommu/intel/iommu.c index ca557d351518..be1793415326
>>>>> 100644
>>>>> --- a/drivers/iommu/intel/iommu.c
>>>>> +++ b/drivers/iommu/intel/iommu.c
>>>>> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct
>>>>> pci_dev
>>>>> *dev)
>>>>>       
>>>>>       	return ret;
>>>>>       }
>>>>> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device
>>>>> +*adev) {
>>>>> +	int ret;
>>>>> +	struct dmar_rmrr_unit *rmrru;
>>>>> +	struct acpi_dmar_reserved_memory *rmrr;
>>>>> +
>>>>> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
>>>>> +		rmrr = container_of(rmrru->hdr,
>>>>> +				struct acpi_dmar_reserved_memory,
>>>>> +				header);
>>>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
>>>>> +						((void *)rmrr) + rmrr->header.length,
>>>>> +						rmrru->devices, rmrru->devices_cnt);
>>>>> +		if (ret)
>>>>> +			break;
>>>>> +	}
>>>>> +	return 0;
>>>>> +}
>>>>>       
>>>>>       int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>>       {
>>>>> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>>       		rmrr = container_of(rmrru->hdr,
>>>>>       				    struct acpi_dmar_reserved_memory, header);
>>>>>       		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>>>> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
>>>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>>>>>       				((void *)rmrr) + rmrr->header.length,
>>>>>       				rmrr->segment, rmrru->devices,
>>>>>       				rmrru->devices_cnt);
>>>>> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct
>>>>> dmar_pci_notify_info *info)
>>>>>       
>>>>>       		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>>>>>       		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>>>> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
>>>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>>>>>       					(void *)atsr + atsr->header.length,
>>>>>       					atsr->segment, atsru->devices,
>>>>>       					atsru->devices_cnt);
>>>>> @@ -4779,6 +4797,26 @@ 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) {
>>>>> +	int ret;
>>>>> +	struct iommu_group *group;
>>>>> +
>>>>> +	if (pn_dev == NULL) {
>>>>> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>>>> +		ret = iommu_probe_device(acpi_device);
>>>>> +		if (ret) {
>>>>> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
>>>>> +			return ret;
>>>>> +		}
>>>>> +		return 0;
>>>>> +	}
>>>>> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>>>> +	group = iommu_group_get(pn_dev);
>>>>> +	__acpi_device_create_direct_mappings(group, acpi_device);
>>>>> +
>>>>> +	return 0;
>>>>> +}
>>>>>       
>>>>>       static int __init probe_acpi_namespace_devices(void)
>>>>>       {
>>>>> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>>>       			struct acpi_device_physical_node *pn;
>>>>>       			struct iommu_group *group;
>>>>>       			struct acpi_device *adev;
>>>>> +			struct device *pn_dev = NULL;
>>>>>       
>>>>>       			if (dev->bus != &acpi_bus_type)
>>>>>       				continue;
>>>>> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>>>       					    &adev->physical_node_list, node) {
>>>>>       				group = iommu_group_get(pn->dev);
>>>>>       				if (group) {
>>>>> +					pn_dev = pn->dev;
>>>>>       					iommu_group_put(group);
>>>>>       					continue;
>>>>>       				}
>>>>> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>>>>>       				ret = iommu_probe_device(pn->dev);
>>>>>       				if (ret)
>>>>>       					break;
>>>>> +				pn_dev = pn->dev;
>>>>>       			}
>>>>> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>>>>>       			mutex_unlock(&adev->physical_node_lock);
>>>>>       
>>>>>       			if (ret)
>>>>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
>>>>> 609bd25bf154..4f714a2d5ef7 100644
>>>>> --- a/drivers/iommu/iommu.c
>>>>> +++ b/drivers/iommu/iommu.c
>>>>> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>>>>>       	return false;
>>>>>       }
>>>>>       
>>>>> +void  __acpi_device_create_direct_mappings(struct iommu_group 
>>>>> +*group, struct device *acpi_device) {
>>>>> +	iommu_create_device_direct_mappings(group, acpi_device); } 
>>>>> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
>>>>> +
>>>>>       /**
>>>>>        * iommu_group_add_device - add a device to an iommu group
>>>>>        * @group: the group into which to add the device (reference 
>>>>> should be held) diff --git a/include/linux/dmar.h 
>>>>> b/include/linux/dmar.h index 65565820328a..881ac61a4336 100644
>>>>> --- a/include/linux/dmar.h
>>>>> +++ b/include/linux/dmar.h
>>>>> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>>>>>       				struct dmar_dev_scope **devices, u16 segment);
>>>>>       extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>>>>>       extern void dmar_free_dev_scope(struct dmar_dev_scope 
>>>>> **devices, int *cnt); -extern int dmar_insert_dev_scope(struct 
>>>>> dmar_pci_notify_info *info,
>>>>> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info 
>>>>> +*info,
>>>>>       				 void *start, void*end, u16 segment,
>>>>>       				 struct dmar_dev_scope *devices,
>>>>>       				 int devices_cnt);
>>>>> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
>>>>> +				struct acpi_device *adev, void *start, void *end,
>>>>> +				struct dmar_dev_scope *devices, int devices_cnt);
>>>>> +
>>>>>       extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>>>>>       				 u16 segment, struct dmar_dev_scope *devices,
>>>>>       				 int count);
>>>>> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>>>>>       extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>>>       extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>>>       extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, 
>>>>> bool insert);
>>>>> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
>>>>> +acpi_device *adev);
>>>>>       extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>>>>>       #else /* !CONFIG_INTEL_IOMMU: */
>>>>>       static inline int intel_iommu_init(void) { return -ENODEV; } 
>>>>> @@
>>>>> -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>>>>>       #define	dmar_check_one_atsr		dmar_res_noop
>>>>>       #define	dmar_release_one_atsr		dmar_res_noop
>>>>>       
>>>>> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
>>>>> +acpi_device *adev) {
>>>>> +	return 0;
>>>>> +}
>>>>> +
>>>>>       static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>>       {
>>>>>       	return 0;
>>>>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
>>>>> fee209efb756..9be134775886 100644
>>>>> --- a/include/linux/iommu.h
>>>>> +++ b/include/linux/iommu.h
>>>>> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>>>>>       extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>>>>>       			      unsigned long iova, int flags);
>>>>>       
>>>>> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
>>>>> +						struct device *acpi_device);
>>>>> +
>>>>>       static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>>>>>       {
>>>>>       	if (domain->ops->flush_iotlb_all)
>>>>>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: 答复: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-04  3:11               ` 答复: " FelixCui-oc
@ 2020-08-05  2:56                 ` Lu Baolu
  2020-08-05  7:37                   ` 答复: " FelixCui-oc
  0 siblings, 1 reply; 14+ messages in thread
From: Lu Baolu @ 2020-08-05  2:56 UTC (permalink / raw)
  To: FelixCui-oc, Joerg Roedel, iommu, linux-kernel, David Woodhouse
  Cc: CobeChen-oc

Hi,

On 8/4/20 11:11 AM, FelixCui-oc wrote:
> Hi  baolu ,
> 		When creating a identity mapping for a namespace device in RMRR, you need to add the namespace device to the rmrr->device[] , right?

Yes. You are right.

> 		The dmar_acpi_bus_add_dev() in patch adds the enumeration of the namespace device in RMRR. This is similar to > enumerating pci devices. Do you think this is unreasonable? If it is 
unreasonable, please tell me why it is unreasonable.

It looks reasonable. Thanks for the explanation.

But I don't think we need to add acpi_device_create_direct_mappings()
since the rmrr identity mapping is already done in the iommu core.

Best regards,
baolu

> 			
> Best regards
> Felix cui-oc
> 
> 
> 
> -----邮件原件-----
> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
> 发送时间: 2020年8月4日 9:12
> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
> 主题: Re: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
> 
> Hi Felix,
> 
> On 2020/8/3 17:41, FelixCui-oc wrote:
>> Hi baolu,
>> 		 dmar_acpi_dev_scope_init() parse ANDD structure and enumerated namespaces device in DRHD.
> 
> Yes.
> 
>> 		 But the namespace device in RMRR is not enumerated, right?
> 
> It should be probed in probe_acpi_namespace_devices().
> 
> Best regards,
> baolu
> 
>>
>> Best regards
>> Felix cui-oc
>>
>>
>>
>>
>> -----邮件原件-----
>> 发件人: FelixCui-oc
>> 发送时间: 2020年8月3日 17:02
>> 收件人: 'Lu Baolu' <baolu.lu@linux.intel.com>; Joerg Roedel
>> <joro@8bytes.org>; iommu@lists.linux-foundation.org;
>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>> 抄送: RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc
>> <CobeChen-oc@zhaoxin.com>
>> 主题: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>
>> Hi  baolu:
>> 		"The namespace devices are enumerated in probe_acpi_namespace_devices().
>> 		It calls iommu_probe_device() to process the enumeration and setup the identity mappings."
>> 		
>> 		This situation only applies to the physical node of the namespaces device as the pci device.
>> 		In fact, the physical node of the namespaces device can be a platform device or NULL.
>> 		If the physical node of the namespaces is a platform device or NULL, it has not actually been enumerated.
>> 		So it is necessary to increase the analysis of the namespaces device in RMRR and establish an identity mapping.
>>
>> Best regards
>> Felix cui
>>
>>
>>
>>
>> -----邮件原件-----
>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>> 发送时间: 2020年8月3日 16:26
>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel
>> <joro@8bytes.org>; iommu@lists.linux-foundation.org;
>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc
>> <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
>> 主题: Re: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>
>> On 2020/8/3 14:52, FelixCui-oc wrote:
>>> Hi  baolu ,
>>> 		Yes ,that's right.
>>> 		This patch is to achieve acpi namespace devices to access the RMRR region.
>>
>> The namespace devices are enumerated in probe_acpi_namespace_devices().
>> It calls iommu_probe_device() to process the enumeration and setup the identity mappings. Can you please check why that code doesn't work for you?
>>
>> Best regards,
>> baolu
>>
>>>
>>> Best regards
>>> Felix cui
>>>
>>>
>>>
>>>
>>> -----邮件原件-----
>>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>>> 发送时间: 2020年8月3日 14:19
>>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel
>>> <joro@8bytes.org>; iommu@lists.linux-foundation.org;
>>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>>> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc
>>> <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
>>> 主题: Re: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>>
>>> Hi,
>>>
>>> On 2020/8/3 12:40, FelixCui-oc wrote:
>>>> Hi baolu:
>>>> 		Some ACPI devices need to issue dma requests to access the reserved memory area.
>>>> 		So bios uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
>>>> 		At present, there is no analysis in the kernel that the device scope type in RMRR is ACPI_NAMESPACE_DEVICE.
>>>> 		This patch is mainly to add the analysis of the device scope type ACPI_NAMESPACE_DEVICE in RMRR structure and establish identity mapping for > these ACPI devices.
>>>
>>> So the problem is "although namespace devices in RMRR have been parsed, but the identity map for those devices aren't created. As the result, the namespace devices fail to access the RMRR region."
>>>
>>> Do I understand it right?
>>>
>>> Best regards,
>>> baolu
>>>
>>>> In addition, some naming changes have been made in patch in order to distinguish acpi device from pci device.
>>>> 		You can refer to the description of type in 8.3.1 device scope in vt-d spec.
>>>>
>>>> Best regards
>>>> FelixCui-oc
>>>>
>>>>
>>>>
>>>> -----邮件原件-----
>>>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>>>> 发送时间: 2020年8月3日 10:32
>>>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel
>>>> <joro@8bytes.org>; iommu@lists.linux-foundation.org;
>>>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>>>> 抄送: baolu.lu@linux.intel.com; Cobe Chen(BJ-RD)
>>>> <CobeChen@zhaoxin.com>; Raymond Pang(BJ-RD)
>>>> <RaymondPang@zhaoxin.com>
>>>> 主题: Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>>>
>>>> Hi,
>>>>
>>>> On 8/2/20 6:07 PM, FelixCuioc wrote:
>>>>> Some ACPI devices require access to the specified reserved memory
>>>>> region.BIOS report the specified reserved memory region through
>>>>> RMRR structures.Add analysis of ACPI device in RMRR and establish
>>>>> identity mapping for ACPI device.
>>>>
>>>> Can you please add more words about the problem you want to solve? Do you mean some RMRRs are not enumerated correctly? Or, enumerated, but not identity mapped?
>>>>
>>>> Nit: add version and change log once you refreshed your patch.
>>>>
>>>>>
>>>>> Reported-by: kernel test robot <lkp@intel.com>
>>>>
>>>> No need to add this. The problem you want to solve through this patch is not reported by lkp.
>>>>
>>>> Best regards,
>>>> baolu
>>>>
>>>>> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
>>>>> ---
>>>>>       drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>>>>>       drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>>>>>       drivers/iommu/iommu.c       |  6 +++
>>>>>       include/linux/dmar.h        | 12 +++++-
>>>>>       include/linux/iommu.h       |  3 ++
>>>>>       5 files changed, 105 insertions(+), 36 deletions(-)
>>>>>
>>>>> diff --git a/drivers/iommu/intel/dmar.c
>>>>> b/drivers/iommu/intel/dmar.c index 93e6345f3414..024ca38dba12
>>>>> 100644
>>>>> --- a/drivers/iommu/intel/dmar.c
>>>>> +++ b/drivers/iommu/intel/dmar.c
>>>>> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>>>>>       }
>>>>>       
>>>>>       /* Return: > 0 if match found, 0 if no match found, < 0 if
>>>>> error happens */ -int dmar_insert_dev_scope(struct
>>>>> dmar_pci_notify_info *info,
>>>>> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>>>>>       			  void *start, void*end, u16 segment,
>>>>>       			  struct dmar_dev_scope *devices,
>>>>>       			  int devices_cnt)
>>>>> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct
>>>>> dmar_pci_notify_info *info)
>>>>>       
>>>>>       		drhd = container_of(dmaru->hdr,
>>>>>       				    struct acpi_dmar_hardware_unit, header);
>>>>> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
>>>>> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>>>>>       				((void *)drhd) + drhd->header.length,
>>>>>       				dmaru->segment,
>>>>>       				dmaru->devices, dmaru->devices_cnt); @@ -696,48 +696,56 @@
>>>>> dmar_find_matched_drhd_unit(struct pci_dev *dev)
>>>>>       
>>>>>       	return dmaru;
>>>>>       }
>>>>> -
>>>>> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
>>>>> -					      struct acpi_device *adev)
>>>>> +int dmar_acpi_insert_dev_scope(u8 device_number,
>>>>> +				struct acpi_device *adev,
>>>>> +				void *start, void *end,
>>>>> +				struct dmar_dev_scope *devices,
>>>>> +				int devices_cnt)
>>>>>       {
>>>>> -	struct dmar_drhd_unit *dmaru;
>>>>> -	struct acpi_dmar_hardware_unit *drhd;
>>>>>       	struct acpi_dmar_device_scope *scope;
>>>>>       	struct device *tmp;
>>>>>       	int i;
>>>>>       	struct acpi_dmar_pci_path *path;
>>>>>       
>>>>> +	for (; start < end; start += scope->length) {
>>>>> +		scope = start;
>>>>> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>>>> +			continue;
>>>>> +		if (scope->enumeration_id != device_number)
>>>>> +			continue;
>>>>> +		path = (void *)(scope + 1);
>>>>> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
>>>>> +			if (tmp == NULL) {
>>>>> +				devices[i].bus = scope->bus;
>>>>> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
>>>>> +				rcu_assign_pointer(devices[i].dev,
>>>>> +						   get_device(&adev->dev));
>>>>> +				return 1;
>>>>> +			}
>>>>> +		WARN_ON(i >= devices_cnt);
>>>>> +	}
>>>>> +	return 0;
>>>>> +}
>>>>> +static int dmar_acpi_bus_add_dev(u8 device_number, struct
>>>>> +acpi_device
>>>>> +*adev) {
>>>>> +	struct dmar_drhd_unit *dmaru;
>>>>> +	struct acpi_dmar_hardware_unit *drhd;
>>>>> +	int ret = 0;
>>>>> +
>>>>>       	for_each_drhd_unit(dmaru) {
>>>>>       		drhd = container_of(dmaru->hdr,
>>>>>       				    struct acpi_dmar_hardware_unit,
>>>>>       				    header);
>>>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
>>>>> +						((void *)drhd)+drhd->header.length,
>>>>> +						dmaru->devices, dmaru->devices_cnt);
>>>>> +		if (ret)
>>>>> +			break;
>>>>> +	}
>>>>> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>>>>>       
>>>>> -		for (scope = (void *)(drhd + 1);
>>>>> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
>>>>> -		     scope = ((void *)scope) + scope->length) {
>>>>> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>>>> -				continue;
>>>>> -			if (scope->enumeration_id != device_number)
>>>>> -				continue;
>>>>> +	return ret;
>>>>>       
>>>>> -			path = (void *)(scope + 1);
>>>>> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
>>>>> -				dev_name(&adev->dev), dmaru->reg_base_addr,
>>>>> -				scope->bus, path->device, path->function);
>>>>> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
>>>>> -				if (tmp == NULL) {
>>>>> -					dmaru->devices[i].bus = scope->bus;
>>>>> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
>>>>> -									    path->function);
>>>>> -					rcu_assign_pointer(dmaru->devices[i].dev,
>>>>> -							   get_device(&adev->dev));
>>>>> -					return;
>>>>> -				}
>>>>> -			BUG_ON(i >= dmaru->devices_cnt);
>>>>> -		}
>>>>> -	}
>>>>> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
>>>>> -		device_number, dev_name(&adev->dev));
>>>>>       }
>>>>>       
>>>>>       static int __init dmar_acpi_dev_scope_init(void) @@ -766,7
>>>>> +774,7 @@ static int __init dmar_acpi_dev_scope_init(void)
>>>>>       				       andd->device_name);
>>>>>       				continue;
>>>>>       			}
>>>>> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
>>>>> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>>>>>       		}
>>>>>       	}
>>>>>       	return 0;
>>>>> diff --git a/drivers/iommu/intel/iommu.c
>>>>> b/drivers/iommu/intel/iommu.c index ca557d351518..be1793415326
>>>>> 100644
>>>>> --- a/drivers/iommu/intel/iommu.c
>>>>> +++ b/drivers/iommu/intel/iommu.c
>>>>> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct
>>>>> pci_dev
>>>>> *dev)
>>>>>       
>>>>>       	return ret;
>>>>>       }
>>>>> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device
>>>>> +*adev) {
>>>>> +	int ret;
>>>>> +	struct dmar_rmrr_unit *rmrru;
>>>>> +	struct acpi_dmar_reserved_memory *rmrr;
>>>>> +
>>>>> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
>>>>> +		rmrr = container_of(rmrru->hdr,
>>>>> +				struct acpi_dmar_reserved_memory,
>>>>> +				header);
>>>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
>>>>> +						((void *)rmrr) + rmrr->header.length,
>>>>> +						rmrru->devices, rmrru->devices_cnt);
>>>>> +		if (ret)
>>>>> +			break;
>>>>> +	}
>>>>> +	return 0;
>>>>> +}
>>>>>       
>>>>>       int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>>       {
>>>>> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>>       		rmrr = container_of(rmrru->hdr,
>>>>>       				    struct acpi_dmar_reserved_memory, header);
>>>>>       		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>>>> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
>>>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>>>>>       				((void *)rmrr) + rmrr->header.length,
>>>>>       				rmrr->segment, rmrru->devices,
>>>>>       				rmrru->devices_cnt);
>>>>> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct
>>>>> dmar_pci_notify_info *info)
>>>>>       
>>>>>       		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>>>>>       		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>>>> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
>>>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>>>>>       					(void *)atsr + atsr->header.length,
>>>>>       					atsr->segment, atsru->devices,
>>>>>       					atsru->devices_cnt);
>>>>> @@ -4779,6 +4797,26 @@ 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) {
>>>>> +	int ret;
>>>>> +	struct iommu_group *group;
>>>>> +
>>>>> +	if (pn_dev == NULL) {
>>>>> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>>>> +		ret = iommu_probe_device(acpi_device);
>>>>> +		if (ret) {
>>>>> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
>>>>> +			return ret;
>>>>> +		}
>>>>> +		return 0;
>>>>> +	}
>>>>> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>>>> +	group = iommu_group_get(pn_dev);
>>>>> +	__acpi_device_create_direct_mappings(group, acpi_device);
>>>>> +
>>>>> +	return 0;
>>>>> +}
>>>>>       
>>>>>       static int __init probe_acpi_namespace_devices(void)
>>>>>       {
>>>>> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>>>       			struct acpi_device_physical_node *pn;
>>>>>       			struct iommu_group *group;
>>>>>       			struct acpi_device *adev;
>>>>> +			struct device *pn_dev = NULL;
>>>>>       
>>>>>       			if (dev->bus != &acpi_bus_type)
>>>>>       				continue;
>>>>> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>>>       					    &adev->physical_node_list, node) {
>>>>>       				group = iommu_group_get(pn->dev);
>>>>>       				if (group) {
>>>>> +					pn_dev = pn->dev;
>>>>>       					iommu_group_put(group);
>>>>>       					continue;
>>>>>       				}
>>>>> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>>>>>       				ret = iommu_probe_device(pn->dev);
>>>>>       				if (ret)
>>>>>       					break;
>>>>> +				pn_dev = pn->dev;
>>>>>       			}
>>>>> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>>>>>       			mutex_unlock(&adev->physical_node_lock);
>>>>>       
>>>>>       			if (ret)
>>>>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
>>>>> 609bd25bf154..4f714a2d5ef7 100644
>>>>> --- a/drivers/iommu/iommu.c
>>>>> +++ b/drivers/iommu/iommu.c
>>>>> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>>>>>       	return false;
>>>>>       }
>>>>>       
>>>>> +void  __acpi_device_create_direct_mappings(struct iommu_group
>>>>> +*group, struct device *acpi_device) {
>>>>> +	iommu_create_device_direct_mappings(group, acpi_device); }
>>>>> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
>>>>> +
>>>>>       /**
>>>>>        * iommu_group_add_device - add a device to an iommu group
>>>>>        * @group: the group into which to add the device (reference
>>>>> should be held) diff --git a/include/linux/dmar.h
>>>>> b/include/linux/dmar.h index 65565820328a..881ac61a4336 100644
>>>>> --- a/include/linux/dmar.h
>>>>> +++ b/include/linux/dmar.h
>>>>> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>>>>>       				struct dmar_dev_scope **devices, u16 segment);
>>>>>       extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>>>>>       extern void dmar_free_dev_scope(struct dmar_dev_scope
>>>>> **devices, int *cnt); -extern int dmar_insert_dev_scope(struct
>>>>> dmar_pci_notify_info *info,
>>>>> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info
>>>>> +*info,
>>>>>       				 void *start, void*end, u16 segment,
>>>>>       				 struct dmar_dev_scope *devices,
>>>>>       				 int devices_cnt);
>>>>> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
>>>>> +				struct acpi_device *adev, void *start, void *end,
>>>>> +				struct dmar_dev_scope *devices, int devices_cnt);
>>>>> +
>>>>>       extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>>>>>       				 u16 segment, struct dmar_dev_scope *devices,
>>>>>       				 int count);
>>>>> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>>>>>       extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>>>       extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>>>       extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru,
>>>>> bool insert);
>>>>> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct
>>>>> +acpi_device *adev);
>>>>>       extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>>>>>       #else /* !CONFIG_INTEL_IOMMU: */
>>>>>       static inline int intel_iommu_init(void) { return -ENODEV; }
>>>>> @@
>>>>> -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>>>>>       #define	dmar_check_one_atsr		dmar_res_noop
>>>>>       #define	dmar_release_one_atsr		dmar_res_noop
>>>>>       
>>>>> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct
>>>>> +acpi_device *adev) {
>>>>> +	return 0;
>>>>> +}
>>>>> +
>>>>>       static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>>       {
>>>>>       	return 0;
>>>>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
>>>>> fee209efb756..9be134775886 100644
>>>>> --- a/include/linux/iommu.h
>>>>> +++ b/include/linux/iommu.h
>>>>> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>>>>>       extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>>>>>       			      unsigned long iova, int flags);
>>>>>       
>>>>> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
>>>>> +						struct device *acpi_device);
>>>>> +
>>>>>       static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>>>>>       {
>>>>>       	if (domain->ops->flush_iotlb_all)
>>>>>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* 答复: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-04  1:11             ` Lu Baolu
@ 2020-08-04  3:11               ` FelixCui-oc
  2020-08-05  2:56                 ` Lu Baolu
  0 siblings, 1 reply; 14+ messages in thread
From: FelixCui-oc @ 2020-08-04  3:11 UTC (permalink / raw)
  To: Lu Baolu, Joerg Roedel, iommu, linux-kernel, David Woodhouse; +Cc: CobeChen-oc

Hi  baolu ,
		When creating a identity mapping for a namespace device in RMRR, you need to add the namespace device to the rmrr->device[] , right?
		The dmar_acpi_bus_add_dev() in patch adds the enumeration of the namespace device in RMRR. This is similar to 
enumerating pci devices. Do you think this is unreasonable? If it is unreasonable, please tell me why it is unreasonable.
			
Best regards
Felix cui-oc



-----邮件原件-----
发件人: Lu Baolu <baolu.lu@linux.intel.com> 
发送时间: 2020年8月4日 9:12
收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
抄送: baolu.lu@linux.intel.com; RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
主题: Re: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR

Hi Felix,

On 2020/8/3 17:41, FelixCui-oc wrote:
> Hi baolu,
> 		 dmar_acpi_dev_scope_init() parse ANDD structure and enumerated namespaces device in DRHD.

Yes.

> 		 But the namespace device in RMRR is not enumerated, right?

It should be probed in probe_acpi_namespace_devices().

Best regards,
baolu

> 
> Best regards
> Felix cui-oc
> 
> 
> 
> 
> -----邮件原件-----
> 发件人: FelixCui-oc
> 发送时间: 2020年8月3日 17:02
> 收件人: 'Lu Baolu' <baolu.lu@linux.intel.com>; Joerg Roedel 
> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc 
> <CobeChen-oc@zhaoxin.com>
> 主题: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
> 
> Hi  baolu:
> 		"The namespace devices are enumerated in probe_acpi_namespace_devices().
> 		It calls iommu_probe_device() to process the enumeration and setup the identity mappings."
> 		
> 		This situation only applies to the physical node of the namespaces device as the pci device.
> 		In fact, the physical node of the namespaces device can be a platform device or NULL.
> 		If the physical node of the namespaces is a platform device or NULL, it has not actually been enumerated.
> 		So it is necessary to increase the analysis of the namespaces device in RMRR and establish an identity mapping.
> 
> Best regards
> Felix cui
> 
> 
> 
> 
> -----邮件原件-----
> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
> 发送时间: 2020年8月3日 16:26
> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc 
> <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
> 主题: Re: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
> 
> On 2020/8/3 14:52, FelixCui-oc wrote:
>> Hi  baolu ,
>> 		Yes ,that's right.
>> 		This patch is to achieve acpi namespace devices to access the RMRR region.
> 
> The namespace devices are enumerated in probe_acpi_namespace_devices().
> It calls iommu_probe_device() to process the enumeration and setup the identity mappings. Can you please check why that code doesn't work for you?
> 
> Best regards,
> baolu
> 
>>
>> Best regards
>> Felix cui
>>
>>
>>
>>
>> -----邮件原件-----
>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>> 发送时间: 2020年8月3日 14:19
>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
>> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc 
>> <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
>> 主题: Re: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>
>> Hi,
>>
>> On 2020/8/3 12:40, FelixCui-oc wrote:
>>> Hi baolu:
>>> 		Some ACPI devices need to issue dma requests to access the reserved memory area.
>>> 		So bios uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
>>> 		At present, there is no analysis in the kernel that the device scope type in RMRR is ACPI_NAMESPACE_DEVICE.
>>> 		This patch is mainly to add the analysis of the device scope type ACPI_NAMESPACE_DEVICE in RMRR structure and establish identity mapping for > these ACPI devices.
>>
>> So the problem is "although namespace devices in RMRR have been parsed, but the identity map for those devices aren't created. As the result, the namespace devices fail to access the RMRR region."
>>
>> Do I understand it right?
>>
>> Best regards,
>> baolu
>>
>>> In addition, some naming changes have been made in patch in order to distinguish acpi device from pci device.
>>> 		You can refer to the description of type in 8.3.1 device scope in vt-d spec.
>>>
>>> Best regards
>>> FelixCui-oc
>>>
>>>
>>>
>>> -----邮件原件-----
>>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>>> 发送时间: 2020年8月3日 10:32
>>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
>>> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
>>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>>> 抄送: baolu.lu@linux.intel.com; Cobe Chen(BJ-RD) 
>>> <CobeChen@zhaoxin.com>; Raymond Pang(BJ-RD) 
>>> <RaymondPang@zhaoxin.com>
>>> 主题: Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>>
>>> Hi,
>>>
>>> On 8/2/20 6:07 PM, FelixCuioc wrote:
>>>> Some ACPI devices require access to the specified reserved memory 
>>>> region.BIOS report the specified reserved memory region through 
>>>> RMRR structures.Add analysis of ACPI device in RMRR and establish 
>>>> identity mapping for ACPI device.
>>>
>>> Can you please add more words about the problem you want to solve? Do you mean some RMRRs are not enumerated correctly? Or, enumerated, but not identity mapped?
>>>
>>> Nit: add version and change log once you refreshed your patch.
>>>
>>>>
>>>> Reported-by: kernel test robot <lkp@intel.com>
>>>
>>> No need to add this. The problem you want to solve through this patch is not reported by lkp.
>>>
>>> Best regards,
>>> baolu
>>>
>>>> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
>>>> ---
>>>>      drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>>>>      drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>>>>      drivers/iommu/iommu.c       |  6 +++
>>>>      include/linux/dmar.h        | 12 +++++-
>>>>      include/linux/iommu.h       |  3 ++
>>>>      5 files changed, 105 insertions(+), 36 deletions(-)
>>>>
>>>> diff --git a/drivers/iommu/intel/dmar.c 
>>>> b/drivers/iommu/intel/dmar.c index 93e6345f3414..024ca38dba12 
>>>> 100644
>>>> --- a/drivers/iommu/intel/dmar.c
>>>> +++ b/drivers/iommu/intel/dmar.c
>>>> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>>>>      }
>>>>      
>>>>      /* Return: > 0 if match found, 0 if no match found, < 0 if 
>>>> error happens */ -int dmar_insert_dev_scope(struct 
>>>> dmar_pci_notify_info *info,
>>>> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>>>>      			  void *start, void*end, u16 segment,
>>>>      			  struct dmar_dev_scope *devices,
>>>>      			  int devices_cnt)
>>>> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct 
>>>> dmar_pci_notify_info *info)
>>>>      
>>>>      		drhd = container_of(dmaru->hdr,
>>>>      				    struct acpi_dmar_hardware_unit, header);
>>>> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
>>>> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>>>>      				((void *)drhd) + drhd->header.length,
>>>>      				dmaru->segment,
>>>>      				dmaru->devices, dmaru->devices_cnt); @@ -696,48 +696,56 @@ 
>>>> dmar_find_matched_drhd_unit(struct pci_dev *dev)
>>>>      
>>>>      	return dmaru;
>>>>      }
>>>> -
>>>> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
>>>> -					      struct acpi_device *adev)
>>>> +int dmar_acpi_insert_dev_scope(u8 device_number,
>>>> +				struct acpi_device *adev,
>>>> +				void *start, void *end,
>>>> +				struct dmar_dev_scope *devices,
>>>> +				int devices_cnt)
>>>>      {
>>>> -	struct dmar_drhd_unit *dmaru;
>>>> -	struct acpi_dmar_hardware_unit *drhd;
>>>>      	struct acpi_dmar_device_scope *scope;
>>>>      	struct device *tmp;
>>>>      	int i;
>>>>      	struct acpi_dmar_pci_path *path;
>>>>      
>>>> +	for (; start < end; start += scope->length) {
>>>> +		scope = start;
>>>> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>>> +			continue;
>>>> +		if (scope->enumeration_id != device_number)
>>>> +			continue;
>>>> +		path = (void *)(scope + 1);
>>>> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
>>>> +			if (tmp == NULL) {
>>>> +				devices[i].bus = scope->bus;
>>>> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
>>>> +				rcu_assign_pointer(devices[i].dev,
>>>> +						   get_device(&adev->dev));
>>>> +				return 1;
>>>> +			}
>>>> +		WARN_ON(i >= devices_cnt);
>>>> +	}
>>>> +	return 0;
>>>> +}
>>>> +static int dmar_acpi_bus_add_dev(u8 device_number, struct 
>>>> +acpi_device
>>>> +*adev) {
>>>> +	struct dmar_drhd_unit *dmaru;
>>>> +	struct acpi_dmar_hardware_unit *drhd;
>>>> +	int ret = 0;
>>>> +
>>>>      	for_each_drhd_unit(dmaru) {
>>>>      		drhd = container_of(dmaru->hdr,
>>>>      				    struct acpi_dmar_hardware_unit,
>>>>      				    header);
>>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
>>>> +						((void *)drhd)+drhd->header.length,
>>>> +						dmaru->devices, dmaru->devices_cnt);
>>>> +		if (ret)
>>>> +			break;
>>>> +	}
>>>> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>>>>      
>>>> -		for (scope = (void *)(drhd + 1);
>>>> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
>>>> -		     scope = ((void *)scope) + scope->length) {
>>>> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>>> -				continue;
>>>> -			if (scope->enumeration_id != device_number)
>>>> -				continue;
>>>> +	return ret;
>>>>      
>>>> -			path = (void *)(scope + 1);
>>>> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
>>>> -				dev_name(&adev->dev), dmaru->reg_base_addr,
>>>> -				scope->bus, path->device, path->function);
>>>> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
>>>> -				if (tmp == NULL) {
>>>> -					dmaru->devices[i].bus = scope->bus;
>>>> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
>>>> -									    path->function);
>>>> -					rcu_assign_pointer(dmaru->devices[i].dev,
>>>> -							   get_device(&adev->dev));
>>>> -					return;
>>>> -				}
>>>> -			BUG_ON(i >= dmaru->devices_cnt);
>>>> -		}
>>>> -	}
>>>> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
>>>> -		device_number, dev_name(&adev->dev));
>>>>      }
>>>>      
>>>>      static int __init dmar_acpi_dev_scope_init(void) @@ -766,7
>>>> +774,7 @@ static int __init dmar_acpi_dev_scope_init(void)
>>>>      				       andd->device_name);
>>>>      				continue;
>>>>      			}
>>>> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
>>>> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>>>>      		}
>>>>      	}
>>>>      	return 0;
>>>> diff --git a/drivers/iommu/intel/iommu.c 
>>>> b/drivers/iommu/intel/iommu.c index ca557d351518..be1793415326
>>>> 100644
>>>> --- a/drivers/iommu/intel/iommu.c
>>>> +++ b/drivers/iommu/intel/iommu.c
>>>> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct
>>>> pci_dev
>>>> *dev)
>>>>      
>>>>      	return ret;
>>>>      }
>>>> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device
>>>> +*adev) {
>>>> +	int ret;
>>>> +	struct dmar_rmrr_unit *rmrru;
>>>> +	struct acpi_dmar_reserved_memory *rmrr;
>>>> +
>>>> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
>>>> +		rmrr = container_of(rmrru->hdr,
>>>> +				struct acpi_dmar_reserved_memory,
>>>> +				header);
>>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
>>>> +						((void *)rmrr) + rmrr->header.length,
>>>> +						rmrru->devices, rmrru->devices_cnt);
>>>> +		if (ret)
>>>> +			break;
>>>> +	}
>>>> +	return 0;
>>>> +}
>>>>      
>>>>      int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>      {
>>>> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>      		rmrr = container_of(rmrru->hdr,
>>>>      				    struct acpi_dmar_reserved_memory, header);
>>>>      		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>>> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
>>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>>>>      				((void *)rmrr) + rmrr->header.length,
>>>>      				rmrr->segment, rmrru->devices,
>>>>      				rmrru->devices_cnt);
>>>> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct
>>>> dmar_pci_notify_info *info)
>>>>      
>>>>      		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>>>>      		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>>> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
>>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>>>>      					(void *)atsr + atsr->header.length,
>>>>      					atsr->segment, atsru->devices,
>>>>      					atsru->devices_cnt);
>>>> @@ -4779,6 +4797,26 @@ 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) {
>>>> +	int ret;
>>>> +	struct iommu_group *group;
>>>> +
>>>> +	if (pn_dev == NULL) {
>>>> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>>> +		ret = iommu_probe_device(acpi_device);
>>>> +		if (ret) {
>>>> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
>>>> +			return ret;
>>>> +		}
>>>> +		return 0;
>>>> +	}
>>>> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>>> +	group = iommu_group_get(pn_dev);
>>>> +	__acpi_device_create_direct_mappings(group, acpi_device);
>>>> +
>>>> +	return 0;
>>>> +}
>>>>      
>>>>      static int __init probe_acpi_namespace_devices(void)
>>>>      {
>>>> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>>      			struct acpi_device_physical_node *pn;
>>>>      			struct iommu_group *group;
>>>>      			struct acpi_device *adev;
>>>> +			struct device *pn_dev = NULL;
>>>>      
>>>>      			if (dev->bus != &acpi_bus_type)
>>>>      				continue;
>>>> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>>      					    &adev->physical_node_list, node) {
>>>>      				group = iommu_group_get(pn->dev);
>>>>      				if (group) {
>>>> +					pn_dev = pn->dev;
>>>>      					iommu_group_put(group);
>>>>      					continue;
>>>>      				}
>>>> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>>>>      				ret = iommu_probe_device(pn->dev);
>>>>      				if (ret)
>>>>      					break;
>>>> +				pn_dev = pn->dev;
>>>>      			}
>>>> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>>>>      			mutex_unlock(&adev->physical_node_lock);
>>>>      
>>>>      			if (ret)
>>>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
>>>> 609bd25bf154..4f714a2d5ef7 100644
>>>> --- a/drivers/iommu/iommu.c
>>>> +++ b/drivers/iommu/iommu.c
>>>> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>>>>      	return false;
>>>>      }
>>>>      
>>>> +void  __acpi_device_create_direct_mappings(struct iommu_group 
>>>> +*group, struct device *acpi_device) {
>>>> +	iommu_create_device_direct_mappings(group, acpi_device); } 
>>>> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
>>>> +
>>>>      /**
>>>>       * iommu_group_add_device - add a device to an iommu group
>>>>       * @group: the group into which to add the device (reference 
>>>> should be held) diff --git a/include/linux/dmar.h 
>>>> b/include/linux/dmar.h index 65565820328a..881ac61a4336 100644
>>>> --- a/include/linux/dmar.h
>>>> +++ b/include/linux/dmar.h
>>>> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>>>>      				struct dmar_dev_scope **devices, u16 segment);
>>>>      extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>>>>      extern void dmar_free_dev_scope(struct dmar_dev_scope 
>>>> **devices, int *cnt); -extern int dmar_insert_dev_scope(struct 
>>>> dmar_pci_notify_info *info,
>>>> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info 
>>>> +*info,
>>>>      				 void *start, void*end, u16 segment,
>>>>      				 struct dmar_dev_scope *devices,
>>>>      				 int devices_cnt);
>>>> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
>>>> +				struct acpi_device *adev, void *start, void *end,
>>>> +				struct dmar_dev_scope *devices, int devices_cnt);
>>>> +
>>>>      extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>>>>      				 u16 segment, struct dmar_dev_scope *devices,
>>>>      				 int count);
>>>> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>>>>      extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>>      extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>>      extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, 
>>>> bool insert);
>>>> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
>>>> +acpi_device *adev);
>>>>      extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>>>>      #else /* !CONFIG_INTEL_IOMMU: */
>>>>      static inline int intel_iommu_init(void) { return -ENODEV; } 
>>>> @@
>>>> -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>>>>      #define	dmar_check_one_atsr		dmar_res_noop
>>>>      #define	dmar_release_one_atsr		dmar_res_noop
>>>>      
>>>> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
>>>> +acpi_device *adev) {
>>>> +	return 0;
>>>> +}
>>>> +
>>>>      static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>      {
>>>>      	return 0;
>>>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
>>>> fee209efb756..9be134775886 100644
>>>> --- a/include/linux/iommu.h
>>>> +++ b/include/linux/iommu.h
>>>> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>>>>      extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>>>>      			      unsigned long iova, int flags);
>>>>      
>>>> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
>>>> +						struct device *acpi_device);
>>>> +
>>>>      static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>>>>      {
>>>>      	if (domain->ops->flush_iotlb_all)
>>>>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-03  9:41           ` FelixCui-oc
@ 2020-08-04  1:11             ` Lu Baolu
  2020-08-04  3:11               ` 答复: " FelixCui-oc
  0 siblings, 1 reply; 14+ messages in thread
From: Lu Baolu @ 2020-08-04  1:11 UTC (permalink / raw)
  To: FelixCui-oc, Joerg Roedel, iommu, linux-kernel, David Woodhouse
  Cc: CobeChen-oc

Hi Felix,

On 2020/8/3 17:41, FelixCui-oc wrote:
> Hi baolu,
> 		 dmar_acpi_dev_scope_init() parse ANDD structure and enumerated namespaces device in DRHD.

Yes.

> 		 But the namespace device in RMRR is not enumerated, right?

It should be probed in probe_acpi_namespace_devices().

Best regards,
baolu

> 
> Best regards
> Felix cui-oc
> 
> 
> 
> 
> -----邮件原件-----
> 发件人: FelixCui-oc
> 发送时间: 2020年8月3日 17:02
> 收件人: 'Lu Baolu' <baolu.lu@linux.intel.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
> 主题: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
> 
> Hi  baolu:
> 		"The namespace devices are enumerated in probe_acpi_namespace_devices().
> 		It calls iommu_probe_device() to process the enumeration and setup the identity mappings."
> 		
> 		This situation only applies to the physical node of the namespaces device as the pci device.
> 		In fact, the physical node of the namespaces device can be a platform device or NULL.
> 		If the physical node of the namespaces is a platform device or NULL, it has not actually been enumerated.
> 		So it is necessary to increase the analysis of the namespaces device in RMRR and establish an identity mapping.
> 
> Best regards
> Felix cui
> 
> 
> 
> 
> -----邮件原件-----
> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
> 发送时间: 2020年8月3日 16:26
> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
> 主题: Re: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
> 
> On 2020/8/3 14:52, FelixCui-oc wrote:
>> Hi  baolu ,
>> 		Yes ,that's right.
>> 		This patch is to achieve acpi namespace devices to access the RMRR region.
> 
> The namespace devices are enumerated in probe_acpi_namespace_devices().
> It calls iommu_probe_device() to process the enumeration and setup the identity mappings. Can you please check why that code doesn't work for you?
> 
> Best regards,
> baolu
> 
>>
>> Best regards
>> Felix cui
>>
>>
>>
>>
>> -----邮件原件-----
>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>> 发送时间: 2020年8月3日 14:19
>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel
>> <joro@8bytes.org>; iommu@lists.linux-foundation.org;
>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc
>> <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
>> 主题: Re: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>
>> Hi,
>>
>> On 2020/8/3 12:40, FelixCui-oc wrote:
>>> Hi baolu:
>>> 		Some ACPI devices need to issue dma requests to access the reserved memory area.
>>> 		So bios uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
>>> 		At present, there is no analysis in the kernel that the device scope type in RMRR is ACPI_NAMESPACE_DEVICE.
>>> 		This patch is mainly to add the analysis of the device scope type ACPI_NAMESPACE_DEVICE in RMRR structure and establish identity mapping for > these ACPI devices.
>>
>> So the problem is "although namespace devices in RMRR have been parsed, but the identity map for those devices aren't created. As the result, the namespace devices fail to access the RMRR region."
>>
>> Do I understand it right?
>>
>> Best regards,
>> baolu
>>
>>> In addition, some naming changes have been made in patch in order to distinguish acpi device from pci device.
>>> 		You can refer to the description of type in 8.3.1 device scope in vt-d spec.
>>>
>>> Best regards
>>> FelixCui-oc
>>>
>>>
>>>
>>> -----邮件原件-----
>>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>>> 发送时间: 2020年8月3日 10:32
>>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel
>>> <joro@8bytes.org>; iommu@lists.linux-foundation.org;
>>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>>> 抄送: baolu.lu@linux.intel.com; Cobe Chen(BJ-RD)
>>> <CobeChen@zhaoxin.com>; Raymond Pang(BJ-RD) <RaymondPang@zhaoxin.com>
>>> 主题: Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>>
>>> Hi,
>>>
>>> On 8/2/20 6:07 PM, FelixCuioc wrote:
>>>> Some ACPI devices require access to the specified reserved memory
>>>> region.BIOS report the specified reserved memory region through RMRR
>>>> structures.Add analysis of ACPI device in RMRR and establish
>>>> identity mapping for ACPI device.
>>>
>>> Can you please add more words about the problem you want to solve? Do you mean some RMRRs are not enumerated correctly? Or, enumerated, but not identity mapped?
>>>
>>> Nit: add version and change log once you refreshed your patch.
>>>
>>>>
>>>> Reported-by: kernel test robot <lkp@intel.com>
>>>
>>> No need to add this. The problem you want to solve through this patch is not reported by lkp.
>>>
>>> Best regards,
>>> baolu
>>>
>>>> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
>>>> ---
>>>>      drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>>>>      drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>>>>      drivers/iommu/iommu.c       |  6 +++
>>>>      include/linux/dmar.h        | 12 +++++-
>>>>      include/linux/iommu.h       |  3 ++
>>>>      5 files changed, 105 insertions(+), 36 deletions(-)
>>>>
>>>> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
>>>> index 93e6345f3414..024ca38dba12 100644
>>>> --- a/drivers/iommu/intel/dmar.c
>>>> +++ b/drivers/iommu/intel/dmar.c
>>>> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>>>>      }
>>>>      
>>>>      /* Return: > 0 if match found, 0 if no match found, < 0 if error
>>>> happens */ -int dmar_insert_dev_scope(struct dmar_pci_notify_info
>>>> *info,
>>>> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>>>>      			  void *start, void*end, u16 segment,
>>>>      			  struct dmar_dev_scope *devices,
>>>>      			  int devices_cnt)
>>>> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct
>>>> dmar_pci_notify_info *info)
>>>>      
>>>>      		drhd = container_of(dmaru->hdr,
>>>>      				    struct acpi_dmar_hardware_unit, header);
>>>> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
>>>> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>>>>      				((void *)drhd) + drhd->header.length,
>>>>      				dmaru->segment,
>>>>      				dmaru->devices, dmaru->devices_cnt); @@ -696,48 +696,56 @@
>>>> dmar_find_matched_drhd_unit(struct pci_dev *dev)
>>>>      
>>>>      	return dmaru;
>>>>      }
>>>> -
>>>> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
>>>> -					      struct acpi_device *adev)
>>>> +int dmar_acpi_insert_dev_scope(u8 device_number,
>>>> +				struct acpi_device *adev,
>>>> +				void *start, void *end,
>>>> +				struct dmar_dev_scope *devices,
>>>> +				int devices_cnt)
>>>>      {
>>>> -	struct dmar_drhd_unit *dmaru;
>>>> -	struct acpi_dmar_hardware_unit *drhd;
>>>>      	struct acpi_dmar_device_scope *scope;
>>>>      	struct device *tmp;
>>>>      	int i;
>>>>      	struct acpi_dmar_pci_path *path;
>>>>      
>>>> +	for (; start < end; start += scope->length) {
>>>> +		scope = start;
>>>> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>>> +			continue;
>>>> +		if (scope->enumeration_id != device_number)
>>>> +			continue;
>>>> +		path = (void *)(scope + 1);
>>>> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
>>>> +			if (tmp == NULL) {
>>>> +				devices[i].bus = scope->bus;
>>>> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
>>>> +				rcu_assign_pointer(devices[i].dev,
>>>> +						   get_device(&adev->dev));
>>>> +				return 1;
>>>> +			}
>>>> +		WARN_ON(i >= devices_cnt);
>>>> +	}
>>>> +	return 0;
>>>> +}
>>>> +static int dmar_acpi_bus_add_dev(u8 device_number, struct
>>>> +acpi_device
>>>> +*adev) {
>>>> +	struct dmar_drhd_unit *dmaru;
>>>> +	struct acpi_dmar_hardware_unit *drhd;
>>>> +	int ret = 0;
>>>> +
>>>>      	for_each_drhd_unit(dmaru) {
>>>>      		drhd = container_of(dmaru->hdr,
>>>>      				    struct acpi_dmar_hardware_unit,
>>>>      				    header);
>>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
>>>> +						((void *)drhd)+drhd->header.length,
>>>> +						dmaru->devices, dmaru->devices_cnt);
>>>> +		if (ret)
>>>> +			break;
>>>> +	}
>>>> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>>>>      
>>>> -		for (scope = (void *)(drhd + 1);
>>>> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
>>>> -		     scope = ((void *)scope) + scope->length) {
>>>> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>>> -				continue;
>>>> -			if (scope->enumeration_id != device_number)
>>>> -				continue;
>>>> +	return ret;
>>>>      
>>>> -			path = (void *)(scope + 1);
>>>> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
>>>> -				dev_name(&adev->dev), dmaru->reg_base_addr,
>>>> -				scope->bus, path->device, path->function);
>>>> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
>>>> -				if (tmp == NULL) {
>>>> -					dmaru->devices[i].bus = scope->bus;
>>>> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
>>>> -									    path->function);
>>>> -					rcu_assign_pointer(dmaru->devices[i].dev,
>>>> -							   get_device(&adev->dev));
>>>> -					return;
>>>> -				}
>>>> -			BUG_ON(i >= dmaru->devices_cnt);
>>>> -		}
>>>> -	}
>>>> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
>>>> -		device_number, dev_name(&adev->dev));
>>>>      }
>>>>      
>>>>      static int __init dmar_acpi_dev_scope_init(void) @@ -766,7
>>>> +774,7 @@ static int __init dmar_acpi_dev_scope_init(void)
>>>>      				       andd->device_name);
>>>>      				continue;
>>>>      			}
>>>> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
>>>> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>>>>      		}
>>>>      	}
>>>>      	return 0;
>>>> diff --git a/drivers/iommu/intel/iommu.c
>>>> b/drivers/iommu/intel/iommu.c index ca557d351518..be1793415326
>>>> 100644
>>>> --- a/drivers/iommu/intel/iommu.c
>>>> +++ b/drivers/iommu/intel/iommu.c
>>>> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct
>>>> pci_dev
>>>> *dev)
>>>>      
>>>>      	return ret;
>>>>      }
>>>> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device
>>>> +*adev) {
>>>> +	int ret;
>>>> +	struct dmar_rmrr_unit *rmrru;
>>>> +	struct acpi_dmar_reserved_memory *rmrr;
>>>> +
>>>> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
>>>> +		rmrr = container_of(rmrru->hdr,
>>>> +				struct acpi_dmar_reserved_memory,
>>>> +				header);
>>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
>>>> +						((void *)rmrr) + rmrr->header.length,
>>>> +						rmrru->devices, rmrru->devices_cnt);
>>>> +		if (ret)
>>>> +			break;
>>>> +	}
>>>> +	return 0;
>>>> +}
>>>>      
>>>>      int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>      {
>>>> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>      		rmrr = container_of(rmrru->hdr,
>>>>      				    struct acpi_dmar_reserved_memory, header);
>>>>      		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>>> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
>>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>>>>      				((void *)rmrr) + rmrr->header.length,
>>>>      				rmrr->segment, rmrru->devices,
>>>>      				rmrru->devices_cnt);
>>>> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct
>>>> dmar_pci_notify_info *info)
>>>>      
>>>>      		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>>>>      		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>>> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
>>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>>>>      					(void *)atsr + atsr->header.length,
>>>>      					atsr->segment, atsru->devices,
>>>>      					atsru->devices_cnt);
>>>> @@ -4779,6 +4797,26 @@ 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) {
>>>> +	int ret;
>>>> +	struct iommu_group *group;
>>>> +
>>>> +	if (pn_dev == NULL) {
>>>> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>>> +		ret = iommu_probe_device(acpi_device);
>>>> +		if (ret) {
>>>> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
>>>> +			return ret;
>>>> +		}
>>>> +		return 0;
>>>> +	}
>>>> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>>> +	group = iommu_group_get(pn_dev);
>>>> +	__acpi_device_create_direct_mappings(group, acpi_device);
>>>> +
>>>> +	return 0;
>>>> +}
>>>>      
>>>>      static int __init probe_acpi_namespace_devices(void)
>>>>      {
>>>> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>>      			struct acpi_device_physical_node *pn;
>>>>      			struct iommu_group *group;
>>>>      			struct acpi_device *adev;
>>>> +			struct device *pn_dev = NULL;
>>>>      
>>>>      			if (dev->bus != &acpi_bus_type)
>>>>      				continue;
>>>> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>>      					    &adev->physical_node_list, node) {
>>>>      				group = iommu_group_get(pn->dev);
>>>>      				if (group) {
>>>> +					pn_dev = pn->dev;
>>>>      					iommu_group_put(group);
>>>>      					continue;
>>>>      				}
>>>> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>>>>      				ret = iommu_probe_device(pn->dev);
>>>>      				if (ret)
>>>>      					break;
>>>> +				pn_dev = pn->dev;
>>>>      			}
>>>> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>>>>      			mutex_unlock(&adev->physical_node_lock);
>>>>      
>>>>      			if (ret)
>>>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
>>>> 609bd25bf154..4f714a2d5ef7 100644
>>>> --- a/drivers/iommu/iommu.c
>>>> +++ b/drivers/iommu/iommu.c
>>>> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>>>>      	return false;
>>>>      }
>>>>      
>>>> +void  __acpi_device_create_direct_mappings(struct iommu_group
>>>> +*group, struct device *acpi_device) {
>>>> +	iommu_create_device_direct_mappings(group, acpi_device); }
>>>> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
>>>> +
>>>>      /**
>>>>       * iommu_group_add_device - add a device to an iommu group
>>>>       * @group: the group into which to add the device (reference
>>>> should be held) diff --git a/include/linux/dmar.h
>>>> b/include/linux/dmar.h index 65565820328a..881ac61a4336 100644
>>>> --- a/include/linux/dmar.h
>>>> +++ b/include/linux/dmar.h
>>>> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>>>>      				struct dmar_dev_scope **devices, u16 segment);
>>>>      extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>>>>      extern void dmar_free_dev_scope(struct dmar_dev_scope **devices,
>>>> int *cnt); -extern int dmar_insert_dev_scope(struct
>>>> dmar_pci_notify_info *info,
>>>> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info
>>>> +*info,
>>>>      				 void *start, void*end, u16 segment,
>>>>      				 struct dmar_dev_scope *devices,
>>>>      				 int devices_cnt);
>>>> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
>>>> +				struct acpi_device *adev, void *start, void *end,
>>>> +				struct dmar_dev_scope *devices, int devices_cnt);
>>>> +
>>>>      extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>>>>      				 u16 segment, struct dmar_dev_scope *devices,
>>>>      				 int count);
>>>> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>>>>      extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>>      extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>>      extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool
>>>> insert);
>>>> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct
>>>> +acpi_device *adev);
>>>>      extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>>>>      #else /* !CONFIG_INTEL_IOMMU: */
>>>>      static inline int intel_iommu_init(void) { return -ENODEV; } @@
>>>> -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>>>>      #define	dmar_check_one_atsr		dmar_res_noop
>>>>      #define	dmar_release_one_atsr		dmar_res_noop
>>>>      
>>>> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct
>>>> +acpi_device *adev) {
>>>> +	return 0;
>>>> +}
>>>> +
>>>>      static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>>      {
>>>>      	return 0;
>>>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
>>>> fee209efb756..9be134775886 100644
>>>> --- a/include/linux/iommu.h
>>>> +++ b/include/linux/iommu.h
>>>> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>>>>      extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>>>>      			      unsigned long iova, int flags);
>>>>      
>>>> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
>>>> +						struct device *acpi_device);
>>>> +
>>>>      static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>>>>      {
>>>>      	if (domain->ops->flush_iotlb_all)
>>>>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-03  8:25         ` Lu Baolu
  2020-08-03  9:01           ` 答复: " FelixCui-oc
@ 2020-08-03  9:41           ` FelixCui-oc
  2020-08-04  1:11             ` Lu Baolu
  1 sibling, 1 reply; 14+ messages in thread
From: FelixCui-oc @ 2020-08-03  9:41 UTC (permalink / raw)
  To: Lu Baolu, Joerg Roedel, iommu, linux-kernel, David Woodhouse; +Cc: CobeChen-oc

Hi baolu,
		 dmar_acpi_dev_scope_init() parse ANDD structure and enumerated namespaces device in DRHD.
		 But the namespace device in RMRR is not enumerated, right?

Best regards
Felix cui-oc




-----邮件原件-----
发件人: FelixCui-oc 
发送时间: 2020年8月3日 17:02
收件人: 'Lu Baolu' <baolu.lu@linux.intel.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
抄送: RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
主题: 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR

Hi  baolu:
		"The namespace devices are enumerated in probe_acpi_namespace_devices().
		It calls iommu_probe_device() to process the enumeration and setup the identity mappings."
		
		This situation only applies to the physical node of the namespaces device as the pci device.
		In fact, the physical node of the namespaces device can be a platform device or NULL.
		If the physical node of the namespaces is a platform device or NULL, it has not actually been enumerated.
		So it is necessary to increase the analysis of the namespaces device in RMRR and establish an identity mapping.

Best regards
Felix cui




-----邮件原件-----
发件人: Lu Baolu <baolu.lu@linux.intel.com>
发送时间: 2020年8月3日 16:26
收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
抄送: baolu.lu@linux.intel.com; RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
主题: Re: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR

On 2020/8/3 14:52, FelixCui-oc wrote:
> Hi  baolu ,
> 		Yes ,that's right.
> 		This patch is to achieve acpi namespace devices to access the RMRR region.

The namespace devices are enumerated in probe_acpi_namespace_devices().
It calls iommu_probe_device() to process the enumeration and setup the identity mappings. Can you please check why that code doesn't work for you?

Best regards,
baolu

> 
> Best regards
> Felix cui
> 
> 
> 
> 
> -----邮件原件-----
> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
> 发送时间: 2020年8月3日 14:19
> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc 
> <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
> 主题: Re: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
> 
> Hi,
> 
> On 2020/8/3 12:40, FelixCui-oc wrote:
>> Hi baolu:
>> 		Some ACPI devices need to issue dma requests to access the reserved memory area.
>> 		So bios uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
>> 		At present, there is no analysis in the kernel that the device scope type in RMRR is ACPI_NAMESPACE_DEVICE.
>> 		This patch is mainly to add the analysis of the device scope type ACPI_NAMESPACE_DEVICE in RMRR structure and establish identity mapping for > these ACPI devices.
> 
> So the problem is "although namespace devices in RMRR have been parsed, but the identity map for those devices aren't created. As the result, the namespace devices fail to access the RMRR region."
> 
> Do I understand it right?
> 
> Best regards,
> baolu
> 
>> In addition, some naming changes have been made in patch in order to distinguish acpi device from pci device.
>> 		You can refer to the description of type in 8.3.1 device scope in vt-d spec.
>>
>> Best regards
>> FelixCui-oc
>>
>>
>>
>> -----邮件原件-----
>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>> 发送时间: 2020年8月3日 10:32
>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
>> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>> 抄送: baolu.lu@linux.intel.com; Cobe Chen(BJ-RD) 
>> <CobeChen@zhaoxin.com>; Raymond Pang(BJ-RD) <RaymondPang@zhaoxin.com>
>> 主题: Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>
>> Hi,
>>
>> On 8/2/20 6:07 PM, FelixCuioc wrote:
>>> Some ACPI devices require access to the specified reserved memory 
>>> region.BIOS report the specified reserved memory region through RMRR 
>>> structures.Add analysis of ACPI device in RMRR and establish 
>>> identity mapping for ACPI device.
>>
>> Can you please add more words about the problem you want to solve? Do you mean some RMRRs are not enumerated correctly? Or, enumerated, but not identity mapped?
>>
>> Nit: add version and change log once you refreshed your patch.
>>
>>>
>>> Reported-by: kernel test robot <lkp@intel.com>
>>
>> No need to add this. The problem you want to solve through this patch is not reported by lkp.
>>
>> Best regards,
>> baolu
>>
>>> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
>>> ---
>>>     drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>>>     drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>>>     drivers/iommu/iommu.c       |  6 +++
>>>     include/linux/dmar.h        | 12 +++++-
>>>     include/linux/iommu.h       |  3 ++
>>>     5 files changed, 105 insertions(+), 36 deletions(-)
>>>
>>> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c 
>>> index 93e6345f3414..024ca38dba12 100644
>>> --- a/drivers/iommu/intel/dmar.c
>>> +++ b/drivers/iommu/intel/dmar.c
>>> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>>>     }
>>>     
>>>     /* Return: > 0 if match found, 0 if no match found, < 0 if error 
>>> happens */ -int dmar_insert_dev_scope(struct dmar_pci_notify_info 
>>> *info,
>>> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>>>     			  void *start, void*end, u16 segment,
>>>     			  struct dmar_dev_scope *devices,
>>>     			  int devices_cnt)
>>> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct 
>>> dmar_pci_notify_info *info)
>>>     
>>>     		drhd = container_of(dmaru->hdr,
>>>     				    struct acpi_dmar_hardware_unit, header);
>>> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
>>> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>>>     				((void *)drhd) + drhd->header.length,
>>>     				dmaru->segment,
>>>     				dmaru->devices, dmaru->devices_cnt); @@ -696,48 +696,56 @@ 
>>> dmar_find_matched_drhd_unit(struct pci_dev *dev)
>>>     
>>>     	return dmaru;
>>>     }
>>> -
>>> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
>>> -					      struct acpi_device *adev)
>>> +int dmar_acpi_insert_dev_scope(u8 device_number,
>>> +				struct acpi_device *adev,
>>> +				void *start, void *end,
>>> +				struct dmar_dev_scope *devices,
>>> +				int devices_cnt)
>>>     {
>>> -	struct dmar_drhd_unit *dmaru;
>>> -	struct acpi_dmar_hardware_unit *drhd;
>>>     	struct acpi_dmar_device_scope *scope;
>>>     	struct device *tmp;
>>>     	int i;
>>>     	struct acpi_dmar_pci_path *path;
>>>     
>>> +	for (; start < end; start += scope->length) {
>>> +		scope = start;
>>> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>> +			continue;
>>> +		if (scope->enumeration_id != device_number)
>>> +			continue;
>>> +		path = (void *)(scope + 1);
>>> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
>>> +			if (tmp == NULL) {
>>> +				devices[i].bus = scope->bus;
>>> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
>>> +				rcu_assign_pointer(devices[i].dev,
>>> +						   get_device(&adev->dev));
>>> +				return 1;
>>> +			}
>>> +		WARN_ON(i >= devices_cnt);
>>> +	}
>>> +	return 0;
>>> +}
>>> +static int dmar_acpi_bus_add_dev(u8 device_number, struct 
>>> +acpi_device
>>> +*adev) {
>>> +	struct dmar_drhd_unit *dmaru;
>>> +	struct acpi_dmar_hardware_unit *drhd;
>>> +	int ret = 0;
>>> +
>>>     	for_each_drhd_unit(dmaru) {
>>>     		drhd = container_of(dmaru->hdr,
>>>     				    struct acpi_dmar_hardware_unit,
>>>     				    header);
>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
>>> +						((void *)drhd)+drhd->header.length,
>>> +						dmaru->devices, dmaru->devices_cnt);
>>> +		if (ret)
>>> +			break;
>>> +	}
>>> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>>>     
>>> -		for (scope = (void *)(drhd + 1);
>>> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
>>> -		     scope = ((void *)scope) + scope->length) {
>>> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>> -				continue;
>>> -			if (scope->enumeration_id != device_number)
>>> -				continue;
>>> +	return ret;
>>>     
>>> -			path = (void *)(scope + 1);
>>> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
>>> -				dev_name(&adev->dev), dmaru->reg_base_addr,
>>> -				scope->bus, path->device, path->function);
>>> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
>>> -				if (tmp == NULL) {
>>> -					dmaru->devices[i].bus = scope->bus;
>>> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
>>> -									    path->function);
>>> -					rcu_assign_pointer(dmaru->devices[i].dev,
>>> -							   get_device(&adev->dev));
>>> -					return;
>>> -				}
>>> -			BUG_ON(i >= dmaru->devices_cnt);
>>> -		}
>>> -	}
>>> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
>>> -		device_number, dev_name(&adev->dev));
>>>     }
>>>     
>>>     static int __init dmar_acpi_dev_scope_init(void) @@ -766,7
>>> +774,7 @@ static int __init dmar_acpi_dev_scope_init(void)
>>>     				       andd->device_name);
>>>     				continue;
>>>     			}
>>> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
>>> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>>>     		}
>>>     	}
>>>     	return 0;
>>> diff --git a/drivers/iommu/intel/iommu.c 
>>> b/drivers/iommu/intel/iommu.c index ca557d351518..be1793415326
>>> 100644
>>> --- a/drivers/iommu/intel/iommu.c
>>> +++ b/drivers/iommu/intel/iommu.c
>>> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct
>>> pci_dev
>>> *dev)
>>>     
>>>     	return ret;
>>>     }
>>> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device
>>> +*adev) {
>>> +	int ret;
>>> +	struct dmar_rmrr_unit *rmrru;
>>> +	struct acpi_dmar_reserved_memory *rmrr;
>>> +
>>> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
>>> +		rmrr = container_of(rmrru->hdr,
>>> +				struct acpi_dmar_reserved_memory,
>>> +				header);
>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
>>> +						((void *)rmrr) + rmrr->header.length,
>>> +						rmrru->devices, rmrru->devices_cnt);
>>> +		if (ret)
>>> +			break;
>>> +	}
>>> +	return 0;
>>> +}
>>>     
>>>     int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>     {
>>> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>     		rmrr = container_of(rmrru->hdr,
>>>     				    struct acpi_dmar_reserved_memory, header);
>>>     		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>>>     				((void *)rmrr) + rmrr->header.length,
>>>     				rmrr->segment, rmrru->devices,
>>>     				rmrru->devices_cnt);
>>> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct
>>> dmar_pci_notify_info *info)
>>>     
>>>     		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>>>     		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>>>     					(void *)atsr + atsr->header.length,
>>>     					atsr->segment, atsru->devices,
>>>     					atsru->devices_cnt);
>>> @@ -4779,6 +4797,26 @@ 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) {
>>> +	int ret;
>>> +	struct iommu_group *group;
>>> +
>>> +	if (pn_dev == NULL) {
>>> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>> +		ret = iommu_probe_device(acpi_device);
>>> +		if (ret) {
>>> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
>>> +			return ret;
>>> +		}
>>> +		return 0;
>>> +	}
>>> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>> +	group = iommu_group_get(pn_dev);
>>> +	__acpi_device_create_direct_mappings(group, acpi_device);
>>> +
>>> +	return 0;
>>> +}
>>>     
>>>     static int __init probe_acpi_namespace_devices(void)
>>>     {
>>> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>     			struct acpi_device_physical_node *pn;
>>>     			struct iommu_group *group;
>>>     			struct acpi_device *adev;
>>> +			struct device *pn_dev = NULL;
>>>     
>>>     			if (dev->bus != &acpi_bus_type)
>>>     				continue;
>>> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>     					    &adev->physical_node_list, node) {
>>>     				group = iommu_group_get(pn->dev);
>>>     				if (group) {
>>> +					pn_dev = pn->dev;
>>>     					iommu_group_put(group);
>>>     					continue;
>>>     				}
>>> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>>>     				ret = iommu_probe_device(pn->dev);
>>>     				if (ret)
>>>     					break;
>>> +				pn_dev = pn->dev;
>>>     			}
>>> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>>>     			mutex_unlock(&adev->physical_node_lock);
>>>     
>>>     			if (ret)
>>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
>>> 609bd25bf154..4f714a2d5ef7 100644
>>> --- a/drivers/iommu/iommu.c
>>> +++ b/drivers/iommu/iommu.c
>>> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>>>     	return false;
>>>     }
>>>     
>>> +void  __acpi_device_create_direct_mappings(struct iommu_group 
>>> +*group, struct device *acpi_device) {
>>> +	iommu_create_device_direct_mappings(group, acpi_device); } 
>>> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
>>> +
>>>     /**
>>>      * iommu_group_add_device - add a device to an iommu group
>>>      * @group: the group into which to add the device (reference 
>>> should be held) diff --git a/include/linux/dmar.h 
>>> b/include/linux/dmar.h index 65565820328a..881ac61a4336 100644
>>> --- a/include/linux/dmar.h
>>> +++ b/include/linux/dmar.h
>>> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>>>     				struct dmar_dev_scope **devices, u16 segment);
>>>     extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>>>     extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, 
>>> int *cnt); -extern int dmar_insert_dev_scope(struct 
>>> dmar_pci_notify_info *info,
>>> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info 
>>> +*info,
>>>     				 void *start, void*end, u16 segment,
>>>     				 struct dmar_dev_scope *devices,
>>>     				 int devices_cnt);
>>> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
>>> +				struct acpi_device *adev, void *start, void *end,
>>> +				struct dmar_dev_scope *devices, int devices_cnt);
>>> +
>>>     extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>>>     				 u16 segment, struct dmar_dev_scope *devices,
>>>     				 int count);
>>> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>>>     extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>     extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>     extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool 
>>> insert);
>>> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
>>> +acpi_device *adev);
>>>     extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>>>     #else /* !CONFIG_INTEL_IOMMU: */
>>>     static inline int intel_iommu_init(void) { return -ENODEV; } @@
>>> -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>>>     #define	dmar_check_one_atsr		dmar_res_noop
>>>     #define	dmar_release_one_atsr		dmar_res_noop
>>>     
>>> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
>>> +acpi_device *adev) {
>>> +	return 0;
>>> +}
>>> +
>>>     static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>     {
>>>     	return 0;
>>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
>>> fee209efb756..9be134775886 100644
>>> --- a/include/linux/iommu.h
>>> +++ b/include/linux/iommu.h
>>> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>>>     extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>>>     			      unsigned long iova, int flags);
>>>     
>>> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
>>> +						struct device *acpi_device);
>>> +
>>>     static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>>>     {
>>>     	if (domain->ops->flush_iotlb_all)
>>>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* 答复: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-03  8:25         ` Lu Baolu
@ 2020-08-03  9:01           ` FelixCui-oc
  2020-08-03  9:41           ` FelixCui-oc
  1 sibling, 0 replies; 14+ messages in thread
From: FelixCui-oc @ 2020-08-03  9:01 UTC (permalink / raw)
  To: Lu Baolu, Joerg Roedel, iommu, linux-kernel, David Woodhouse; +Cc: CobeChen-oc

Hi  baolu:
		"The namespace devices are enumerated in probe_acpi_namespace_devices().
		It calls iommu_probe_device() to process the enumeration and setup the identity mappings."
		
		This situation only applies to the physical node of the namespaces device as the pci device.
		In fact, the physical node of the namespaces device can be a platform device or NULL.
		If the physical node of the namespaces is a platform device or NULL, it has not actually been enumerated.
		So it is necessary to increase the analysis of the namespaces device in RMRR and establish an identity mapping.

Best regards
Felix cui




-----邮件原件-----
发件人: Lu Baolu <baolu.lu@linux.intel.com> 
发送时间: 2020年8月3日 16:26
收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
抄送: baolu.lu@linux.intel.com; RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
主题: Re: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR

On 2020/8/3 14:52, FelixCui-oc wrote:
> Hi  baolu ,
> 		Yes ,that's right.
> 		This patch is to achieve acpi namespace devices to access the RMRR region.

The namespace devices are enumerated in probe_acpi_namespace_devices().
It calls iommu_probe_device() to process the enumeration and setup the identity mappings. Can you please check why that code doesn't work for you?

Best regards,
baolu

> 
> Best regards
> Felix cui
> 
> 
> 
> 
> -----邮件原件-----
> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
> 发送时间: 2020年8月3日 14:19
> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc 
> <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
> 主题: Re: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
> 
> Hi,
> 
> On 2020/8/3 12:40, FelixCui-oc wrote:
>> Hi baolu:
>> 		Some ACPI devices need to issue dma requests to access the reserved memory area.
>> 		So bios uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
>> 		At present, there is no analysis in the kernel that the device scope type in RMRR is ACPI_NAMESPACE_DEVICE.
>> 		This patch is mainly to add the analysis of the device scope type ACPI_NAMESPACE_DEVICE in RMRR structure and establish identity mapping for > these ACPI devices.
> 
> So the problem is "although namespace devices in RMRR have been parsed, but the identity map for those devices aren't created. As the result, the namespace devices fail to access the RMRR region."
> 
> Do I understand it right?
> 
> Best regards,
> baolu
> 
>> In addition, some naming changes have been made in patch in order to distinguish acpi device from pci device.
>> 		You can refer to the description of type in 8.3.1 device scope in vt-d spec.
>>
>> Best regards
>> FelixCui-oc
>>
>>
>>
>> -----邮件原件-----
>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>> 发送时间: 2020年8月3日 10:32
>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
>> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>> 抄送: baolu.lu@linux.intel.com; Cobe Chen(BJ-RD) 
>> <CobeChen@zhaoxin.com>; Raymond Pang(BJ-RD) <RaymondPang@zhaoxin.com>
>> 主题: Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>
>> Hi,
>>
>> On 8/2/20 6:07 PM, FelixCuioc wrote:
>>> Some ACPI devices require access to the specified reserved memory 
>>> region.BIOS report the specified reserved memory region through RMRR 
>>> structures.Add analysis of ACPI device in RMRR and establish 
>>> identity mapping for ACPI device.
>>
>> Can you please add more words about the problem you want to solve? Do you mean some RMRRs are not enumerated correctly? Or, enumerated, but not identity mapped?
>>
>> Nit: add version and change log once you refreshed your patch.
>>
>>>
>>> Reported-by: kernel test robot <lkp@intel.com>
>>
>> No need to add this. The problem you want to solve through this patch is not reported by lkp.
>>
>> Best regards,
>> baolu
>>
>>> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
>>> ---
>>>     drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>>>     drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>>>     drivers/iommu/iommu.c       |  6 +++
>>>     include/linux/dmar.h        | 12 +++++-
>>>     include/linux/iommu.h       |  3 ++
>>>     5 files changed, 105 insertions(+), 36 deletions(-)
>>>
>>> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c 
>>> index 93e6345f3414..024ca38dba12 100644
>>> --- a/drivers/iommu/intel/dmar.c
>>> +++ b/drivers/iommu/intel/dmar.c
>>> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>>>     }
>>>     
>>>     /* Return: > 0 if match found, 0 if no match found, < 0 if error 
>>> happens */ -int dmar_insert_dev_scope(struct dmar_pci_notify_info 
>>> *info,
>>> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>>>     			  void *start, void*end, u16 segment,
>>>     			  struct dmar_dev_scope *devices,
>>>     			  int devices_cnt)
>>> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct 
>>> dmar_pci_notify_info *info)
>>>     
>>>     		drhd = container_of(dmaru->hdr,
>>>     				    struct acpi_dmar_hardware_unit, header);
>>> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
>>> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>>>     				((void *)drhd) + drhd->header.length,
>>>     				dmaru->segment,
>>>     				dmaru->devices, dmaru->devices_cnt); @@ -696,48 +696,56 @@ 
>>> dmar_find_matched_drhd_unit(struct pci_dev *dev)
>>>     
>>>     	return dmaru;
>>>     }
>>> -
>>> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
>>> -					      struct acpi_device *adev)
>>> +int dmar_acpi_insert_dev_scope(u8 device_number,
>>> +				struct acpi_device *adev,
>>> +				void *start, void *end,
>>> +				struct dmar_dev_scope *devices,
>>> +				int devices_cnt)
>>>     {
>>> -	struct dmar_drhd_unit *dmaru;
>>> -	struct acpi_dmar_hardware_unit *drhd;
>>>     	struct acpi_dmar_device_scope *scope;
>>>     	struct device *tmp;
>>>     	int i;
>>>     	struct acpi_dmar_pci_path *path;
>>>     
>>> +	for (; start < end; start += scope->length) {
>>> +		scope = start;
>>> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>> +			continue;
>>> +		if (scope->enumeration_id != device_number)
>>> +			continue;
>>> +		path = (void *)(scope + 1);
>>> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
>>> +			if (tmp == NULL) {
>>> +				devices[i].bus = scope->bus;
>>> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
>>> +				rcu_assign_pointer(devices[i].dev,
>>> +						   get_device(&adev->dev));
>>> +				return 1;
>>> +			}
>>> +		WARN_ON(i >= devices_cnt);
>>> +	}
>>> +	return 0;
>>> +}
>>> +static int dmar_acpi_bus_add_dev(u8 device_number, struct 
>>> +acpi_device
>>> +*adev) {
>>> +	struct dmar_drhd_unit *dmaru;
>>> +	struct acpi_dmar_hardware_unit *drhd;
>>> +	int ret = 0;
>>> +
>>>     	for_each_drhd_unit(dmaru) {
>>>     		drhd = container_of(dmaru->hdr,
>>>     				    struct acpi_dmar_hardware_unit,
>>>     				    header);
>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
>>> +						((void *)drhd)+drhd->header.length,
>>> +						dmaru->devices, dmaru->devices_cnt);
>>> +		if (ret)
>>> +			break;
>>> +	}
>>> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>>>     
>>> -		for (scope = (void *)(drhd + 1);
>>> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
>>> -		     scope = ((void *)scope) + scope->length) {
>>> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>> -				continue;
>>> -			if (scope->enumeration_id != device_number)
>>> -				continue;
>>> +	return ret;
>>>     
>>> -			path = (void *)(scope + 1);
>>> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
>>> -				dev_name(&adev->dev), dmaru->reg_base_addr,
>>> -				scope->bus, path->device, path->function);
>>> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
>>> -				if (tmp == NULL) {
>>> -					dmaru->devices[i].bus = scope->bus;
>>> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
>>> -									    path->function);
>>> -					rcu_assign_pointer(dmaru->devices[i].dev,
>>> -							   get_device(&adev->dev));
>>> -					return;
>>> -				}
>>> -			BUG_ON(i >= dmaru->devices_cnt);
>>> -		}
>>> -	}
>>> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
>>> -		device_number, dev_name(&adev->dev));
>>>     }
>>>     
>>>     static int __init dmar_acpi_dev_scope_init(void) @@ -766,7 
>>> +774,7 @@ static int __init dmar_acpi_dev_scope_init(void)
>>>     				       andd->device_name);
>>>     				continue;
>>>     			}
>>> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
>>> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>>>     		}
>>>     	}
>>>     	return 0;
>>> diff --git a/drivers/iommu/intel/iommu.c 
>>> b/drivers/iommu/intel/iommu.c index ca557d351518..be1793415326 
>>> 100644
>>> --- a/drivers/iommu/intel/iommu.c
>>> +++ b/drivers/iommu/intel/iommu.c
>>> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct 
>>> pci_dev
>>> *dev)
>>>     
>>>     	return ret;
>>>     }
>>> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device
>>> +*adev) {
>>> +	int ret;
>>> +	struct dmar_rmrr_unit *rmrru;
>>> +	struct acpi_dmar_reserved_memory *rmrr;
>>> +
>>> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
>>> +		rmrr = container_of(rmrru->hdr,
>>> +				struct acpi_dmar_reserved_memory,
>>> +				header);
>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
>>> +						((void *)rmrr) + rmrr->header.length,
>>> +						rmrru->devices, rmrru->devices_cnt);
>>> +		if (ret)
>>> +			break;
>>> +	}
>>> +	return 0;
>>> +}
>>>     
>>>     int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>     {
>>> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>     		rmrr = container_of(rmrru->hdr,
>>>     				    struct acpi_dmar_reserved_memory, header);
>>>     		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>>>     				((void *)rmrr) + rmrr->header.length,
>>>     				rmrr->segment, rmrru->devices,
>>>     				rmrru->devices_cnt);
>>> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct
>>> dmar_pci_notify_info *info)
>>>     
>>>     		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>>>     		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>>>     					(void *)atsr + atsr->header.length,
>>>     					atsr->segment, atsru->devices,
>>>     					atsru->devices_cnt);
>>> @@ -4779,6 +4797,26 @@ 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) {
>>> +	int ret;
>>> +	struct iommu_group *group;
>>> +
>>> +	if (pn_dev == NULL) {
>>> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>> +		ret = iommu_probe_device(acpi_device);
>>> +		if (ret) {
>>> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
>>> +			return ret;
>>> +		}
>>> +		return 0;
>>> +	}
>>> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>> +	group = iommu_group_get(pn_dev);
>>> +	__acpi_device_create_direct_mappings(group, acpi_device);
>>> +
>>> +	return 0;
>>> +}
>>>     
>>>     static int __init probe_acpi_namespace_devices(void)
>>>     {
>>> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>     			struct acpi_device_physical_node *pn;
>>>     			struct iommu_group *group;
>>>     			struct acpi_device *adev;
>>> +			struct device *pn_dev = NULL;
>>>     
>>>     			if (dev->bus != &acpi_bus_type)
>>>     				continue;
>>> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>     					    &adev->physical_node_list, node) {
>>>     				group = iommu_group_get(pn->dev);
>>>     				if (group) {
>>> +					pn_dev = pn->dev;
>>>     					iommu_group_put(group);
>>>     					continue;
>>>     				}
>>> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>>>     				ret = iommu_probe_device(pn->dev);
>>>     				if (ret)
>>>     					break;
>>> +				pn_dev = pn->dev;
>>>     			}
>>> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>>>     			mutex_unlock(&adev->physical_node_lock);
>>>     
>>>     			if (ret)
>>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
>>> 609bd25bf154..4f714a2d5ef7 100644
>>> --- a/drivers/iommu/iommu.c
>>> +++ b/drivers/iommu/iommu.c
>>> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>>>     	return false;
>>>     }
>>>     
>>> +void  __acpi_device_create_direct_mappings(struct iommu_group 
>>> +*group, struct device *acpi_device) {
>>> +	iommu_create_device_direct_mappings(group, acpi_device); } 
>>> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
>>> +
>>>     /**
>>>      * iommu_group_add_device - add a device to an iommu group
>>>      * @group: the group into which to add the device (reference 
>>> should be held) diff --git a/include/linux/dmar.h 
>>> b/include/linux/dmar.h index 65565820328a..881ac61a4336 100644
>>> --- a/include/linux/dmar.h
>>> +++ b/include/linux/dmar.h
>>> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>>>     				struct dmar_dev_scope **devices, u16 segment);
>>>     extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>>>     extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, 
>>> int *cnt); -extern int dmar_insert_dev_scope(struct 
>>> dmar_pci_notify_info *info,
>>> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info 
>>> +*info,
>>>     				 void *start, void*end, u16 segment,
>>>     				 struct dmar_dev_scope *devices,
>>>     				 int devices_cnt);
>>> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
>>> +				struct acpi_device *adev, void *start, void *end,
>>> +				struct dmar_dev_scope *devices, int devices_cnt);
>>> +
>>>     extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>>>     				 u16 segment, struct dmar_dev_scope *devices,
>>>     				 int count);
>>> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>>>     extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>     extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>     extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool 
>>> insert);
>>> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
>>> +acpi_device *adev);
>>>     extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>>>     #else /* !CONFIG_INTEL_IOMMU: */
>>>     static inline int intel_iommu_init(void) { return -ENODEV; } @@
>>> -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>>>     #define	dmar_check_one_atsr		dmar_res_noop
>>>     #define	dmar_release_one_atsr		dmar_res_noop
>>>     
>>> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
>>> +acpi_device *adev) {
>>> +	return 0;
>>> +}
>>> +
>>>     static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>     {
>>>     	return 0;
>>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
>>> fee209efb756..9be134775886 100644
>>> --- a/include/linux/iommu.h
>>> +++ b/include/linux/iommu.h
>>> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>>>     extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>>>     			      unsigned long iova, int flags);
>>>     
>>> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
>>> +						struct device *acpi_device);
>>> +
>>>     static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>>>     {
>>>     	if (domain->ops->flush_iotlb_all)
>>>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-03  6:52       ` 答复: " FelixCui-oc
@ 2020-08-03  8:25         ` Lu Baolu
  2020-08-03  9:01           ` 答复: " FelixCui-oc
  2020-08-03  9:41           ` FelixCui-oc
  0 siblings, 2 replies; 14+ messages in thread
From: Lu Baolu @ 2020-08-03  8:25 UTC (permalink / raw)
  To: FelixCui-oc, Joerg Roedel, iommu, linux-kernel, David Woodhouse
  Cc: CobeChen-oc

On 2020/8/3 14:52, FelixCui-oc wrote:
> Hi  baolu ,
> 		Yes ,that's right.
> 		This patch is to achieve acpi namespace devices to access the RMRR region.

The namespace devices are enumerated in probe_acpi_namespace_devices().
It calls iommu_probe_device() to process the enumeration and setup the
identity mappings. Can you please check why that code doesn't work for
you?

Best regards,
baolu

> 
> Best regards
> Felix cui
> 
> 
> 
> 
> -----邮件原件-----
> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
> 发送时间: 2020年8月3日 14:19
> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: baolu.lu@linux.intel.com; RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
> 主题: Re: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
> 
> Hi,
> 
> On 2020/8/3 12:40, FelixCui-oc wrote:
>> Hi baolu:
>> 		Some ACPI devices need to issue dma requests to access the reserved memory area.
>> 		So bios uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
>> 		At present, there is no analysis in the kernel that the device scope type in RMRR is ACPI_NAMESPACE_DEVICE.
>> 		This patch is mainly to add the analysis of the device scope type ACPI_NAMESPACE_DEVICE in RMRR structure and establish identity mapping for > these ACPI devices.
> 
> So the problem is "although namespace devices in RMRR have been parsed, but the identity map for those devices aren't created. As the result, the namespace devices fail to access the RMRR region."
> 
> Do I understand it right?
> 
> Best regards,
> baolu
> 
>> In addition, some naming changes have been made in patch in order to distinguish acpi device from pci device.
>> 		You can refer to the description of type in 8.3.1 device scope in vt-d spec.
>>
>> Best regards
>> FelixCui-oc
>>
>>
>>
>> -----邮件原件-----
>> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
>> 发送时间: 2020年8月3日 10:32
>> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel
>> <joro@8bytes.org>; iommu@lists.linux-foundation.org;
>> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
>> 抄送: baolu.lu@linux.intel.com; Cobe Chen(BJ-RD) <CobeChen@zhaoxin.com>;
>> Raymond Pang(BJ-RD) <RaymondPang@zhaoxin.com>
>> 主题: Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
>>
>> Hi,
>>
>> On 8/2/20 6:07 PM, FelixCuioc wrote:
>>> Some ACPI devices require access to the specified reserved memory
>>> region.BIOS report the specified reserved memory region through RMRR
>>> structures.Add analysis of ACPI device in RMRR and establish identity
>>> mapping for ACPI device.
>>
>> Can you please add more words about the problem you want to solve? Do you mean some RMRRs are not enumerated correctly? Or, enumerated, but not identity mapped?
>>
>> Nit: add version and change log once you refreshed your patch.
>>
>>>
>>> Reported-by: kernel test robot <lkp@intel.com>
>>
>> No need to add this. The problem you want to solve through this patch is not reported by lkp.
>>
>> Best regards,
>> baolu
>>
>>> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
>>> ---
>>>     drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>>>     drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>>>     drivers/iommu/iommu.c       |  6 +++
>>>     include/linux/dmar.h        | 12 +++++-
>>>     include/linux/iommu.h       |  3 ++
>>>     5 files changed, 105 insertions(+), 36 deletions(-)
>>>
>>> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
>>> index 93e6345f3414..024ca38dba12 100644
>>> --- a/drivers/iommu/intel/dmar.c
>>> +++ b/drivers/iommu/intel/dmar.c
>>> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>>>     }
>>>     
>>>     /* Return: > 0 if match found, 0 if no match found, < 0 if error
>>> happens */ -int dmar_insert_dev_scope(struct dmar_pci_notify_info
>>> *info,
>>> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>>>     			  void *start, void*end, u16 segment,
>>>     			  struct dmar_dev_scope *devices,
>>>     			  int devices_cnt)
>>> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct
>>> dmar_pci_notify_info *info)
>>>     
>>>     		drhd = container_of(dmaru->hdr,
>>>     				    struct acpi_dmar_hardware_unit, header);
>>> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
>>> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>>>     				((void *)drhd) + drhd->header.length,
>>>     				dmaru->segment,
>>>     				dmaru->devices, dmaru->devices_cnt); @@ -696,48 +696,56 @@
>>> dmar_find_matched_drhd_unit(struct pci_dev *dev)
>>>     
>>>     	return dmaru;
>>>     }
>>> -
>>> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
>>> -					      struct acpi_device *adev)
>>> +int dmar_acpi_insert_dev_scope(u8 device_number,
>>> +				struct acpi_device *adev,
>>> +				void *start, void *end,
>>> +				struct dmar_dev_scope *devices,
>>> +				int devices_cnt)
>>>     {
>>> -	struct dmar_drhd_unit *dmaru;
>>> -	struct acpi_dmar_hardware_unit *drhd;
>>>     	struct acpi_dmar_device_scope *scope;
>>>     	struct device *tmp;
>>>     	int i;
>>>     	struct acpi_dmar_pci_path *path;
>>>     
>>> +	for (; start < end; start += scope->length) {
>>> +		scope = start;
>>> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>> +			continue;
>>> +		if (scope->enumeration_id != device_number)
>>> +			continue;
>>> +		path = (void *)(scope + 1);
>>> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
>>> +			if (tmp == NULL) {
>>> +				devices[i].bus = scope->bus;
>>> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
>>> +				rcu_assign_pointer(devices[i].dev,
>>> +						   get_device(&adev->dev));
>>> +				return 1;
>>> +			}
>>> +		WARN_ON(i >= devices_cnt);
>>> +	}
>>> +	return 0;
>>> +}
>>> +static int dmar_acpi_bus_add_dev(u8 device_number, struct
>>> +acpi_device
>>> +*adev) {
>>> +	struct dmar_drhd_unit *dmaru;
>>> +	struct acpi_dmar_hardware_unit *drhd;
>>> +	int ret = 0;
>>> +
>>>     	for_each_drhd_unit(dmaru) {
>>>     		drhd = container_of(dmaru->hdr,
>>>     				    struct acpi_dmar_hardware_unit,
>>>     				    header);
>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
>>> +						((void *)drhd)+drhd->header.length,
>>> +						dmaru->devices, dmaru->devices_cnt);
>>> +		if (ret)
>>> +			break;
>>> +	}
>>> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>>>     
>>> -		for (scope = (void *)(drhd + 1);
>>> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
>>> -		     scope = ((void *)scope) + scope->length) {
>>> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>>> -				continue;
>>> -			if (scope->enumeration_id != device_number)
>>> -				continue;
>>> +	return ret;
>>>     
>>> -			path = (void *)(scope + 1);
>>> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
>>> -				dev_name(&adev->dev), dmaru->reg_base_addr,
>>> -				scope->bus, path->device, path->function);
>>> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
>>> -				if (tmp == NULL) {
>>> -					dmaru->devices[i].bus = scope->bus;
>>> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
>>> -									    path->function);
>>> -					rcu_assign_pointer(dmaru->devices[i].dev,
>>> -							   get_device(&adev->dev));
>>> -					return;
>>> -				}
>>> -			BUG_ON(i >= dmaru->devices_cnt);
>>> -		}
>>> -	}
>>> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
>>> -		device_number, dev_name(&adev->dev));
>>>     }
>>>     
>>>     static int __init dmar_acpi_dev_scope_init(void) @@ -766,7 +774,7
>>> @@ static int __init dmar_acpi_dev_scope_init(void)
>>>     				       andd->device_name);
>>>     				continue;
>>>     			}
>>> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
>>> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>>>     		}
>>>     	}
>>>     	return 0;
>>> diff --git a/drivers/iommu/intel/iommu.c
>>> b/drivers/iommu/intel/iommu.c index ca557d351518..be1793415326 100644
>>> --- a/drivers/iommu/intel/iommu.c
>>> +++ b/drivers/iommu/intel/iommu.c
>>> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct pci_dev
>>> *dev)
>>>     
>>>     	return ret;
>>>     }
>>> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device
>>> +*adev) {
>>> +	int ret;
>>> +	struct dmar_rmrr_unit *rmrru;
>>> +	struct acpi_dmar_reserved_memory *rmrr;
>>> +
>>> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
>>> +		rmrr = container_of(rmrru->hdr,
>>> +				struct acpi_dmar_reserved_memory,
>>> +				header);
>>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
>>> +						((void *)rmrr) + rmrr->header.length,
>>> +						rmrru->devices, rmrru->devices_cnt);
>>> +		if (ret)
>>> +			break;
>>> +	}
>>> +	return 0;
>>> +}
>>>     
>>>     int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>     {
>>> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>     		rmrr = container_of(rmrru->hdr,
>>>     				    struct acpi_dmar_reserved_memory, header);
>>>     		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>>>     				((void *)rmrr) + rmrr->header.length,
>>>     				rmrr->segment, rmrru->devices,
>>>     				rmrru->devices_cnt);
>>> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct
>>> dmar_pci_notify_info *info)
>>>     
>>>     		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>>>     		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>>> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
>>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>>>     					(void *)atsr + atsr->header.length,
>>>     					atsr->segment, atsru->devices,
>>>     					atsru->devices_cnt);
>>> @@ -4779,6 +4797,26 @@ 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) {
>>> +	int ret;
>>> +	struct iommu_group *group;
>>> +
>>> +	if (pn_dev == NULL) {
>>> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>> +		ret = iommu_probe_device(acpi_device);
>>> +		if (ret) {
>>> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
>>> +			return ret;
>>> +		}
>>> +		return 0;
>>> +	}
>>> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
>>> +	group = iommu_group_get(pn_dev);
>>> +	__acpi_device_create_direct_mappings(group, acpi_device);
>>> +
>>> +	return 0;
>>> +}
>>>     
>>>     static int __init probe_acpi_namespace_devices(void)
>>>     {
>>> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>     			struct acpi_device_physical_node *pn;
>>>     			struct iommu_group *group;
>>>     			struct acpi_device *adev;
>>> +			struct device *pn_dev = NULL;
>>>     
>>>     			if (dev->bus != &acpi_bus_type)
>>>     				continue;
>>> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>>>     					    &adev->physical_node_list, node) {
>>>     				group = iommu_group_get(pn->dev);
>>>     				if (group) {
>>> +					pn_dev = pn->dev;
>>>     					iommu_group_put(group);
>>>     					continue;
>>>     				}
>>> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>>>     				ret = iommu_probe_device(pn->dev);
>>>     				if (ret)
>>>     					break;
>>> +				pn_dev = pn->dev;
>>>     			}
>>> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>>>     			mutex_unlock(&adev->physical_node_lock);
>>>     
>>>     			if (ret)
>>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
>>> 609bd25bf154..4f714a2d5ef7 100644
>>> --- a/drivers/iommu/iommu.c
>>> +++ b/drivers/iommu/iommu.c
>>> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>>>     	return false;
>>>     }
>>>     
>>> +void  __acpi_device_create_direct_mappings(struct iommu_group
>>> +*group, struct device *acpi_device) {
>>> +	iommu_create_device_direct_mappings(group, acpi_device); }
>>> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
>>> +
>>>     /**
>>>      * iommu_group_add_device - add a device to an iommu group
>>>      * @group: the group into which to add the device (reference
>>> should be held) diff --git a/include/linux/dmar.h
>>> b/include/linux/dmar.h index 65565820328a..881ac61a4336 100644
>>> --- a/include/linux/dmar.h
>>> +++ b/include/linux/dmar.h
>>> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>>>     				struct dmar_dev_scope **devices, u16 segment);
>>>     extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>>>     extern void dmar_free_dev_scope(struct dmar_dev_scope **devices,
>>> int *cnt); -extern int dmar_insert_dev_scope(struct
>>> dmar_pci_notify_info *info,
>>> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info
>>> +*info,
>>>     				 void *start, void*end, u16 segment,
>>>     				 struct dmar_dev_scope *devices,
>>>     				 int devices_cnt);
>>> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
>>> +				struct acpi_device *adev, void *start, void *end,
>>> +				struct dmar_dev_scope *devices, int devices_cnt);
>>> +
>>>     extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>>>     				 u16 segment, struct dmar_dev_scope *devices,
>>>     				 int count);
>>> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>>>     extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>     extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>>     extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool
>>> insert);
>>> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct
>>> +acpi_device *adev);
>>>     extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>>>     #else /* !CONFIG_INTEL_IOMMU: */
>>>     static inline int intel_iommu_init(void) { return -ENODEV; } @@
>>> -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>>>     #define	dmar_check_one_atsr		dmar_res_noop
>>>     #define	dmar_release_one_atsr		dmar_res_noop
>>>     
>>> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct
>>> +acpi_device *adev) {
>>> +	return 0;
>>> +}
>>> +
>>>     static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>>     {
>>>     	return 0;
>>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
>>> fee209efb756..9be134775886 100644
>>> --- a/include/linux/iommu.h
>>> +++ b/include/linux/iommu.h
>>> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>>>     extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>>>     			      unsigned long iova, int flags);
>>>     
>>> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
>>> +						struct device *acpi_device);
>>> +
>>>     static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>>>     {
>>>     	if (domain->ops->flush_iotlb_all)
>>>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* 答复: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-03  6:18     ` Lu Baolu
@ 2020-08-03  6:52       ` FelixCui-oc
  2020-08-03  8:25         ` Lu Baolu
  0 siblings, 1 reply; 14+ messages in thread
From: FelixCui-oc @ 2020-08-03  6:52 UTC (permalink / raw)
  To: Lu Baolu, Joerg Roedel, iommu, linux-kernel, David Woodhouse; +Cc: CobeChen-oc

Hi  baolu ,
		Yes ,that's right.
		This patch is to achieve acpi namespace devices to access the RMRR region.

Best regards
Felix cui




-----邮件原件-----
发件人: Lu Baolu <baolu.lu@linux.intel.com> 
发送时间: 2020年8月3日 14:19
收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
抄送: baolu.lu@linux.intel.com; RaymondPang-oc <RaymondPang-oc@zhaoxin.com>; CobeChen-oc <CobeChen-oc@zhaoxin.com>
主题: Re: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR

Hi,

On 2020/8/3 12:40, FelixCui-oc wrote:
> Hi baolu:
> 		Some ACPI devices need to issue dma requests to access the reserved memory area.
> 		So bios uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
> 		At present, there is no analysis in the kernel that the device scope type in RMRR is ACPI_NAMESPACE_DEVICE.
> 		This patch is mainly to add the analysis of the device scope type ACPI_NAMESPACE_DEVICE in RMRR structure and establish identity mapping for > these ACPI devices.

So the problem is "although namespace devices in RMRR have been parsed, but the identity map for those devices aren't created. As the result, the namespace devices fail to access the RMRR region."

Do I understand it right?

Best regards,
baolu

> In addition, some naming changes have been made in patch in order to distinguish acpi device from pci device.
> 		You can refer to the description of type in 8.3.1 device scope in vt-d spec.
> 
> Best regards
> FelixCui-oc
> 
> 
> 
> -----邮件原件-----
> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
> 发送时间: 2020年8月3日 10:32
> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel 
> <joro@8bytes.org>; iommu@lists.linux-foundation.org; 
> linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: baolu.lu@linux.intel.com; Cobe Chen(BJ-RD) <CobeChen@zhaoxin.com>; 
> Raymond Pang(BJ-RD) <RaymondPang@zhaoxin.com>
> 主题: Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
> 
> Hi,
> 
> On 8/2/20 6:07 PM, FelixCuioc wrote:
>> Some ACPI devices require access to the specified reserved memory 
>> region.BIOS report the specified reserved memory region through RMRR 
>> structures.Add analysis of ACPI device in RMRR and establish identity 
>> mapping for ACPI device.
> 
> Can you please add more words about the problem you want to solve? Do you mean some RMRRs are not enumerated correctly? Or, enumerated, but not identity mapped?
> 
> Nit: add version and change log once you refreshed your patch.
> 
>>
>> Reported-by: kernel test robot <lkp@intel.com>
> 
> No need to add this. The problem you want to solve through this patch is not reported by lkp.
> 
> Best regards,
> baolu
> 
>> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
>> ---
>>    drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>>    drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>>    drivers/iommu/iommu.c       |  6 +++
>>    include/linux/dmar.h        | 12 +++++-
>>    include/linux/iommu.h       |  3 ++
>>    5 files changed, 105 insertions(+), 36 deletions(-)
>>
>> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c 
>> index 93e6345f3414..024ca38dba12 100644
>> --- a/drivers/iommu/intel/dmar.c
>> +++ b/drivers/iommu/intel/dmar.c
>> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>>    }
>>    
>>    /* Return: > 0 if match found, 0 if no match found, < 0 if error 
>> happens */ -int dmar_insert_dev_scope(struct dmar_pci_notify_info 
>> *info,
>> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>>    			  void *start, void*end, u16 segment,
>>    			  struct dmar_dev_scope *devices,
>>    			  int devices_cnt)
>> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct 
>> dmar_pci_notify_info *info)
>>    
>>    		drhd = container_of(dmaru->hdr,
>>    				    struct acpi_dmar_hardware_unit, header);
>> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
>> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>>    				((void *)drhd) + drhd->header.length,
>>    				dmaru->segment,
>>    				dmaru->devices, dmaru->devices_cnt); @@ -696,48 +696,56 @@ 
>> dmar_find_matched_drhd_unit(struct pci_dev *dev)
>>    
>>    	return dmaru;
>>    }
>> -
>> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
>> -					      struct acpi_device *adev)
>> +int dmar_acpi_insert_dev_scope(u8 device_number,
>> +				struct acpi_device *adev,
>> +				void *start, void *end,
>> +				struct dmar_dev_scope *devices,
>> +				int devices_cnt)
>>    {
>> -	struct dmar_drhd_unit *dmaru;
>> -	struct acpi_dmar_hardware_unit *drhd;
>>    	struct acpi_dmar_device_scope *scope;
>>    	struct device *tmp;
>>    	int i;
>>    	struct acpi_dmar_pci_path *path;
>>    
>> +	for (; start < end; start += scope->length) {
>> +		scope = start;
>> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>> +			continue;
>> +		if (scope->enumeration_id != device_number)
>> +			continue;
>> +		path = (void *)(scope + 1);
>> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
>> +			if (tmp == NULL) {
>> +				devices[i].bus = scope->bus;
>> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
>> +				rcu_assign_pointer(devices[i].dev,
>> +						   get_device(&adev->dev));
>> +				return 1;
>> +			}
>> +		WARN_ON(i >= devices_cnt);
>> +	}
>> +	return 0;
>> +}
>> +static int dmar_acpi_bus_add_dev(u8 device_number, struct 
>> +acpi_device
>> +*adev) {
>> +	struct dmar_drhd_unit *dmaru;
>> +	struct acpi_dmar_hardware_unit *drhd;
>> +	int ret = 0;
>> +
>>    	for_each_drhd_unit(dmaru) {
>>    		drhd = container_of(dmaru->hdr,
>>    				    struct acpi_dmar_hardware_unit,
>>    				    header);
>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
>> +						((void *)drhd)+drhd->header.length,
>> +						dmaru->devices, dmaru->devices_cnt);
>> +		if (ret)
>> +			break;
>> +	}
>> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>>    
>> -		for (scope = (void *)(drhd + 1);
>> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
>> -		     scope = ((void *)scope) + scope->length) {
>> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>> -				continue;
>> -			if (scope->enumeration_id != device_number)
>> -				continue;
>> +	return ret;
>>    
>> -			path = (void *)(scope + 1);
>> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
>> -				dev_name(&adev->dev), dmaru->reg_base_addr,
>> -				scope->bus, path->device, path->function);
>> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
>> -				if (tmp == NULL) {
>> -					dmaru->devices[i].bus = scope->bus;
>> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
>> -									    path->function);
>> -					rcu_assign_pointer(dmaru->devices[i].dev,
>> -							   get_device(&adev->dev));
>> -					return;
>> -				}
>> -			BUG_ON(i >= dmaru->devices_cnt);
>> -		}
>> -	}
>> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
>> -		device_number, dev_name(&adev->dev));
>>    }
>>    
>>    static int __init dmar_acpi_dev_scope_init(void) @@ -766,7 +774,7 
>> @@ static int __init dmar_acpi_dev_scope_init(void)
>>    				       andd->device_name);
>>    				continue;
>>    			}
>> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
>> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>>    		}
>>    	}
>>    	return 0;
>> diff --git a/drivers/iommu/intel/iommu.c 
>> b/drivers/iommu/intel/iommu.c index ca557d351518..be1793415326 100644
>> --- a/drivers/iommu/intel/iommu.c
>> +++ b/drivers/iommu/intel/iommu.c
>> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct pci_dev
>> *dev)
>>    
>>    	return ret;
>>    }
>> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device
>> +*adev) {
>> +	int ret;
>> +	struct dmar_rmrr_unit *rmrru;
>> +	struct acpi_dmar_reserved_memory *rmrr;
>> +
>> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
>> +		rmrr = container_of(rmrru->hdr,
>> +				struct acpi_dmar_reserved_memory,
>> +				header);
>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
>> +						((void *)rmrr) + rmrr->header.length,
>> +						rmrru->devices, rmrru->devices_cnt);
>> +		if (ret)
>> +			break;
>> +	}
>> +	return 0;
>> +}
>>    
>>    int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>    {
>> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>    		rmrr = container_of(rmrru->hdr,
>>    				    struct acpi_dmar_reserved_memory, header);
>>    		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>>    				((void *)rmrr) + rmrr->header.length,
>>    				rmrr->segment, rmrru->devices,
>>    				rmrru->devices_cnt);
>> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct
>> dmar_pci_notify_info *info)
>>    
>>    		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>>    		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>>    					(void *)atsr + atsr->header.length,
>>    					atsr->segment, atsru->devices,
>>    					atsru->devices_cnt);
>> @@ -4779,6 +4797,26 @@ 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) {
>> +	int ret;
>> +	struct iommu_group *group;
>> +
>> +	if (pn_dev == NULL) {
>> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
>> +		ret = iommu_probe_device(acpi_device);
>> +		if (ret) {
>> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
>> +			return ret;
>> +		}
>> +		return 0;
>> +	}
>> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
>> +	group = iommu_group_get(pn_dev);
>> +	__acpi_device_create_direct_mappings(group, acpi_device);
>> +
>> +	return 0;
>> +}
>>    
>>    static int __init probe_acpi_namespace_devices(void)
>>    {
>> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>>    			struct acpi_device_physical_node *pn;
>>    			struct iommu_group *group;
>>    			struct acpi_device *adev;
>> +			struct device *pn_dev = NULL;
>>    
>>    			if (dev->bus != &acpi_bus_type)
>>    				continue;
>> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>>    					    &adev->physical_node_list, node) {
>>    				group = iommu_group_get(pn->dev);
>>    				if (group) {
>> +					pn_dev = pn->dev;
>>    					iommu_group_put(group);
>>    					continue;
>>    				}
>> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>>    				ret = iommu_probe_device(pn->dev);
>>    				if (ret)
>>    					break;
>> +				pn_dev = pn->dev;
>>    			}
>> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>>    			mutex_unlock(&adev->physical_node_lock);
>>    
>>    			if (ret)
>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
>> 609bd25bf154..4f714a2d5ef7 100644
>> --- a/drivers/iommu/iommu.c
>> +++ b/drivers/iommu/iommu.c
>> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>>    	return false;
>>    }
>>    
>> +void  __acpi_device_create_direct_mappings(struct iommu_group 
>> +*group, struct device *acpi_device) {
>> +	iommu_create_device_direct_mappings(group, acpi_device); } 
>> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
>> +
>>    /**
>>     * iommu_group_add_device - add a device to an iommu group
>>     * @group: the group into which to add the device (reference 
>> should be held) diff --git a/include/linux/dmar.h 
>> b/include/linux/dmar.h index 65565820328a..881ac61a4336 100644
>> --- a/include/linux/dmar.h
>> +++ b/include/linux/dmar.h
>> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>>    				struct dmar_dev_scope **devices, u16 segment);
>>    extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>>    extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, 
>> int *cnt); -extern int dmar_insert_dev_scope(struct 
>> dmar_pci_notify_info *info,
>> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info 
>> +*info,
>>    				 void *start, void*end, u16 segment,
>>    				 struct dmar_dev_scope *devices,
>>    				 int devices_cnt);
>> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
>> +				struct acpi_device *adev, void *start, void *end,
>> +				struct dmar_dev_scope *devices, int devices_cnt);
>> +
>>    extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>>    				 u16 segment, struct dmar_dev_scope *devices,
>>    				 int count);
>> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>>    extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>    extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>    extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool 
>> insert);
>> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
>> +acpi_device *adev);
>>    extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>>    #else /* !CONFIG_INTEL_IOMMU: */
>>    static inline int intel_iommu_init(void) { return -ENODEV; } @@
>> -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>>    #define	dmar_check_one_atsr		dmar_res_noop
>>    #define	dmar_release_one_atsr		dmar_res_noop
>>    
>> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
>> +acpi_device *adev) {
>> +	return 0;
>> +}
>> +
>>    static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>    {
>>    	return 0;
>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
>> fee209efb756..9be134775886 100644
>> --- a/include/linux/iommu.h
>> +++ b/include/linux/iommu.h
>> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>>    extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>>    			      unsigned long iova, int flags);
>>    
>> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
>> +						struct device *acpi_device);
>> +
>>    static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>>    {
>>    	if (domain->ops->flush_iotlb_all)
>>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-03  4:40   ` 答复: " FelixCui-oc
@ 2020-08-03  6:18     ` Lu Baolu
  2020-08-03  6:52       ` 答复: " FelixCui-oc
  0 siblings, 1 reply; 14+ messages in thread
From: Lu Baolu @ 2020-08-03  6:18 UTC (permalink / raw)
  To: FelixCui-oc, Joerg Roedel, iommu, linux-kernel, David Woodhouse
  Cc: CobeChen-oc

Hi,

On 2020/8/3 12:40, FelixCui-oc wrote:
> Hi baolu:
> 		Some ACPI devices need to issue dma requests to access the reserved memory area.
> 		So bios uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
> 		At present, there is no analysis in the kernel that the device scope type in RMRR is ACPI_NAMESPACE_DEVICE.
> 		This patch is mainly to add the analysis of the device scope type ACPI_NAMESPACE_DEVICE in RMRR structure and establish identity mapping for > these ACPI devices.

So the problem is "although namespace devices in RMRR have been parsed,
but the identity map for those devices aren't created. As the result,
the namespace devices fail to access the RMRR region."

Do I understand it right?

Best regards,
baolu

> In addition, some naming changes have been made in patch in order to distinguish acpi device from pci device.
> 		You can refer to the description of type in 8.3.1 device scope in vt-d spec.
> 
> Best regards
> FelixCui-oc
> 
> 
> 
> -----邮件原件-----
> 发件人: Lu Baolu <baolu.lu@linux.intel.com>
> 发送时间: 2020年8月3日 10:32
> 收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
> 抄送: baolu.lu@linux.intel.com; Cobe Chen(BJ-RD) <CobeChen@zhaoxin.com>; Raymond Pang(BJ-RD) <RaymondPang@zhaoxin.com>
> 主题: Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
> 
> Hi,
> 
> On 8/2/20 6:07 PM, FelixCuioc wrote:
>> Some ACPI devices require access to the specified reserved memory
>> region.BIOS report the specified reserved memory region through RMRR
>> structures.Add analysis of ACPI device in RMRR and establish identity
>> mapping for ACPI device.
> 
> Can you please add more words about the problem you want to solve? Do you mean some RMRRs are not enumerated correctly? Or, enumerated, but not identity mapped?
> 
> Nit: add version and change log once you refreshed your patch.
> 
>>
>> Reported-by: kernel test robot <lkp@intel.com>
> 
> No need to add this. The problem you want to solve through this patch is not reported by lkp.
> 
> Best regards,
> baolu
> 
>> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
>> ---
>>    drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>>    drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>>    drivers/iommu/iommu.c       |  6 +++
>>    include/linux/dmar.h        | 12 +++++-
>>    include/linux/iommu.h       |  3 ++
>>    5 files changed, 105 insertions(+), 36 deletions(-)
>>
>> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
>> index 93e6345f3414..024ca38dba12 100644
>> --- a/drivers/iommu/intel/dmar.c
>> +++ b/drivers/iommu/intel/dmar.c
>> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>>    }
>>    
>>    /* Return: > 0 if match found, 0 if no match found, < 0 if error
>> happens */ -int dmar_insert_dev_scope(struct dmar_pci_notify_info
>> *info,
>> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>>    			  void *start, void*end, u16 segment,
>>    			  struct dmar_dev_scope *devices,
>>    			  int devices_cnt)
>> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct
>> dmar_pci_notify_info *info)
>>    
>>    		drhd = container_of(dmaru->hdr,
>>    				    struct acpi_dmar_hardware_unit, header);
>> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
>> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>>    				((void *)drhd) + drhd->header.length,
>>    				dmaru->segment,
>>    				dmaru->devices, dmaru->devices_cnt); @@ -696,48 +696,56 @@
>> dmar_find_matched_drhd_unit(struct pci_dev *dev)
>>    
>>    	return dmaru;
>>    }
>> -
>> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
>> -					      struct acpi_device *adev)
>> +int dmar_acpi_insert_dev_scope(u8 device_number,
>> +				struct acpi_device *adev,
>> +				void *start, void *end,
>> +				struct dmar_dev_scope *devices,
>> +				int devices_cnt)
>>    {
>> -	struct dmar_drhd_unit *dmaru;
>> -	struct acpi_dmar_hardware_unit *drhd;
>>    	struct acpi_dmar_device_scope *scope;
>>    	struct device *tmp;
>>    	int i;
>>    	struct acpi_dmar_pci_path *path;
>>    
>> +	for (; start < end; start += scope->length) {
>> +		scope = start;
>> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>> +			continue;
>> +		if (scope->enumeration_id != device_number)
>> +			continue;
>> +		path = (void *)(scope + 1);
>> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
>> +			if (tmp == NULL) {
>> +				devices[i].bus = scope->bus;
>> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
>> +				rcu_assign_pointer(devices[i].dev,
>> +						   get_device(&adev->dev));
>> +				return 1;
>> +			}
>> +		WARN_ON(i >= devices_cnt);
>> +	}
>> +	return 0;
>> +}
>> +static int dmar_acpi_bus_add_dev(u8 device_number, struct acpi_device
>> +*adev) {
>> +	struct dmar_drhd_unit *dmaru;
>> +	struct acpi_dmar_hardware_unit *drhd;
>> +	int ret = 0;
>> +
>>    	for_each_drhd_unit(dmaru) {
>>    		drhd = container_of(dmaru->hdr,
>>    				    struct acpi_dmar_hardware_unit,
>>    				    header);
>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
>> +						((void *)drhd)+drhd->header.length,
>> +						dmaru->devices, dmaru->devices_cnt);
>> +		if (ret)
>> +			break;
>> +	}
>> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>>    
>> -		for (scope = (void *)(drhd + 1);
>> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
>> -		     scope = ((void *)scope) + scope->length) {
>> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
>> -				continue;
>> -			if (scope->enumeration_id != device_number)
>> -				continue;
>> +	return ret;
>>    
>> -			path = (void *)(scope + 1);
>> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
>> -				dev_name(&adev->dev), dmaru->reg_base_addr,
>> -				scope->bus, path->device, path->function);
>> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
>> -				if (tmp == NULL) {
>> -					dmaru->devices[i].bus = scope->bus;
>> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
>> -									    path->function);
>> -					rcu_assign_pointer(dmaru->devices[i].dev,
>> -							   get_device(&adev->dev));
>> -					return;
>> -				}
>> -			BUG_ON(i >= dmaru->devices_cnt);
>> -		}
>> -	}
>> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
>> -		device_number, dev_name(&adev->dev));
>>    }
>>    
>>    static int __init dmar_acpi_dev_scope_init(void) @@ -766,7 +774,7 @@
>> static int __init dmar_acpi_dev_scope_init(void)
>>    				       andd->device_name);
>>    				continue;
>>    			}
>> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
>> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>>    		}
>>    	}
>>    	return 0;
>> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
>> index ca557d351518..be1793415326 100644
>> --- a/drivers/iommu/intel/iommu.c
>> +++ b/drivers/iommu/intel/iommu.c
>> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct pci_dev
>> *dev)
>>    
>>    	return ret;
>>    }
>> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device
>> +*adev) {
>> +	int ret;
>> +	struct dmar_rmrr_unit *rmrru;
>> +	struct acpi_dmar_reserved_memory *rmrr;
>> +
>> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
>> +		rmrr = container_of(rmrru->hdr,
>> +				struct acpi_dmar_reserved_memory,
>> +				header);
>> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
>> +						((void *)rmrr) + rmrr->header.length,
>> +						rmrru->devices, rmrru->devices_cnt);
>> +		if (ret)
>> +			break;
>> +	}
>> +	return 0;
>> +}
>>    
>>    int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>    {
>> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>    		rmrr = container_of(rmrru->hdr,
>>    				    struct acpi_dmar_reserved_memory, header);
>>    		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>>    				((void *)rmrr) + rmrr->header.length,
>>    				rmrr->segment, rmrru->devices,
>>    				rmrru->devices_cnt);
>> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct
>> dmar_pci_notify_info *info)
>>    
>>    		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>>    		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
>> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
>> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>>    					(void *)atsr + atsr->header.length,
>>    					atsr->segment, atsru->devices,
>>    					atsru->devices_cnt);
>> @@ -4779,6 +4797,26 @@ 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) {
>> +	int ret;
>> +	struct iommu_group *group;
>> +
>> +	if (pn_dev == NULL) {
>> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
>> +		ret = iommu_probe_device(acpi_device);
>> +		if (ret) {
>> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
>> +			return ret;
>> +		}
>> +		return 0;
>> +	}
>> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
>> +	group = iommu_group_get(pn_dev);
>> +	__acpi_device_create_direct_mappings(group, acpi_device);
>> +
>> +	return 0;
>> +}
>>    
>>    static int __init probe_acpi_namespace_devices(void)
>>    {
>> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>>    			struct acpi_device_physical_node *pn;
>>    			struct iommu_group *group;
>>    			struct acpi_device *adev;
>> +			struct device *pn_dev = NULL;
>>    
>>    			if (dev->bus != &acpi_bus_type)
>>    				continue;
>> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>>    					    &adev->physical_node_list, node) {
>>    				group = iommu_group_get(pn->dev);
>>    				if (group) {
>> +					pn_dev = pn->dev;
>>    					iommu_group_put(group);
>>    					continue;
>>    				}
>> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>>    				ret = iommu_probe_device(pn->dev);
>>    				if (ret)
>>    					break;
>> +				pn_dev = pn->dev;
>>    			}
>> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>>    			mutex_unlock(&adev->physical_node_lock);
>>    
>>    			if (ret)
>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index
>> 609bd25bf154..4f714a2d5ef7 100644
>> --- a/drivers/iommu/iommu.c
>> +++ b/drivers/iommu/iommu.c
>> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>>    	return false;
>>    }
>>    
>> +void  __acpi_device_create_direct_mappings(struct iommu_group *group,
>> +struct device *acpi_device) {
>> +	iommu_create_device_direct_mappings(group, acpi_device); }
>> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
>> +
>>    /**
>>     * iommu_group_add_device - add a device to an iommu group
>>     * @group: the group into which to add the device (reference should
>> be held) diff --git a/include/linux/dmar.h b/include/linux/dmar.h
>> index 65565820328a..881ac61a4336 100644
>> --- a/include/linux/dmar.h
>> +++ b/include/linux/dmar.h
>> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>>    				struct dmar_dev_scope **devices, u16 segment);
>>    extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>>    extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int
>> *cnt); -extern int dmar_insert_dev_scope(struct dmar_pci_notify_info
>> *info,
>> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info
>> +*info,
>>    				 void *start, void*end, u16 segment,
>>    				 struct dmar_dev_scope *devices,
>>    				 int devices_cnt);
>> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
>> +				struct acpi_device *adev, void *start, void *end,
>> +				struct dmar_dev_scope *devices, int devices_cnt);
>> +
>>    extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>>    				 u16 segment, struct dmar_dev_scope *devices,
>>    				 int count);
>> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>>    extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>    extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>>    extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool
>> insert);
>> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct
>> +acpi_device *adev);
>>    extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>>    #else /* !CONFIG_INTEL_IOMMU: */
>>    static inline int intel_iommu_init(void) { return -ENODEV; } @@
>> -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>>    #define	dmar_check_one_atsr		dmar_res_noop
>>    #define	dmar_release_one_atsr		dmar_res_noop
>>    
>> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct
>> +acpi_device *adev) {
>> +	return 0;
>> +}
>> +
>>    static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>>    {
>>    	return 0;
>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index
>> fee209efb756..9be134775886 100644
>> --- a/include/linux/iommu.h
>> +++ b/include/linux/iommu.h
>> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>>    extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>>    			      unsigned long iova, int flags);
>>    
>> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
>> +						struct device *acpi_device);
>> +
>>    static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>>    {
>>    	if (domain->ops->flush_iotlb_all)
>>
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* 答复: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-03  2:31 ` Lu Baolu
@ 2020-08-03  4:40   ` FelixCui-oc
  2020-08-03  6:18     ` Lu Baolu
  0 siblings, 1 reply; 14+ messages in thread
From: FelixCui-oc @ 2020-08-03  4:40 UTC (permalink / raw)
  To: Lu Baolu, Joerg Roedel, iommu, linux-kernel, David Woodhouse; +Cc: CobeChen-oc

Hi baolu:
		Some ACPI devices need to issue dma requests to access the reserved memory area.
		So bios uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
		At present, there is no analysis in the kernel that the device scope type in RMRR is ACPI_NAMESPACE_DEVICE.
		This patch is mainly to add the analysis of the device scope type ACPI_NAMESPACE_DEVICE in RMRR structure and establish identity mapping for these ACPI devices. In addition, some naming changes have been made in patch in order to distinguish acpi device from pci device.
		You can refer to the description of type in 8.3.1 device scope in vt-d spec.

Best regards
FelixCui-oc



-----邮件原件-----
发件人: Lu Baolu <baolu.lu@linux.intel.com> 
发送时间: 2020年8月3日 10:32
收件人: FelixCui-oc <FelixCui-oc@zhaoxin.com>; Joerg Roedel <joro@8bytes.org>; iommu@lists.linux-foundation.org; linux-kernel@vger.kernel.org; David Woodhouse <dwmw2@infradead.org>
抄送: baolu.lu@linux.intel.com; Cobe Chen(BJ-RD) <CobeChen@zhaoxin.com>; Raymond Pang(BJ-RD) <RaymondPang@zhaoxin.com>
主题: Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR

Hi,

On 8/2/20 6:07 PM, FelixCuioc wrote:
> Some ACPI devices require access to the specified reserved memory 
> region.BIOS report the specified reserved memory region through RMRR 
> structures.Add analysis of ACPI device in RMRR and establish identity 
> mapping for ACPI device.

Can you please add more words about the problem you want to solve? Do you mean some RMRRs are not enumerated correctly? Or, enumerated, but not identity mapped?

Nit: add version and change log once you refreshed your patch.

> 
> Reported-by: kernel test robot <lkp@intel.com>

No need to add this. The problem you want to solve through this patch is not reported by lkp.

Best regards,
baolu

> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
> ---
>   drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>   drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>   drivers/iommu/iommu.c       |  6 +++
>   include/linux/dmar.h        | 12 +++++-
>   include/linux/iommu.h       |  3 ++
>   5 files changed, 105 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c 
> index 93e6345f3414..024ca38dba12 100644
> --- a/drivers/iommu/intel/dmar.c
> +++ b/drivers/iommu/intel/dmar.c
> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>   }
>   
>   /* Return: > 0 if match found, 0 if no match found, < 0 if error 
> happens */ -int dmar_insert_dev_scope(struct dmar_pci_notify_info 
> *info,
> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>   			  void *start, void*end, u16 segment,
>   			  struct dmar_dev_scope *devices,
>   			  int devices_cnt)
> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct 
> dmar_pci_notify_info *info)
>   
>   		drhd = container_of(dmaru->hdr,
>   				    struct acpi_dmar_hardware_unit, header);
> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>   				((void *)drhd) + drhd->header.length,
>   				dmaru->segment,
>   				dmaru->devices, dmaru->devices_cnt); @@ -696,48 +696,56 @@ 
> dmar_find_matched_drhd_unit(struct pci_dev *dev)
>   
>   	return dmaru;
>   }
> -
> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
> -					      struct acpi_device *adev)
> +int dmar_acpi_insert_dev_scope(u8 device_number,
> +				struct acpi_device *adev,
> +				void *start, void *end,
> +				struct dmar_dev_scope *devices,
> +				int devices_cnt)
>   {
> -	struct dmar_drhd_unit *dmaru;
> -	struct acpi_dmar_hardware_unit *drhd;
>   	struct acpi_dmar_device_scope *scope;
>   	struct device *tmp;
>   	int i;
>   	struct acpi_dmar_pci_path *path;
>   
> +	for (; start < end; start += scope->length) {
> +		scope = start;
> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
> +			continue;
> +		if (scope->enumeration_id != device_number)
> +			continue;
> +		path = (void *)(scope + 1);
> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
> +			if (tmp == NULL) {
> +				devices[i].bus = scope->bus;
> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
> +				rcu_assign_pointer(devices[i].dev,
> +						   get_device(&adev->dev));
> +				return 1;
> +			}
> +		WARN_ON(i >= devices_cnt);
> +	}
> +	return 0;
> +}
> +static int dmar_acpi_bus_add_dev(u8 device_number, struct acpi_device 
> +*adev) {
> +	struct dmar_drhd_unit *dmaru;
> +	struct acpi_dmar_hardware_unit *drhd;
> +	int ret = 0;
> +
>   	for_each_drhd_unit(dmaru) {
>   		drhd = container_of(dmaru->hdr,
>   				    struct acpi_dmar_hardware_unit,
>   				    header);
> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
> +						((void *)drhd)+drhd->header.length,
> +						dmaru->devices, dmaru->devices_cnt);
> +		if (ret)
> +			break;
> +	}
> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>   
> -		for (scope = (void *)(drhd + 1);
> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
> -		     scope = ((void *)scope) + scope->length) {
> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
> -				continue;
> -			if (scope->enumeration_id != device_number)
> -				continue;
> +	return ret;
>   
> -			path = (void *)(scope + 1);
> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
> -				dev_name(&adev->dev), dmaru->reg_base_addr,
> -				scope->bus, path->device, path->function);
> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
> -				if (tmp == NULL) {
> -					dmaru->devices[i].bus = scope->bus;
> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
> -									    path->function);
> -					rcu_assign_pointer(dmaru->devices[i].dev,
> -							   get_device(&adev->dev));
> -					return;
> -				}
> -			BUG_ON(i >= dmaru->devices_cnt);
> -		}
> -	}
> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
> -		device_number, dev_name(&adev->dev));
>   }
>   
>   static int __init dmar_acpi_dev_scope_init(void) @@ -766,7 +774,7 @@ 
> static int __init dmar_acpi_dev_scope_init(void)
>   				       andd->device_name);
>   				continue;
>   			}
> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>   		}
>   	}
>   	return 0;
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c 
> index ca557d351518..be1793415326 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct pci_dev 
> *dev)
>   
>   	return ret;
>   }
> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device 
> +*adev) {
> +	int ret;
> +	struct dmar_rmrr_unit *rmrru;
> +	struct acpi_dmar_reserved_memory *rmrr;
> +
> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
> +		rmrr = container_of(rmrru->hdr,
> +				struct acpi_dmar_reserved_memory,
> +				header);
> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
> +						((void *)rmrr) + rmrr->header.length,
> +						rmrru->devices, rmrru->devices_cnt);
> +		if (ret)
> +			break;
> +	}
> +	return 0;
> +}
>   
>   int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>   {
> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>   		rmrr = container_of(rmrru->hdr,
>   				    struct acpi_dmar_reserved_memory, header);
>   		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>   				((void *)rmrr) + rmrr->header.length,
>   				rmrr->segment, rmrru->devices,
>   				rmrru->devices_cnt);
> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct 
> dmar_pci_notify_info *info)
>   
>   		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>   		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>   					(void *)atsr + atsr->header.length,
>   					atsr->segment, atsru->devices,
>   					atsru->devices_cnt);
> @@ -4779,6 +4797,26 @@ 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) {
> +	int ret;
> +	struct iommu_group *group;
> +
> +	if (pn_dev == NULL) {
> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
> +		ret = iommu_probe_device(acpi_device);
> +		if (ret) {
> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
> +			return ret;
> +		}
> +		return 0;
> +	}
> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
> +	group = iommu_group_get(pn_dev);
> +	__acpi_device_create_direct_mappings(group, acpi_device);
> +
> +	return 0;
> +}
>   
>   static int __init probe_acpi_namespace_devices(void)
>   {
> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>   			struct acpi_device_physical_node *pn;
>   			struct iommu_group *group;
>   			struct acpi_device *adev;
> +			struct device *pn_dev = NULL;
>   
>   			if (dev->bus != &acpi_bus_type)
>   				continue;
> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>   					    &adev->physical_node_list, node) {
>   				group = iommu_group_get(pn->dev);
>   				if (group) {
> +					pn_dev = pn->dev;
>   					iommu_group_put(group);
>   					continue;
>   				}
> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>   				ret = iommu_probe_device(pn->dev);
>   				if (ret)
>   					break;
> +				pn_dev = pn->dev;
>   			}
> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>   			mutex_unlock(&adev->physical_node_lock);
>   
>   			if (ret)
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 
> 609bd25bf154..4f714a2d5ef7 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>   	return false;
>   }
>   
> +void  __acpi_device_create_direct_mappings(struct iommu_group *group, 
> +struct device *acpi_device) {
> +	iommu_create_device_direct_mappings(group, acpi_device); } 
> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
> +
>   /**
>    * iommu_group_add_device - add a device to an iommu group
>    * @group: the group into which to add the device (reference should 
> be held) diff --git a/include/linux/dmar.h b/include/linux/dmar.h 
> index 65565820328a..881ac61a4336 100644
> --- a/include/linux/dmar.h
> +++ b/include/linux/dmar.h
> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>   				struct dmar_dev_scope **devices, u16 segment);
>   extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>   extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int 
> *cnt); -extern int dmar_insert_dev_scope(struct dmar_pci_notify_info 
> *info,
> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info 
> +*info,
>   				 void *start, void*end, u16 segment,
>   				 struct dmar_dev_scope *devices,
>   				 int devices_cnt);
> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
> +				struct acpi_device *adev, void *start, void *end,
> +				struct dmar_dev_scope *devices, int devices_cnt);
> +
>   extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>   				 u16 segment, struct dmar_dev_scope *devices,
>   				 int count);
> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>   extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>   extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>   extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool 
> insert);
> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
> +acpi_device *adev);
>   extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>   #else /* !CONFIG_INTEL_IOMMU: */
>   static inline int intel_iommu_init(void) { return -ENODEV; } @@ 
> -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>   #define	dmar_check_one_atsr		dmar_res_noop
>   #define	dmar_release_one_atsr		dmar_res_noop
>   
> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct 
> +acpi_device *adev) {
> +	return 0;
> +}
> +
>   static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>   {
>   	return 0;
> diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 
> fee209efb756..9be134775886 100644
> --- a/include/linux/iommu.h
> +++ b/include/linux/iommu.h
> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>   extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>   			      unsigned long iova, int flags);
>   
> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
> +						struct device *acpi_device);
> +
>   static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>   {
>   	if (domain->ops->flush_iotlb_all)
> 
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
  2020-08-02 10:07 FelixCuioc
@ 2020-08-03  2:31 ` Lu Baolu
  2020-08-03  4:40   ` 答复: " FelixCui-oc
  0 siblings, 1 reply; 14+ messages in thread
From: Lu Baolu @ 2020-08-03  2:31 UTC (permalink / raw)
  To: FelixCuioc, Joerg Roedel, iommu, linux-kernel, David Woodhouse
  Cc: CobeChen, RaymondPang

Hi,

On 8/2/20 6:07 PM, FelixCuioc wrote:
> Some ACPI devices require access to the specified reserved memory
> region.BIOS report the specified reserved memory region through
> RMRR structures.Add analysis of ACPI device in RMRR and establish
> identity mapping for ACPI device.

Can you please add more words about the problem you want to solve? Do
you mean some RMRRs are not enumerated correctly? Or, enumerated, but
not identity mapped?

Nit: add version and change log once you refreshed your patch.

> 
> Reported-by: kernel test robot <lkp@intel.com>

No need to add this. The problem you want to solve through this patch is
not reported by lkp.

Best regards,
baolu

> Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
> ---
>   drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
>   drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
>   drivers/iommu/iommu.c       |  6 +++
>   include/linux/dmar.h        | 12 +++++-
>   include/linux/iommu.h       |  3 ++
>   5 files changed, 105 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> index 93e6345f3414..024ca38dba12 100644
> --- a/drivers/iommu/intel/dmar.c
> +++ b/drivers/iommu/intel/dmar.c
> @@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
>   }
>   
>   /* Return: > 0 if match found, 0 if no match found, < 0 if error happens */
> -int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
> +int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>   			  void *start, void*end, u16 segment,
>   			  struct dmar_dev_scope *devices,
>   			  int devices_cnt)
> @@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct dmar_pci_notify_info *info)
>   
>   		drhd = container_of(dmaru->hdr,
>   				    struct acpi_dmar_hardware_unit, header);
> -		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
> +		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
>   				((void *)drhd) + drhd->header.length,
>   				dmaru->segment,
>   				dmaru->devices, dmaru->devices_cnt);
> @@ -696,48 +696,56 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
>   
>   	return dmaru;
>   }
> -
> -static void __init dmar_acpi_insert_dev_scope(u8 device_number,
> -					      struct acpi_device *adev)
> +int dmar_acpi_insert_dev_scope(u8 device_number,
> +				struct acpi_device *adev,
> +				void *start, void *end,
> +				struct dmar_dev_scope *devices,
> +				int devices_cnt)
>   {
> -	struct dmar_drhd_unit *dmaru;
> -	struct acpi_dmar_hardware_unit *drhd;
>   	struct acpi_dmar_device_scope *scope;
>   	struct device *tmp;
>   	int i;
>   	struct acpi_dmar_pci_path *path;
>   
> +	for (; start < end; start += scope->length) {
> +		scope = start;
> +		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
> +			continue;
> +		if (scope->enumeration_id != device_number)
> +			continue;
> +		path = (void *)(scope + 1);
> +		for_each_dev_scope(devices, devices_cnt, i, tmp)
> +			if (tmp == NULL) {
> +				devices[i].bus = scope->bus;
> +				devices[i].devfn = PCI_DEVFN(path->device, path->function);
> +				rcu_assign_pointer(devices[i].dev,
> +						   get_device(&adev->dev));
> +				return 1;
> +			}
> +		WARN_ON(i >= devices_cnt);
> +	}
> +	return 0;
> +}
> +static int dmar_acpi_bus_add_dev(u8 device_number, struct acpi_device *adev)
> +{
> +	struct dmar_drhd_unit *dmaru;
> +	struct acpi_dmar_hardware_unit *drhd;
> +	int ret = 0;
> +
>   	for_each_drhd_unit(dmaru) {
>   		drhd = container_of(dmaru->hdr,
>   				    struct acpi_dmar_hardware_unit,
>   				    header);
> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
> +						((void *)drhd)+drhd->header.length,
> +						dmaru->devices, dmaru->devices_cnt);
> +		if (ret)
> +			break;
> +	}
> +	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
>   
> -		for (scope = (void *)(drhd + 1);
> -		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
> -		     scope = ((void *)scope) + scope->length) {
> -			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
> -				continue;
> -			if (scope->enumeration_id != device_number)
> -				continue;
> +	return ret;
>   
> -			path = (void *)(scope + 1);
> -			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
> -				dev_name(&adev->dev), dmaru->reg_base_addr,
> -				scope->bus, path->device, path->function);
> -			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
> -				if (tmp == NULL) {
> -					dmaru->devices[i].bus = scope->bus;
> -					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
> -									    path->function);
> -					rcu_assign_pointer(dmaru->devices[i].dev,
> -							   get_device(&adev->dev));
> -					return;
> -				}
> -			BUG_ON(i >= dmaru->devices_cnt);
> -		}
> -	}
> -	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
> -		device_number, dev_name(&adev->dev));
>   }
>   
>   static int __init dmar_acpi_dev_scope_init(void)
> @@ -766,7 +774,7 @@ static int __init dmar_acpi_dev_scope_init(void)
>   				       andd->device_name);
>   				continue;
>   			}
> -			dmar_acpi_insert_dev_scope(andd->device_number, adev);
> +			dmar_acpi_bus_add_dev(andd->device_number, adev);
>   		}
>   	}
>   	return 0;
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index ca557d351518..be1793415326 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)
>   
>   	return ret;
>   }
> +int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev)
> +{
> +	int ret;
> +	struct dmar_rmrr_unit *rmrru;
> +	struct acpi_dmar_reserved_memory *rmrr;
> +
> +	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
> +		rmrr = container_of(rmrru->hdr,
> +				struct acpi_dmar_reserved_memory,
> +				header);
> +		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
> +						((void *)rmrr) + rmrr->header.length,
> +						rmrru->devices, rmrru->devices_cnt);
> +		if (ret)
> +			break;
> +	}
> +	return 0;
> +}
>   
>   int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>   {
> @@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>   		rmrr = container_of(rmrru->hdr,
>   				    struct acpi_dmar_reserved_memory, header);
>   		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
> -			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
> +			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
>   				((void *)rmrr) + rmrr->header.length,
>   				rmrr->segment, rmrru->devices,
>   				rmrru->devices_cnt);
> @@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>   
>   		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
>   		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
> -			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
> +			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
>   					(void *)atsr + atsr->header.length,
>   					atsr->segment, atsru->devices,
>   					atsru->devices_cnt);
> @@ -4779,6 +4797,26 @@ 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)
> +{
> +	int ret;
> +	struct iommu_group *group;
> +
> +	if (pn_dev == NULL) {
> +		acpi_device->bus->iommu_ops = &intel_iommu_ops;
> +		ret = iommu_probe_device(acpi_device);
> +		if (ret) {
> +			pr_err("acpi_device probe fail! ret:%d\n", ret);
> +			return ret;
> +		}
> +		return 0;
> +	}
> +	acpi_device->bus->iommu_ops = &intel_iommu_ops;
> +	group = iommu_group_get(pn_dev);
> +	__acpi_device_create_direct_mappings(group, acpi_device);
> +
> +	return 0;
> +}
>   
>   static int __init probe_acpi_namespace_devices(void)
>   {
> @@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
>   			struct acpi_device_physical_node *pn;
>   			struct iommu_group *group;
>   			struct acpi_device *adev;
> +			struct device *pn_dev = NULL;
>   
>   			if (dev->bus != &acpi_bus_type)
>   				continue;
> @@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
>   					    &adev->physical_node_list, node) {
>   				group = iommu_group_get(pn->dev);
>   				if (group) {
> +					pn_dev = pn->dev;
>   					iommu_group_put(group);
>   					continue;
>   				}
> @@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
>   				ret = iommu_probe_device(pn->dev);
>   				if (ret)
>   					break;
> +				pn_dev = pn->dev;
>   			}
> +			ret = acpi_device_create_direct_mappings(pn_dev, dev);
>   			mutex_unlock(&adev->physical_node_lock);
>   
>   			if (ret)
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 609bd25bf154..4f714a2d5ef7 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
>   	return false;
>   }
>   
> +void  __acpi_device_create_direct_mappings(struct iommu_group *group, struct device *acpi_device)
> +{
> +	iommu_create_device_direct_mappings(group, acpi_device);
> +}
> +EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
> +
>   /**
>    * iommu_group_add_device - add a device to an iommu group
>    * @group: the group into which to add the device (reference should be held)
> diff --git a/include/linux/dmar.h b/include/linux/dmar.h
> index 65565820328a..881ac61a4336 100644
> --- a/include/linux/dmar.h
> +++ b/include/linux/dmar.h
> @@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
>   				struct dmar_dev_scope **devices, u16 segment);
>   extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
>   extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt);
> -extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
> +extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
>   				 void *start, void*end, u16 segment,
>   				 struct dmar_dev_scope *devices,
>   				 int devices_cnt);
> +extern int dmar_acpi_insert_dev_scope(u8 device_number,
> +				struct acpi_device *adev, void *start, void *end,
> +				struct dmar_dev_scope *devices, int devices_cnt);
> +
>   extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
>   				 u16 segment, struct dmar_dev_scope *devices,
>   				 int count);
> @@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
>   extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>   extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
>   extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert);
> +extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev);
>   extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
>   #else /* !CONFIG_INTEL_IOMMU: */
>   static inline int intel_iommu_init(void) { return -ENODEV; }
> @@ -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
>   #define	dmar_check_one_atsr		dmar_res_noop
>   #define	dmar_release_one_atsr		dmar_res_noop
>   
> +static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev)
> +{
> +	return 0;
> +}
> +
>   static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
>   {
>   	return 0;
> diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> index fee209efb756..9be134775886 100644
> --- a/include/linux/iommu.h
> +++ b/include/linux/iommu.h
> @@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
>   extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
>   			      unsigned long iova, int flags);
>   
> +extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
> +						struct device *acpi_device);
> +
>   static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
>   {
>   	if (domain->ops->flush_iotlb_all)
> 
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] iommu/vt-d:Add support for ACPI device in RMRR
@ 2020-08-02 10:07 FelixCuioc
  2020-08-03  2:31 ` Lu Baolu
  0 siblings, 1 reply; 14+ messages in thread
From: FelixCuioc @ 2020-08-02 10:07 UTC (permalink / raw)
  To: Joerg Roedel, iommu, linux-kernel, David Woodhouse, Lu Baolu
  Cc: CobeChen, RaymondPang

Some ACPI devices require access to the specified reserved memory
region.BIOS report the specified reserved memory region through
RMRR structures.Add analysis of ACPI device in RMRR and establish
identity mapping for ACPI device.

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: FelixCuioc <FelixCui-oc@zhaoxin.com>
---
 drivers/iommu/intel/dmar.c  | 74 ++++++++++++++++++++-----------------
 drivers/iommu/intel/iommu.c | 46 ++++++++++++++++++++++-
 drivers/iommu/iommu.c       |  6 +++
 include/linux/dmar.h        | 12 +++++-
 include/linux/iommu.h       |  3 ++
 5 files changed, 105 insertions(+), 36 deletions(-)

diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index 93e6345f3414..024ca38dba12 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus,
 }
 
 /* Return: > 0 if match found, 0 if no match found, < 0 if error happens */
-int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
+int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
 			  void *start, void*end, u16 segment,
 			  struct dmar_dev_scope *devices,
 			  int devices_cnt)
@@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct dmar_pci_notify_info *info)
 
 		drhd = container_of(dmaru->hdr,
 				    struct acpi_dmar_hardware_unit, header);
-		ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
+		ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
 				((void *)drhd) + drhd->header.length,
 				dmaru->segment,
 				dmaru->devices, dmaru->devices_cnt);
@@ -696,48 +696,56 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
 
 	return dmaru;
 }
-
-static void __init dmar_acpi_insert_dev_scope(u8 device_number,
-					      struct acpi_device *adev)
+int dmar_acpi_insert_dev_scope(u8 device_number,
+				struct acpi_device *adev,
+				void *start, void *end,
+				struct dmar_dev_scope *devices,
+				int devices_cnt)
 {
-	struct dmar_drhd_unit *dmaru;
-	struct acpi_dmar_hardware_unit *drhd;
 	struct acpi_dmar_device_scope *scope;
 	struct device *tmp;
 	int i;
 	struct acpi_dmar_pci_path *path;
 
+	for (; start < end; start += scope->length) {
+		scope = start;
+		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
+			continue;
+		if (scope->enumeration_id != device_number)
+			continue;
+		path = (void *)(scope + 1);
+		for_each_dev_scope(devices, devices_cnt, i, tmp)
+			if (tmp == NULL) {
+				devices[i].bus = scope->bus;
+				devices[i].devfn = PCI_DEVFN(path->device, path->function);
+				rcu_assign_pointer(devices[i].dev,
+						   get_device(&adev->dev));
+				return 1;
+			}
+		WARN_ON(i >= devices_cnt);
+	}
+	return 0;
+}
+static int dmar_acpi_bus_add_dev(u8 device_number, struct acpi_device *adev)
+{
+	struct dmar_drhd_unit *dmaru;
+	struct acpi_dmar_hardware_unit *drhd;
+	int ret = 0;
+
 	for_each_drhd_unit(dmaru) {
 		drhd = container_of(dmaru->hdr,
 				    struct acpi_dmar_hardware_unit,
 				    header);
+		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
+						((void *)drhd)+drhd->header.length,
+						dmaru->devices, dmaru->devices_cnt);
+		if (ret)
+			break;
+	}
+	ret = dmar_rmrr_add_acpi_dev(device_number, adev);
 
-		for (scope = (void *)(drhd + 1);
-		     (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
-		     scope = ((void *)scope) + scope->length) {
-			if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
-				continue;
-			if (scope->enumeration_id != device_number)
-				continue;
+	return ret;
 
-			path = (void *)(scope + 1);
-			pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n",
-				dev_name(&adev->dev), dmaru->reg_base_addr,
-				scope->bus, path->device, path->function);
-			for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp)
-				if (tmp == NULL) {
-					dmaru->devices[i].bus = scope->bus;
-					dmaru->devices[i].devfn = PCI_DEVFN(path->device,
-									    path->function);
-					rcu_assign_pointer(dmaru->devices[i].dev,
-							   get_device(&adev->dev));
-					return;
-				}
-			BUG_ON(i >= dmaru->devices_cnt);
-		}
-	}
-	pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n",
-		device_number, dev_name(&adev->dev));
 }
 
 static int __init dmar_acpi_dev_scope_init(void)
@@ -766,7 +774,7 @@ static int __init dmar_acpi_dev_scope_init(void)
 				       andd->device_name);
 				continue;
 			}
-			dmar_acpi_insert_dev_scope(andd->device_number, adev);
+			dmar_acpi_bus_add_dev(andd->device_number, adev);
 		}
 	}
 	return 0;
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index ca557d351518..be1793415326 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4507,6 +4507,24 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev)
 
 	return ret;
 }
+int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev)
+{
+	int ret;
+	struct dmar_rmrr_unit *rmrru;
+	struct acpi_dmar_reserved_memory *rmrr;
+
+	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
+		rmrr = container_of(rmrru->hdr,
+				struct acpi_dmar_reserved_memory,
+				header);
+		ret = dmar_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
+						((void *)rmrr) + rmrr->header.length,
+						rmrru->devices, rmrru->devices_cnt);
+		if (ret)
+			break;
+	}
+	return 0;
+}
 
 int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
 {
@@ -4523,7 +4541,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
 		rmrr = container_of(rmrru->hdr,
 				    struct acpi_dmar_reserved_memory, header);
 		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
-			ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
+			ret = dmar_pci_insert_dev_scope(info, (void *)(rmrr + 1),
 				((void *)rmrr) + rmrr->header.length,
 				rmrr->segment, rmrru->devices,
 				rmrru->devices_cnt);
@@ -4541,7 +4559,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
 
 		atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
 		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
-			ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
+			ret = dmar_pci_insert_dev_scope(info, (void *)(atsr + 1),
 					(void *)atsr + atsr->header.length,
 					atsr->segment, atsru->devices,
 					atsru->devices_cnt);
@@ -4779,6 +4797,26 @@ 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)
+{
+	int ret;
+	struct iommu_group *group;
+
+	if (pn_dev == NULL) {
+		acpi_device->bus->iommu_ops = &intel_iommu_ops;
+		ret = iommu_probe_device(acpi_device);
+		if (ret) {
+			pr_err("acpi_device probe fail! ret:%d\n", ret);
+			return ret;
+		}
+		return 0;
+	}
+	acpi_device->bus->iommu_ops = &intel_iommu_ops;
+	group = iommu_group_get(pn_dev);
+	__acpi_device_create_direct_mappings(group, acpi_device);
+
+	return 0;
+}
 
 static int __init probe_acpi_namespace_devices(void)
 {
@@ -4794,6 +4832,7 @@ static int __init probe_acpi_namespace_devices(void)
 			struct acpi_device_physical_node *pn;
 			struct iommu_group *group;
 			struct acpi_device *adev;
+			struct device *pn_dev = NULL;
 
 			if (dev->bus != &acpi_bus_type)
 				continue;
@@ -4804,6 +4843,7 @@ static int __init probe_acpi_namespace_devices(void)
 					    &adev->physical_node_list, node) {
 				group = iommu_group_get(pn->dev);
 				if (group) {
+					pn_dev = pn->dev;
 					iommu_group_put(group);
 					continue;
 				}
@@ -4812,7 +4852,9 @@ static int __init probe_acpi_namespace_devices(void)
 				ret = iommu_probe_device(pn->dev);
 				if (ret)
 					break;
+				pn_dev = pn->dev;
 			}
+			ret = acpi_device_create_direct_mappings(pn_dev, dev);
 			mutex_unlock(&adev->physical_node_lock);
 
 			if (ret)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 609bd25bf154..4f714a2d5ef7 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain *domain,
 	return false;
 }
 
+void  __acpi_device_create_direct_mappings(struct iommu_group *group, struct device *acpi_device)
+{
+	iommu_create_device_direct_mappings(group, acpi_device);
+}
+EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
+
 /**
  * iommu_group_add_device - add a device to an iommu group
  * @group: the group into which to add the device (reference should be held)
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 65565820328a..881ac61a4336 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -113,10 +113,14 @@ extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
 				struct dmar_dev_scope **devices, u16 segment);
 extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
 extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt);
-extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
+extern int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
 				 void *start, void*end, u16 segment,
 				 struct dmar_dev_scope *devices,
 				 int devices_cnt);
+extern int dmar_acpi_insert_dev_scope(u8 device_number,
+				struct acpi_device *adev, void *start, void *end,
+				struct dmar_dev_scope *devices, int devices_cnt);
+
 extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
 				 u16 segment, struct dmar_dev_scope *devices,
 				 int count);
@@ -140,6 +144,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
 extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
 extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
 extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert);
+extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev);
 extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
 #else /* !CONFIG_INTEL_IOMMU: */
 static inline int intel_iommu_init(void) { return -ENODEV; }
@@ -150,6 +155,11 @@ static inline void intel_iommu_shutdown(void) { }
 #define	dmar_check_one_atsr		dmar_res_noop
 #define	dmar_release_one_atsr		dmar_res_noop
 
+static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev)
+{
+	return 0;
+}
+
 static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
 {
 	return 0;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index fee209efb756..9be134775886 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
 extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
 			      unsigned long iova, int flags);
 
+extern void __acpi_device_create_direct_mappings(struct iommu_group *group,
+						struct device *acpi_device);
+
 static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
 {
 	if (domain->ops->flush_iotlb_all)
-- 
2.17.1

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, back to index

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-28 10:06 [PATCH] iommu/vt-d:Add support for ACPI device in RMRR FelixCuioc
2020-07-31  9:06 ` kernel test robot
2020-08-02 10:07 FelixCuioc
2020-08-03  2:31 ` Lu Baolu
2020-08-03  4:40   ` 答复: " FelixCui-oc
2020-08-03  6:18     ` Lu Baolu
2020-08-03  6:52       ` 答复: " FelixCui-oc
2020-08-03  8:25         ` Lu Baolu
2020-08-03  9:01           ` 答复: " FelixCui-oc
2020-08-03  9:41           ` FelixCui-oc
2020-08-04  1:11             ` Lu Baolu
2020-08-04  3:11               ` 答复: " FelixCui-oc
2020-08-05  2:56                 ` Lu Baolu
2020-08-05  7:37                   ` 答复: " FelixCui-oc

IOMMU Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-iommu/0 linux-iommu/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-iommu linux-iommu/ https://lore.kernel.org/linux-iommu \
		iommu@lists.linux-foundation.org
	public-inbox-index linux-iommu

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.linux-foundation.lists.iommu


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git