linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] iommu/vt-d: Add support for ACPI/SATC table
@ 2021-02-03  9:33 Lu Baolu
  2021-02-03  9:33 ` [PATCH v2 1/3] iommu/vt-d: Add new enum value and structure for SATC Lu Baolu
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Lu Baolu @ 2021-02-03  9:33 UTC (permalink / raw)
  To: Joerg Roedel
  Cc: Will Deacon, Yian Chen, Ashok Raj, iommu, linux-kernel, Lu Baolu

The Intel VT-d specification v3.2 comes with a new ACPI SATC (SoC-
Integrated Address Translation Cache) reporting structure. The SoC
integrated device enumerated in this table has a functional
requirement to enable its ATC (Address Translation Cache) via the
ATS capability for device operation.

This patch set adds the code to parse the SATC table, enumerates the
devices in it and satisfies the ATS requirement for them. Please help
to review. I will queue it in VT-d update for v5.12 if no objection.

Yian Chen (3):
  iommu/vt-d: Add new enum value and structure for SATC
  iommu/vt-d: Parse SATC reporting structure
  iommu/vt-d: Apply SATC policy

 drivers/iommu/intel/dmar.c  |   8 ++
 drivers/iommu/intel/iommu.c | 162 +++++++++++++++++++++++++++++++++++-
 include/acpi/actbl1.h       |  11 ++-
 include/linux/dmar.h        |   2 +
 4 files changed, 178 insertions(+), 5 deletions(-)

-- 
2.25.1


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

* [PATCH v2 1/3] iommu/vt-d: Add new enum value and structure for SATC
  2021-02-03  9:33 [PATCH v2 0/3] iommu/vt-d: Add support for ACPI/SATC table Lu Baolu
@ 2021-02-03  9:33 ` Lu Baolu
  2021-02-03  9:33 ` [PATCH v2 2/3] iommu/vt-d: Parse SATC reporting structure Lu Baolu
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Lu Baolu @ 2021-02-03  9:33 UTC (permalink / raw)
  To: Joerg Roedel
  Cc: Will Deacon, Yian Chen, Ashok Raj, iommu, linux-kernel, Lu Baolu

From: Yian Chen <yian.chen@intel.com>

Starting from Intel Platform VT-d v3.2, BIOS may provide new remapping
structure SATC for SOC integrated devices, according to section 8.8 of
Intel VT-d architecture specification v3.2. The SATC structure reports
a list of the devices that require ATS for normal device operation. It
is a functional requirement that these devices will not work without OS
enabling ATS capability.

This patch introduces the new enum value and structure to represent the
remapping information. Kernel should parse the information from the
reporting structure and enable ATC for the devices as needed.

Signed-off-by: Yian Chen <yian.chen@intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
 include/acpi/actbl1.h | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index 43549547ed3e..c38e08cf1b9e 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -514,7 +514,8 @@ enum acpi_dmar_type {
 	ACPI_DMAR_TYPE_ROOT_ATS = 2,
 	ACPI_DMAR_TYPE_HARDWARE_AFFINITY = 3,
 	ACPI_DMAR_TYPE_NAMESPACE = 4,
-	ACPI_DMAR_TYPE_RESERVED = 5	/* 5 and greater are reserved */
+	ACPI_DMAR_TYPE_SATC = 5,
+	ACPI_DMAR_TYPE_RESERVED = 6	/* 6 and greater are reserved */
 };
 
 /* DMAR Device Scope structure */
@@ -607,6 +608,14 @@ struct acpi_dmar_andd {
 	char device_name[1];
 };
 
+/* 5: SOC Integrated Address Translation Cache Reporting Structure */
+
+struct acpi_dmar_satc {
+	struct acpi_dmar_header header;
+	u8 flags;
+	u8 reserved;
+	u16 segment;
+};
 /*******************************************************************************
  *
  * DRTM - Dynamic Root of Trust for Measurement table
-- 
2.25.1


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

* [PATCH v2 2/3] iommu/vt-d: Parse SATC reporting structure
  2021-02-03  9:33 [PATCH v2 0/3] iommu/vt-d: Add support for ACPI/SATC table Lu Baolu
  2021-02-03  9:33 ` [PATCH v2 1/3] iommu/vt-d: Add new enum value and structure for SATC Lu Baolu
@ 2021-02-03  9:33 ` Lu Baolu
  2021-02-03  9:33 ` [PATCH v2 3/3] iommu/vt-d: Apply SATC policy Lu Baolu
  2021-02-03  9:48 ` [PATCH v2 0/3] iommu/vt-d: Add support for ACPI/SATC table Lu Baolu
  3 siblings, 0 replies; 7+ messages in thread
From: Lu Baolu @ 2021-02-03  9:33 UTC (permalink / raw)
  To: Joerg Roedel
  Cc: Will Deacon, Yian Chen, Ashok Raj, iommu, linux-kernel, Lu Baolu

From: Yian Chen <yian.chen@intel.com>

Software should parse every SATC table and all devices in the tables
reported by the BIOS and keep the information in kernel list for further
reference.

Signed-off-by: Yian Chen <yian.chen@intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
 drivers/iommu/intel/dmar.c  |  8 ++++
 drivers/iommu/intel/iommu.c | 89 +++++++++++++++++++++++++++++++++++++
 include/linux/dmar.h        |  2 +
 3 files changed, 99 insertions(+)

diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index 980e8ae090af..d5c51b5c20af 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -526,6 +526,7 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
 	struct acpi_dmar_reserved_memory *rmrr;
 	struct acpi_dmar_atsr *atsr;
 	struct acpi_dmar_rhsa *rhsa;
+	struct acpi_dmar_satc *satc;
 
 	switch (header->type) {
 	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
@@ -555,6 +556,10 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
 		/* We don't print this here because we need to sanity-check
 		   it first. So print it in dmar_parse_one_andd() instead. */
 		break;
+	case ACPI_DMAR_TYPE_SATC:
+		satc = container_of(header, struct acpi_dmar_satc, header);
+		pr_info("SATC flags: 0x%x\n", satc->flags);
+		break;
 	}
 }
 
@@ -642,6 +647,7 @@ parse_dmar_table(void)
 		.cb[ACPI_DMAR_TYPE_ROOT_ATS] = &dmar_parse_one_atsr,
 		.cb[ACPI_DMAR_TYPE_HARDWARE_AFFINITY] = &dmar_parse_one_rhsa,
 		.cb[ACPI_DMAR_TYPE_NAMESPACE] = &dmar_parse_one_andd,
+		.cb[ACPI_DMAR_TYPE_SATC] = &dmar_parse_one_satc,
 	};
 
 	/*
@@ -2077,6 +2083,7 @@ static guid_t dmar_hp_guid =
 #define	DMAR_DSM_FUNC_DRHD		1
 #define	DMAR_DSM_FUNC_ATSR		2
 #define	DMAR_DSM_FUNC_RHSA		3
+#define	DMAR_DSM_FUNC_SATC		4
 
 static inline bool dmar_detect_dsm(acpi_handle handle, int func)
 {
@@ -2094,6 +2101,7 @@ static int dmar_walk_dsm_resource(acpi_handle handle, int func,
 		[DMAR_DSM_FUNC_DRHD] = ACPI_DMAR_TYPE_HARDWARE_UNIT,
 		[DMAR_DSM_FUNC_ATSR] = ACPI_DMAR_TYPE_ROOT_ATS,
 		[DMAR_DSM_FUNC_RHSA] = ACPI_DMAR_TYPE_HARDWARE_AFFINITY,
+		[DMAR_DSM_FUNC_SATC] = ACPI_DMAR_TYPE_SATC,
 	};
 
 	if (!dmar_detect_dsm(handle, func))
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index ecbd05d8a1fc..ee0932307d64 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -316,8 +316,18 @@ struct dmar_atsr_unit {
 	u8 include_all:1;		/* include all ports */
 };
 
+struct dmar_satc_unit {
+	struct list_head list;		/* list of SATC units */
+	struct acpi_dmar_header *hdr;	/* ACPI header */
+	struct dmar_dev_scope *devices;	/* target devices */
+	struct intel_iommu *iommu;	/* the corresponding iommu */
+	int devices_cnt;		/* target device count */
+	u8 atc_required:1;		/* ATS is required */
+};
+
 static LIST_HEAD(dmar_atsr_units);
 static LIST_HEAD(dmar_rmrr_units);
+static LIST_HEAD(dmar_satc_units);
 
 #define for_each_rmrr_units(rmrr) \
 	list_for_each_entry(rmrr, &dmar_rmrr_units, list)
@@ -3716,6 +3726,57 @@ int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
 	return 0;
 }
 
+static struct dmar_satc_unit *dmar_find_satc(struct acpi_dmar_satc *satc)
+{
+	struct dmar_satc_unit *satcu;
+	struct acpi_dmar_satc *tmp;
+
+	list_for_each_entry_rcu(satcu, &dmar_satc_units, list,
+				dmar_rcu_check()) {
+		tmp = (struct acpi_dmar_satc *)satcu->hdr;
+		if (satc->segment != tmp->segment)
+			continue;
+		if (satc->header.length != tmp->header.length)
+			continue;
+		if (memcmp(satc, tmp, satc->header.length) == 0)
+			return satcu;
+	}
+
+	return NULL;
+}
+
+int dmar_parse_one_satc(struct acpi_dmar_header *hdr, void *arg)
+{
+	struct acpi_dmar_satc *satc;
+	struct dmar_satc_unit *satcu;
+
+	if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
+		return 0;
+
+	satc = container_of(hdr, struct acpi_dmar_satc, header);
+	satcu = dmar_find_satc(satc);
+	if (satcu)
+		return 0;
+
+	satcu = kzalloc(sizeof(*satcu) + hdr->length, GFP_KERNEL);
+	if (!satcu)
+		return -ENOMEM;
+
+	satcu->hdr = (void *)(satcu + 1);
+	memcpy(satcu->hdr, hdr, hdr->length);
+	satcu->atc_required = satc->flags & 0x1;
+	satcu->devices = dmar_alloc_dev_scope((void *)(satc + 1),
+					      (void *)satc + satc->header.length,
+					      &satcu->devices_cnt);
+	if (satcu->devices_cnt && !satcu->devices) {
+		kfree(satcu);
+		return -ENOMEM;
+	}
+	list_add_rcu(&satcu->list, &dmar_satc_units);
+
+	return 0;
+}
+
 static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
 {
 	int sp, ret;
@@ -3823,6 +3884,7 @@ static void intel_iommu_free_dmars(void)
 {
 	struct dmar_rmrr_unit *rmrru, *rmrr_n;
 	struct dmar_atsr_unit *atsru, *atsr_n;
+	struct dmar_satc_unit *satcu, *satc_n;
 
 	list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
 		list_del(&rmrru->list);
@@ -3834,6 +3896,11 @@ static void intel_iommu_free_dmars(void)
 		list_del(&atsru->list);
 		intel_iommu_free_atsr(atsru);
 	}
+	list_for_each_entry_safe(satcu, satc_n, &dmar_satc_units, list) {
+		list_del(&satcu->list);
+		dmar_free_dev_scope(&satcu->devices, &satcu->devices_cnt);
+		kfree(satcu);
+	}
 }
 
 int dmar_find_matched_atsr_unit(struct pci_dev *dev)
@@ -3885,8 +3952,10 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
 	int ret;
 	struct dmar_rmrr_unit *rmrru;
 	struct dmar_atsr_unit *atsru;
+	struct dmar_satc_unit *satcu;
 	struct acpi_dmar_atsr *atsr;
 	struct acpi_dmar_reserved_memory *rmrr;
+	struct acpi_dmar_satc *satc;
 
 	if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
 		return 0;
@@ -3927,6 +3996,23 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
 				break;
 		}
 	}
+	list_for_each_entry(satcu, &dmar_satc_units, list) {
+		satc = container_of(satcu->hdr, struct acpi_dmar_satc, header);
+		if (info->event == BUS_NOTIFY_ADD_DEVICE) {
+			ret = dmar_insert_dev_scope(info, (void *)(satc + 1),
+					(void *)satc + satc->header.length,
+					satc->segment, satcu->devices,
+					satcu->devices_cnt);
+			if (ret > 0)
+				break;
+			else if (ret < 0)
+				return ret;
+		} else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
+			if (dmar_remove_dev_scope(info, satc->segment,
+					satcu->devices, satcu->devices_cnt))
+				break;
+		}
+	}
 
 	return 0;
 }
@@ -4270,6 +4356,9 @@ int __init intel_iommu_init(void)
 	if (list_empty(&dmar_atsr_units))
 		pr_info("No ATSR found\n");
 
+	if (list_empty(&dmar_satc_units))
+		pr_info("No SATC found\n");
+
 	if (dmar_map_gfx)
 		intel_iommu_gfx_mapped = 1;
 
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 65565820328a..e04436a7ff27 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -138,6 +138,7 @@ extern void intel_iommu_shutdown(void);
 extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg);
 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_parse_one_satc(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_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
@@ -149,6 +150,7 @@ static inline void intel_iommu_shutdown(void) { }
 #define	dmar_parse_one_atsr		dmar_res_noop
 #define	dmar_check_one_atsr		dmar_res_noop
 #define	dmar_release_one_atsr		dmar_res_noop
+#define	dmar_parse_one_satc		dmar_res_noop
 
 static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
 {
-- 
2.25.1


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

* [PATCH v2 3/3] iommu/vt-d: Apply SATC policy
  2021-02-03  9:33 [PATCH v2 0/3] iommu/vt-d: Add support for ACPI/SATC table Lu Baolu
  2021-02-03  9:33 ` [PATCH v2 1/3] iommu/vt-d: Add new enum value and structure for SATC Lu Baolu
  2021-02-03  9:33 ` [PATCH v2 2/3] iommu/vt-d: Parse SATC reporting structure Lu Baolu
@ 2021-02-03  9:33 ` Lu Baolu
  2021-02-04  1:59   ` Tian, Kevin
  2021-02-03  9:48 ` [PATCH v2 0/3] iommu/vt-d: Add support for ACPI/SATC table Lu Baolu
  3 siblings, 1 reply; 7+ messages in thread
From: Lu Baolu @ 2021-02-03  9:33 UTC (permalink / raw)
  To: Joerg Roedel
  Cc: Will Deacon, Yian Chen, Ashok Raj, iommu, linux-kernel, Lu Baolu

From: Yian Chen <yian.chen@intel.com>

Starting from Intel VT-d v3.2, Intel platform BIOS can provide a new SATC
table structure. SATC table lists a set of SoC integrated devices that
require ATC to work (VT-d specification v3.2, section 8.8). Furthermore,
the new version of IOMMU supports SoC device ATS in both its Scalable mode
and legacy mode.

When IOMMU is working in scalable mode, software must enable device ATS
support. On the other hand, when IOMMU is in legacy mode for whatever
reason, the hardware managed ATS will automatically take effect and the
SATC required devices can work transparently to the software. As the
result, software shouldn't enable ATS on that device, otherwise duplicate
device TLB invalidations will occur.

Signed-off-by: Yian Chen <yian.chen@intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
 drivers/iommu/intel/iommu.c | 73 +++++++++++++++++++++++++++++++++++--
 1 file changed, 69 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index ee0932307d64..3e30c340e6a9 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -872,6 +872,60 @@ static bool iommu_is_dummy(struct intel_iommu *iommu, struct device *dev)
 	return false;
 }
 
+static bool iommu_support_ats(struct intel_iommu *iommu)
+{
+	return ecap_dev_iotlb_support(iommu->ecap);
+}
+
+static bool device_support_ats(struct pci_dev *dev)
+{
+	return pci_ats_supported(dev) && dmar_find_matched_atsr_unit(dev);
+}
+
+static int segment_atc_required(u16 segment)
+{
+	struct acpi_dmar_satc *satc;
+	struct dmar_satc_unit *satcu;
+	int ret = 1;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(satcu, &dmar_satc_units, list) {
+		satc = container_of(satcu->hdr, struct acpi_dmar_satc, header);
+		if (satcu->atc_required && satcu->devices_cnt &&
+		    satc->segment == segment)
+			goto out;
+	}
+	ret = 0;
+out:
+	rcu_read_unlock();
+	return ret;
+}
+
+static int device_atc_required(struct pci_dev *dev)
+{
+	struct dmar_satc_unit *satcu;
+	struct acpi_dmar_satc *satc;
+	struct device *tmp;
+	int i, ret = 1;
+
+	dev = pci_physfn(dev);
+	rcu_read_lock();
+	list_for_each_entry_rcu(satcu, &dmar_satc_units, list) {
+		satc = container_of(satcu->hdr, struct acpi_dmar_satc, header);
+		if (!satcu->atc_required ||
+		    satc->segment != pci_domain_nr(dev->bus))
+			continue;
+
+		for_each_dev_scope(satcu->devices, satcu->devices_cnt, i, tmp)
+			if (to_pci_dev(tmp) == dev)
+				goto out;
+	}
+	ret = 0;
+out:
+	rcu_read_unlock();
+	return ret;
+}
+
 struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
 {
 	struct dmar_drhd_unit *drhd = NULL;
@@ -2555,10 +2609,16 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
 	if (dev && dev_is_pci(dev)) {
 		struct pci_dev *pdev = to_pci_dev(info->dev);
 
-		if (ecap_dev_iotlb_support(iommu->ecap) &&
-		    pci_ats_supported(pdev) &&
-		    dmar_find_matched_atsr_unit(pdev))
-			info->ats_supported = 1;
+		/*
+		 * Support ATS by default if it's supported by both IOMMU and
+		 * client sides, except that the device's ATS is required by
+		 * ACPI/SATC but the IOMMU scalable mode is disabled. In that
+		 * case the hardware managed ATS will be automatically used.
+		 */
+		if (iommu_support_ats(iommu) && device_support_ats(pdev)) {
+			if (!device_atc_required(pdev) || sm_supported(iommu))
+				info->ats_supported = 1;
+		}
 
 		if (sm_supported(iommu)) {
 			if (pasid_supported(iommu)) {
@@ -3155,6 +3215,11 @@ static int __init init_dmars(void)
 	 * endfor
 	 */
 	for_each_drhd_unit(drhd) {
+		if (pci_ats_disabled() && segment_atc_required(drhd->segment)) {
+			pr_warn("Scalable mode disabled -- Use hardware managed ATS because PCIe ATS is disabled but some devices in PCIe segment 0x%x require it.",
+				drhd->segment);
+			intel_iommu_sm = 0;
+		}
 		/*
 		 * lock not needed as this is only incremented in the single
 		 * threaded kernel __init code path all other access are read
-- 
2.25.1


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

* Re: [PATCH v2 0/3] iommu/vt-d: Add support for ACPI/SATC table
  2021-02-03  9:33 [PATCH v2 0/3] iommu/vt-d: Add support for ACPI/SATC table Lu Baolu
                   ` (2 preceding siblings ...)
  2021-02-03  9:33 ` [PATCH v2 3/3] iommu/vt-d: Apply SATC policy Lu Baolu
@ 2021-02-03  9:48 ` Lu Baolu
  3 siblings, 0 replies; 7+ messages in thread
From: Lu Baolu @ 2021-02-03  9:48 UTC (permalink / raw)
  To: Joerg Roedel
  Cc: baolu.lu, Will Deacon, Yian Chen, Ashok Raj, iommu, linux-kernel

Add the change log. Sorry for the quick sent.

On 2021/2/3 17:33, Lu Baolu wrote:
> The Intel VT-d specification v3.2 comes with a new ACPI SATC (SoC-
> Integrated Address Translation Cache) reporting structure. The SoC
> integrated device enumerated in this table has a functional
> requirement to enable its ATC (Address Translation Cache) via the
> ATS capability for device operation.
> 
> This patch set adds the code to parse the SATC table, enumerates the
> devices in it and satisfies the ATS requirement for them. Please help
> to review. I will queue it in VT-d update for v5.12 if no objection.
> 

Change log:
v1->v2:
  - Rephrase some words in the cover letter, commit message and
    code comments.
  - Refactored a code style to make it look nicer.

Best regards,
baolu

> Yian Chen (3):
>    iommu/vt-d: Add new enum value and structure for SATC
>    iommu/vt-d: Parse SATC reporting structure
>    iommu/vt-d: Apply SATC policy
> 
>   drivers/iommu/intel/dmar.c  |   8 ++
>   drivers/iommu/intel/iommu.c | 162 +++++++++++++++++++++++++++++++++++-
>   include/acpi/actbl1.h       |  11 ++-
>   include/linux/dmar.h        |   2 +
>   4 files changed, 178 insertions(+), 5 deletions(-)
> 

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

* RE: [PATCH v2 3/3] iommu/vt-d: Apply SATC policy
  2021-02-03  9:33 ` [PATCH v2 3/3] iommu/vt-d: Apply SATC policy Lu Baolu
@ 2021-02-04  1:59   ` Tian, Kevin
  2021-02-04  2:13     ` Lu Baolu
  0 siblings, 1 reply; 7+ messages in thread
From: Tian, Kevin @ 2021-02-04  1:59 UTC (permalink / raw)
  To: Lu Baolu, Joerg Roedel; +Cc: Raj, Ashok, linux-kernel, iommu, Will Deacon

> From: Lu Baolu
> Sent: Wednesday, February 3, 2021 5:33 PM
> 
> From: Yian Chen <yian.chen@intel.com>
> 
> Starting from Intel VT-d v3.2, Intel platform BIOS can provide a new SATC
> table structure. SATC table lists a set of SoC integrated devices that
> require ATC to work (VT-d specification v3.2, section 8.8). Furthermore,

This statement is not accurate. The purpose of SATC is to tell whether a
SoC integrated device has been validated to meet the isolation requirements 
of using device TLB. All devices listed in SATC can have ATC safely enabled by 
OS. In addition, there is a flag for each listed device for whether ATC is a 
functional requirement. However, above description only captured the last 
point.

> the new version of IOMMU supports SoC device ATS in both its Scalable
> mode
> and legacy mode.
> 
> When IOMMU is working in scalable mode, software must enable device ATS
> support. 

"must enable" is misleading here. You need describe the policies for three
categories:

- SATC devices with ATC_REQUIRED=1
- SATC devices with ATC_REQUIRED=0
- devices not listed in SATC, or when SATC is missing

> On the other hand, when IOMMU is in legacy mode for whatever
> reason, the hardware managed ATS will automatically take effect and the
> SATC required devices can work transparently to the software. As the

No background about hardware-managed ATS. 

> result, software shouldn't enable ATS on that device, otherwise duplicate
> device TLB invalidations will occur.

This description draws a equation between legacy mode and hardware
managed ATS. Do we care about the scenario where there is no hardware
managed ATS but people also want to turn on ATC in legacy mode?

Thanks
Kevin

> 
> Signed-off-by: Yian Chen <yian.chen@intel.com>
> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
> ---
>  drivers/iommu/intel/iommu.c | 73
> +++++++++++++++++++++++++++++++++++--
>  1 file changed, 69 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index ee0932307d64..3e30c340e6a9 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -872,6 +872,60 @@ static bool iommu_is_dummy(struct intel_iommu
> *iommu, struct device *dev)
>  	return false;
>  }
> 
> +static bool iommu_support_ats(struct intel_iommu *iommu)
> +{
> +	return ecap_dev_iotlb_support(iommu->ecap);
> +}
> +
> +static bool device_support_ats(struct pci_dev *dev)
> +{
> +	return pci_ats_supported(dev) &&
> dmar_find_matched_atsr_unit(dev);
> +}
> +
> +static int segment_atc_required(u16 segment)
> +{
> +	struct acpi_dmar_satc *satc;
> +	struct dmar_satc_unit *satcu;
> +	int ret = 1;
> +
> +	rcu_read_lock();
> +	list_for_each_entry_rcu(satcu, &dmar_satc_units, list) {
> +		satc = container_of(satcu->hdr, struct acpi_dmar_satc,
> header);
> +		if (satcu->atc_required && satcu->devices_cnt &&
> +		    satc->segment == segment)
> +			goto out;
> +	}
> +	ret = 0;
> +out:
> +	rcu_read_unlock();
> +	return ret;
> +}
> +
> +static int device_atc_required(struct pci_dev *dev)
> +{
> +	struct dmar_satc_unit *satcu;
> +	struct acpi_dmar_satc *satc;
> +	struct device *tmp;
> +	int i, ret = 1;
> +
> +	dev = pci_physfn(dev);
> +	rcu_read_lock();
> +	list_for_each_entry_rcu(satcu, &dmar_satc_units, list) {
> +		satc = container_of(satcu->hdr, struct acpi_dmar_satc,
> header);
> +		if (!satcu->atc_required ||
> +		    satc->segment != pci_domain_nr(dev->bus))
> +			continue;
> +
> +		for_each_dev_scope(satcu->devices, satcu->devices_cnt, i,
> tmp)
> +			if (to_pci_dev(tmp) == dev)
> +				goto out;
> +	}
> +	ret = 0;
> +out:
> +	rcu_read_unlock();
> +	return ret;
> +}
> +
>  struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8
> *devfn)
>  {
>  	struct dmar_drhd_unit *drhd = NULL;
> @@ -2555,10 +2609,16 @@ static struct dmar_domain
> *dmar_insert_one_dev_info(struct intel_iommu *iommu,
>  	if (dev && dev_is_pci(dev)) {
>  		struct pci_dev *pdev = to_pci_dev(info->dev);
> 
> -		if (ecap_dev_iotlb_support(iommu->ecap) &&
> -		    pci_ats_supported(pdev) &&
> -		    dmar_find_matched_atsr_unit(pdev))
> -			info->ats_supported = 1;
> +		/*
> +		 * Support ATS by default if it's supported by both IOMMU
> and
> +		 * client sides, except that the device's ATS is required by
> +		 * ACPI/SATC but the IOMMU scalable mode is disabled. In
> that
> +		 * case the hardware managed ATS will be automatically used.
> +		 */
> +		if (iommu_support_ats(iommu) &&
> device_support_ats(pdev)) {
> +			if (!device_atc_required(pdev) ||
> sm_supported(iommu))
> +				info->ats_supported = 1;
> +		}
> 
>  		if (sm_supported(iommu)) {
>  			if (pasid_supported(iommu)) {
> @@ -3155,6 +3215,11 @@ static int __init init_dmars(void)
>  	 * endfor
>  	 */
>  	for_each_drhd_unit(drhd) {
> +		if (pci_ats_disabled() && segment_atc_required(drhd-
> >segment)) {
> +			pr_warn("Scalable mode disabled -- Use hardware
> managed ATS because PCIe ATS is disabled but some devices in PCIe segment
> 0x%x require it.",
> +				drhd->segment);
> +			intel_iommu_sm = 0;
> +		}
>  		/*
>  		 * lock not needed as this is only incremented in the single
>  		 * threaded kernel __init code path all other access are read
> --
> 2.25.1
> 
> _______________________________________________
> iommu mailing list
> iommu@lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH v2 3/3] iommu/vt-d: Apply SATC policy
  2021-02-04  1:59   ` Tian, Kevin
@ 2021-02-04  2:13     ` Lu Baolu
  0 siblings, 0 replies; 7+ messages in thread
From: Lu Baolu @ 2021-02-04  2:13 UTC (permalink / raw)
  To: Tian, Kevin, Joerg Roedel
  Cc: baolu.lu, Raj, Ashok, linux-kernel, iommu, Will Deacon

Hi Kevin,

On 2/4/21 9:59 AM, Tian, Kevin wrote:
>> From: Lu Baolu
>> Sent: Wednesday, February 3, 2021 5:33 PM
>>
>> From: Yian Chen<yian.chen@intel.com>
>>
>> Starting from Intel VT-d v3.2, Intel platform BIOS can provide a new SATC
>> table structure. SATC table lists a set of SoC integrated devices that
>> require ATC to work (VT-d specification v3.2, section 8.8). Furthermore,
> This statement is not accurate. The purpose of SATC is to tell whether a
> SoC integrated device has been validated to meet the isolation requirements
> of using device TLB. All devices listed in SATC can have ATC safely enabled by
> OS. In addition, there is a flag for each listed device for whether ATC is a
> functional requirement. However, above description only captured the last
> point.

You are right. This series only addresses the devices with the flag set
which have functional requirement for ATS.

> 
>> the new version of IOMMU supports SoC device ATS in both its Scalable
>> mode
>> and legacy mode.
>>
>> When IOMMU is working in scalable mode, software must enable device ATS
>> support.
> "must enable" is misleading here. You need describe the policies for three
> categories:
> 
> - SATC devices with ATC_REQUIRED=1
> - SATC devices with ATC_REQUIRED=0
> - devices not listed in SATC, or when SATC is missing

Yian is working on this part. We planed it for v5.13. He will bring it
up for discussion later.

> 
>> On the other hand, when IOMMU is in legacy mode for whatever
>> reason, the hardware managed ATS will automatically take effect and the
>> SATC required devices can work transparently to the software. As the
> No background about hardware-managed ATS.
> 
>> result, software shouldn't enable ATS on that device, otherwise duplicate
>> device TLB invalidations will occur.
> This description draws a equation between legacy mode and hardware
> managed ATS. Do we care about the scenario where there is no hardware
> managed ATS but people also want to turn on ATC in legacy mode?

The hardware managed ATS is defined in the platform specific
specification. The purpose of this hardware design is backward
compatibility - legacy OSes with no SM or ATS awareness still running
well on them.

> 
> Thanks
> Kevin
> 

Best regards,
baolu

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

end of thread, other threads:[~2021-02-04  2:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-03  9:33 [PATCH v2 0/3] iommu/vt-d: Add support for ACPI/SATC table Lu Baolu
2021-02-03  9:33 ` [PATCH v2 1/3] iommu/vt-d: Add new enum value and structure for SATC Lu Baolu
2021-02-03  9:33 ` [PATCH v2 2/3] iommu/vt-d: Parse SATC reporting structure Lu Baolu
2021-02-03  9:33 ` [PATCH v2 3/3] iommu/vt-d: Apply SATC policy Lu Baolu
2021-02-04  1:59   ` Tian, Kevin
2021-02-04  2:13     ` Lu Baolu
2021-02-03  9:48 ` [PATCH v2 0/3] iommu/vt-d: Add support for ACPI/SATC table Lu Baolu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).