public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system
@ 2022-07-13 22:56 Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 1/9] iommu/amd: Change macro for IOMMU control register bit shift to decimal value Suravee Suthikulpanit
                   ` (9 more replies)
  0 siblings, 10 replies; 12+ messages in thread
From: Suravee Suthikulpanit @ 2022-07-13 22:56 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: joro, robin.murphy, vasant.hegde, ashish.kalra, jon.grimm,
	Suravee Suthikulpanit

To support the new AMD Secure Nested Paging (SNP) feature, AMD IOMMU driver
needs to be modified to comply with new restrictions enforced by the SNP
feature.

The SNP feature detection needs to happen early in the IOMMU driver
initialization, and the feature must be supported across all IOMMUs.

To simplify the detection process, this series introduces global variables
for tracking IOMMU Extended Feature Registers (EFR and EFR2), which store
common feature bits across all IOMMUs. These global variables are available
as soon as the IVRS table is parsed, which happens at the beginning of
the driver initialization. Therefore, they can be used for early detection
of SNP feature. (See patch 2 - 5)

Once the feature is detected, IOMMU driver needs to be informed when the
feature system-wide. Therefor, the function amd_iommu_snp_enable() is
introduced in patch 6, and will be called by SEV-SNP driver.

When IOMMU driver initializing the device table entries (DTEs), care must
be taken when setting up the DTE[TV] bit on SNP-enabled system.
(See patch 7)

Lastly, an SNP-enabled system requires IOMMU v1 page table to be configured
with non-zero DTE[Mode] for DMA-capable devices. This affects a number of
use cases such as IOMMU pass-through mode and AMD IOMMUv2 APIs for binding/
unbinding pasid cannot be supported with SNP. These are handled in patch 8
and 9.

Testing:
  - Tested booting and verify dmesg.
  - Tested booting with iommu=pt
  - Tested changing the iommu domain to identity at runtime
  - Tested loading amd_iommu_v2 driver
  - Tested booting SEV/SNP-enabled guest
  - Tested when CONFIG_AMD_MEM_ENCRYPT is not set

Chanages from v3:
(https://www.spinics.net/lists/kernel/msg4409539.html)
  - Patch 1, 2, and 5 are new.
  - Patch 3: Modify to use global common EFR/EFR2 vaiable
             when tracking supported features.

Best Regards,
Suravee

Brijesh Singh (1):
  iommu/amd: Introduce function to check and enable SNP

Suravee Suthikulpanit (8):
  iommu/amd: Change macro for IOMMU control register bit shift to
    decimal value
  iommu/amd: Introduce Support for Extended Feature 2 Register
  iommu/amd: Introduce global variable for storing common EFR and EFR2
  iommu/amd: Process all IVHDs before enabling IOMMU features
  iommu/amd: Globally detect SNP support
  iommu/amd: Set translation valid bit only when IO page tables are in
    use
  iommu/amd: Do not support IOMMU_DOMAIN_IDENTITY after SNP is enabled
  iommu/amd: Do not support IOMMUv2 APIs when SNP is enabled

 drivers/iommu/amd/amd_iommu.h       |   5 +
 drivers/iommu/amd/amd_iommu_types.h |  46 +++++----
 drivers/iommu/amd/init.c            | 153 +++++++++++++++++++++++-----
 drivers/iommu/amd/iommu.c           |  24 ++++-
 include/linux/amd-iommu.h           |   4 +
 5 files changed, 183 insertions(+), 49 deletions(-)

-- 
2.32.0


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

* [PATCH v4 1/9] iommu/amd: Change macro for IOMMU control register bit shift to decimal value
  2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
@ 2022-07-13 22:56 ` Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 2/9] iommu/amd: Introduce Support for Extended Feature 2 Register Suravee Suthikulpanit
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Suravee Suthikulpanit @ 2022-07-13 22:56 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: joro, robin.murphy, vasant.hegde, ashish.kalra, jon.grimm,
	Suravee Suthikulpanit

There is no functional change.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
 drivers/iommu/amd/amd_iommu_types.h | 42 ++++++++++++++---------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index 40f52d02c5b9..7c830e3c7a91 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -143,27 +143,27 @@
 #define EVENT_FLAG_I		0x008
 
 /* feature control bits */
-#define CONTROL_IOMMU_EN        0x00ULL
-#define CONTROL_HT_TUN_EN       0x01ULL
-#define CONTROL_EVT_LOG_EN      0x02ULL
-#define CONTROL_EVT_INT_EN      0x03ULL
-#define CONTROL_COMWAIT_EN      0x04ULL
-#define CONTROL_INV_TIMEOUT	0x05ULL
-#define CONTROL_PASSPW_EN       0x08ULL
-#define CONTROL_RESPASSPW_EN    0x09ULL
-#define CONTROL_COHERENT_EN     0x0aULL
-#define CONTROL_ISOC_EN         0x0bULL
-#define CONTROL_CMDBUF_EN       0x0cULL
-#define CONTROL_PPRLOG_EN       0x0dULL
-#define CONTROL_PPRINT_EN       0x0eULL
-#define CONTROL_PPR_EN          0x0fULL
-#define CONTROL_GT_EN           0x10ULL
-#define CONTROL_GA_EN           0x11ULL
-#define CONTROL_GAM_EN          0x19ULL
-#define CONTROL_GALOG_EN        0x1CULL
-#define CONTROL_GAINT_EN        0x1DULL
-#define CONTROL_XT_EN           0x32ULL
-#define CONTROL_INTCAPXT_EN     0x33ULL
+#define CONTROL_IOMMU_EN	0
+#define CONTROL_HT_TUN_EN	1
+#define CONTROL_EVT_LOG_EN	2
+#define CONTROL_EVT_INT_EN	3
+#define CONTROL_COMWAIT_EN	4
+#define CONTROL_INV_TIMEOUT	5
+#define CONTROL_PASSPW_EN	8
+#define CONTROL_RESPASSPW_EN	9
+#define CONTROL_COHERENT_EN	10
+#define CONTROL_ISOC_EN		11
+#define CONTROL_CMDBUF_EN	12
+#define CONTROL_PPRLOG_EN	13
+#define CONTROL_PPRINT_EN	14
+#define CONTROL_PPR_EN		15
+#define CONTROL_GT_EN		16
+#define CONTROL_GA_EN		17
+#define CONTROL_GAM_EN		25
+#define CONTROL_GALOG_EN	28
+#define CONTROL_GAINT_EN	29
+#define CONTROL_XT_EN		50
+#define CONTROL_INTCAPXT_EN	51
 
 #define CTRL_INV_TO_MASK	(7 << CONTROL_INV_TIMEOUT)
 #define CTRL_INV_TO_NONE	0
-- 
2.32.0


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

* [PATCH v4 2/9] iommu/amd: Introduce Support for Extended Feature 2 Register
  2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 1/9] iommu/amd: Change macro for IOMMU control register bit shift to decimal value Suravee Suthikulpanit
@ 2022-07-13 22:56 ` Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 3/9] iommu/amd: Introduce global variable for storing common EFR and EFR2 Suravee Suthikulpanit
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Suravee Suthikulpanit @ 2022-07-13 22:56 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: joro, robin.murphy, vasant.hegde, ashish.kalra, jon.grimm,
	Suravee Suthikulpanit

AMD IOMMU spec introduces additional extended feature register
in the IVRS IVHD offset 80h (for IVHD type 11h and 40h) and MMIO
offset 1A0h.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
 drivers/iommu/amd/amd_iommu_types.h |  4 ++++
 drivers/iommu/amd/init.c            | 24 ++++++++++++++++--------
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index 7c830e3c7a91..3c1205ba636a 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -67,6 +67,7 @@
 #define MMIO_INTCAPXT_EVT_OFFSET	0x0170
 #define MMIO_INTCAPXT_PPR_OFFSET	0x0178
 #define MMIO_INTCAPXT_GALOG_OFFSET	0x0180
+#define MMIO_EXT_FEATURES2	0x01A0
 #define MMIO_CMD_HEAD_OFFSET	0x2000
 #define MMIO_CMD_TAIL_OFFSET	0x2008
 #define MMIO_EVT_HEAD_OFFSET	0x2010
@@ -645,6 +646,9 @@ struct amd_iommu {
 	/* Extended features */
 	u64 features;
 
+	/* Extended features 2 */
+	u64 features2;
+
 	/* IOMMUv2 */
 	bool is_iommu_v2;
 
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 3c82d9c5f1c0..92ab02f6c5dc 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -114,7 +114,7 @@ struct ivhd_header {
 
 	/* Following only valid on IVHD type 11h and 40h */
 	u64 efr_reg; /* Exact copy of MMIO_EXT_FEATURES */
-	u64 res;
+	u64 efr_reg2;
 } __attribute__((packed));
 
 /*
@@ -283,8 +283,10 @@ static bool check_feature_on_all_iommus(u64 mask)
 static void __init early_iommu_features_init(struct amd_iommu *iommu,
 					     struct ivhd_header *h)
 {
-	if (amd_iommu_ivinfo & IOMMU_IVINFO_EFRSUP)
+	if (amd_iommu_ivinfo & IOMMU_IVINFO_EFRSUP) {
 		iommu->features = h->efr_reg;
+		iommu->features2 = h->efr_reg2;
+	}
 	if (amd_iommu_ivinfo & IOMMU_IVINFO_DMA_REMAP)
 		amdr_ivrs_remap_support = true;
 }
@@ -1912,7 +1914,7 @@ static ssize_t amd_iommu_show_features(struct device *dev,
 				       char *buf)
 {
 	struct amd_iommu *iommu = dev_to_amd_iommu(dev);
-	return sprintf(buf, "%llx\n", iommu->features);
+	return sprintf(buf, "%llx:%llx\n", iommu->features2, iommu->features);
 }
 static DEVICE_ATTR(features, S_IRUGO, amd_iommu_show_features, NULL);
 
@@ -1939,16 +1941,18 @@ static const struct attribute_group *amd_iommu_groups[] = {
  */
 static void __init late_iommu_features_init(struct amd_iommu *iommu)
 {
-	u64 features;
+	u64 features, features2;
 
 	if (!(iommu->cap & (1 << IOMMU_CAP_EFR)))
 		return;
 
 	/* read extended feature bits */
 	features = readq(iommu->mmio_base + MMIO_EXT_FEATURES);
+	features2 = readq(iommu->mmio_base + MMIO_EXT_FEATURES2);
 
 	if (!iommu->features) {
 		iommu->features = features;
+		iommu->features2 = features2;
 		return;
 	}
 
@@ -1956,9 +1960,13 @@ static void __init late_iommu_features_init(struct amd_iommu *iommu)
 	 * Sanity check and warn if EFR values from
 	 * IVHD and MMIO conflict.
 	 */
-	if (features != iommu->features)
-		pr_warn(FW_WARN "EFR mismatch. Use IVHD EFR (%#llx : %#llx).\n",
-			features, iommu->features);
+	if (features != iommu->features ||
+	    features2 != iommu->features2) {
+		pr_warn(FW_WARN
+			"EFR mismatch. Use IVHD EFR (%#llx : %#llx), EFR2 (%#llx : %#llx).\n",
+			features, iommu->features,
+			features2, iommu->features2);
+	}
 }
 
 static int __init iommu_init_pci(struct amd_iommu *iommu)
@@ -2080,7 +2088,7 @@ static void print_iommu_info(void)
 		pci_info(pdev, "Found IOMMU cap 0x%x\n", iommu->cap_ptr);
 
 		if (iommu->cap & (1 << IOMMU_CAP_EFR)) {
-			pr_info("Extended features (%#llx):", iommu->features);
+			pr_info("Extended features (%#llx, %#llx):", iommu->features, iommu->features2);
 
 			for (i = 0; i < ARRAY_SIZE(feat_str); ++i) {
 				if (iommu_feature(iommu, (1ULL << i)))
-- 
2.32.0


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

* [PATCH v4 3/9] iommu/amd: Introduce global variable for storing common EFR and EFR2
  2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 1/9] iommu/amd: Change macro for IOMMU control register bit shift to decimal value Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 2/9] iommu/amd: Introduce Support for Extended Feature 2 Register Suravee Suthikulpanit
@ 2022-07-13 22:56 ` Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 4/9] iommu/amd: Process all IVHDs before enabling IOMMU features Suravee Suthikulpanit
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Suravee Suthikulpanit @ 2022-07-13 22:56 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: joro, robin.murphy, vasant.hegde, ashish.kalra, jon.grimm,
	Suravee Suthikulpanit

Some IOMMU features require that all IOMMUs must support the feature,
which is determined by checking the support bit in the Extended Feature
Register 1 and 2 (EFR/EFR2) on all IOMMUs. This check is done by the
function check_feature_on_all_iommus(), which iterates through all
IOMMUs everytime it is called.

Instead, introduce a global variable to store common EFR/EFR2 among all
IOMMUs. In case of inconsistent EFR/EFR2 masks are detected on an IOMMU,
a FW_BUG warning is reported.

Suggested-by: Joerg Roedel <joro@8bytes.org>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
 drivers/iommu/amd/amd_iommu.h |  3 +++
 drivers/iommu/amd/init.c      | 45 ++++++++++++++++++++++++++++-------
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 9b7092182ca7..1b945d47741c 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -137,4 +137,7 @@ static inline void amd_iommu_apply_ivrs_quirks(void) { }
 extern void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
 					 u64 *root, int mode);
 extern struct dev_table_entry *get_dev_table(struct amd_iommu *iommu);
+
+extern u64 amd_iommu_efr;
+extern u64 amd_iommu_efr2;
 #endif
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 92ab02f6c5dc..741fee1abfc4 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -164,6 +164,10 @@ static bool amd_iommu_disabled __initdata;
 static bool amd_iommu_force_enable __initdata;
 static int amd_iommu_target_ivhd_type;
 
+/* Global EFR and EFR2 registers */
+u64 amd_iommu_efr;
+u64 amd_iommu_efr2;
+
 LIST_HEAD(amd_iommu_pci_seg_list);	/* list of all PCI segments */
 LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the
 					   system */
@@ -259,21 +263,46 @@ int amd_iommu_get_num_iommus(void)
 	return amd_iommus_present;
 }
 
-#ifdef CONFIG_IRQ_REMAP
-static bool check_feature_on_all_iommus(u64 mask)
+/*
+ * Iterate through all the IOMMUs to get common EFR
+ * masks among all IOMMUs and warn if found inconsistency.
+ */
+static void get_global_efr(void)
 {
-	bool ret = false;
 	struct amd_iommu *iommu;
 
 	for_each_iommu(iommu) {
-		ret = iommu_feature(iommu, mask);
-		if (!ret)
-			return false;
+		u64 tmp = iommu->features;
+		u64 tmp2 = iommu->features2;
+
+		if (list_is_first(&iommu->list, &amd_iommu_list)) {
+			amd_iommu_efr = tmp;
+			amd_iommu_efr2 = tmp2;
+			continue;
+		}
+
+		if (amd_iommu_efr == tmp &&
+		    amd_iommu_efr2 == tmp2)
+			continue;
+
+		pr_err(FW_BUG
+		       "Found inconsistent EFR/EFR2 %#llx,%#llx (global %#llx,%#llx) on iommu%d (%04x:%02x:%02x.%01x).\n",
+		       tmp, tmp2, amd_iommu_efr, amd_iommu_efr2,
+		       iommu->index, iommu->pci_seg->id,
+		       PCI_BUS_NUM(iommu->devid), PCI_SLOT(iommu->devid),
+		       PCI_FUNC(iommu->devid));
+
+		amd_iommu_efr &= tmp;
+		amd_iommu_efr2 &= tmp2;
 	}
 
-	return true;
+	pr_info("Using global IVHD EFR:%#llx, EFR2:%#llx\n", amd_iommu_efr, amd_iommu_efr2);
+}
+
+static bool check_feature_on_all_iommus(u64 mask)
+{
+	return !!(amd_iommu_efr & mask);
 }
-#endif
 
 /*
  * For IVHD type 0x11/0x40, EFR is also available via IVHD.
-- 
2.32.0


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

* [PATCH v4 4/9] iommu/amd: Process all IVHDs before enabling IOMMU features
  2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
                   ` (2 preceding siblings ...)
  2022-07-13 22:56 ` [PATCH v4 3/9] iommu/amd: Introduce global variable for storing common EFR and EFR2 Suravee Suthikulpanit
@ 2022-07-13 22:56 ` Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 5/9] iommu/amd: Globally detect SNP support Suravee Suthikulpanit
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Suravee Suthikulpanit @ 2022-07-13 22:56 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: joro, robin.murphy, vasant.hegde, ashish.kalra, jon.grimm,
	Suravee Suthikulpanit

The ACPI IVRS table can contain multiple IVHD blocks. Each block contains
information used to initialize each IOMMU instance.

Currently, init_iommu_all sequentially process IVHD block and initialize
IOMMU instance one-by-one. However, certain features require all IOMMUs
to be configured in the same way system-wide. In case certain IVHD blocks
contain inconsistent information (most likely FW bugs), the driver needs
to go through and try to revert settings on IOMMUs that have already been
configured.

A solution is to split IOMMU initialization into 3 phases:

Phase1 : Processes information of the IVRS table for all IOMMU instances.
This allow all IVHDs to be processed prior to enabling features.

Phase2 : Early feature support check on all IOMMUs (using information in
IVHD blocks.

Phase3 : Iterates through all IOMMU instances and enabling features.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
 drivers/iommu/amd/init.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 741fee1abfc4..a0f4b5bbd98c 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -1721,7 +1721,6 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h,
 				 struct acpi_table_header *ivrs_base)
 {
 	struct amd_iommu_pci_seg *pci_seg;
-	int ret;
 
 	pci_seg = get_pci_segment(h->pci_seg, ivrs_base);
 	if (pci_seg == NULL)
@@ -1802,6 +1801,13 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h,
 	if (!iommu->mmio_base)
 		return -ENOMEM;
 
+	return init_iommu_from_acpi(iommu, h);
+}
+
+static int __init init_iommu_one_late(struct amd_iommu *iommu)
+{
+	int ret;
+
 	if (alloc_cwwb_sem(iommu))
 		return -ENOMEM;
 
@@ -1823,10 +1829,6 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h,
 	if (amd_iommu_pre_enabled)
 		amd_iommu_pre_enabled = translation_pre_enabled(iommu);
 
-	ret = init_iommu_from_acpi(iommu, h);
-	if (ret)
-		return ret;
-
 	if (amd_iommu_irq_remap) {
 		ret = amd_iommu_create_irq_domain(iommu);
 		if (ret)
@@ -1837,7 +1839,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h,
 	 * Make sure IOMMU is not considered to translate itself. The IVRS
 	 * table tells us so, but this is a lie!
 	 */
-	pci_seg->rlookup_table[iommu->devid] = NULL;
+	iommu->pci_seg->rlookup_table[iommu->devid] = NULL;
 
 	return 0;
 }
@@ -1882,6 +1884,7 @@ static int __init init_iommu_all(struct acpi_table_header *table)
 	end += table->length;
 	p += IVRS_HEADER_LENGTH;
 
+	/* Phase 1: Process all IVHD blocks */
 	while (p < end) {
 		h = (struct ivhd_header *)p;
 		if (*p == amd_iommu_target_ivhd_type) {
@@ -1907,6 +1910,16 @@ static int __init init_iommu_all(struct acpi_table_header *table)
 	}
 	WARN_ON(p != end);
 
+	/* Phase 2 : Early feature support check */
+	get_global_efr();
+
+	/* Phase 3 : Enabling IOMMU features */
+	for_each_iommu(iommu) {
+		ret = init_iommu_one_late(iommu);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
-- 
2.32.0


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

* [PATCH v4 5/9] iommu/amd: Globally detect SNP support
  2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
                   ` (3 preceding siblings ...)
  2022-07-13 22:56 ` [PATCH v4 4/9] iommu/amd: Process all IVHDs before enabling IOMMU features Suravee Suthikulpanit
@ 2022-07-13 22:56 ` Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 6/9] iommu/amd: Introduce function to check and enable SNP Suravee Suthikulpanit
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Suravee Suthikulpanit @ 2022-07-13 22:56 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: joro, robin.murphy, vasant.hegde, ashish.kalra, jon.grimm,
	Suravee Suthikulpanit

Modify existing SNP feature check to use the helper function
check_feature_on_all_iommus() to ensure consistency among all IOMMUs.
Also report IOMMU SNP support information for each IOMMU.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
 drivers/iommu/amd/init.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index a0f4b5bbd98c..2f338c8c3d10 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -389,7 +389,7 @@ static void iommu_set_cwwb_range(struct amd_iommu *iommu)
 	u64 start = iommu_virt_to_phys((void *)iommu->cmd_sem);
 	u64 entry = start & PM_ADDR_MASK;
 
-	if (!iommu_feature(iommu, FEATURE_SNP))
+	if (!check_feature_on_all_iommus(FEATURE_SNP))
 		return;
 
 	/* Note:
@@ -804,7 +804,7 @@ static void *__init iommu_alloc_4k_pages(struct amd_iommu *iommu,
 	void *buf = (void *)__get_free_pages(gfp, order);
 
 	if (buf &&
-	    iommu_feature(iommu, FEATURE_SNP) &&
+	    check_feature_on_all_iommus(FEATURE_SNP) &&
 	    set_memory_4k((unsigned long)buf, (1 << order))) {
 		free_pages((unsigned long)buf, order);
 		buf = NULL;
@@ -2140,6 +2140,9 @@ static void print_iommu_info(void)
 			if (iommu->features & FEATURE_GAM_VAPIC)
 				pr_cont(" GA_vAPIC");
 
+			if (iommu->features & FEATURE_SNP)
+				pr_cont(" SNP");
+
 			pr_cont("\n");
 		}
 	}
-- 
2.32.0


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

* [PATCH v4 6/9] iommu/amd: Introduce function to check and enable SNP
  2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
                   ` (4 preceding siblings ...)
  2022-07-13 22:56 ` [PATCH v4 5/9] iommu/amd: Globally detect SNP support Suravee Suthikulpanit
@ 2022-07-13 22:56 ` Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 7/9] iommu/amd: Set translation valid bit only when IO page tables are in use Suravee Suthikulpanit
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Suravee Suthikulpanit @ 2022-07-13 22:56 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: joro, robin.murphy, vasant.hegde, ashish.kalra, jon.grimm,
	Brijesh Singh, Suravee Suthikulpanit

From: Brijesh Singh <brijesh.singh@amd.com>

To support SNP, IOMMU needs to be enabled, and prohibits IOMMU
configurations where DTE[Mode]=0, which means it cannot be supported with
IOMMU passthrough domain (a.k.a IOMMU_DOMAIN_IDENTITY),
and when AMD IOMMU driver is configured to not use the IOMMU host (v1) page
table. Otherwise, RMP table initialization could cause the system to crash.

The request to enable SNP support in IOMMU must be done before PCI
initialization state of the IOMMU driver because enabling SNP affects
how IOMMU driver sets up IOMMU data structures (i.e. DTE).

Unlike other IOMMU features, SNP feature does not have an enable bit in
the IOMMU control register. Instead, the IOMMU driver introduces
an amd_iommu_snp_en variable to track enabling state of SNP.

Introduce amd_iommu_snp_enable() for other drivers to request enabling
the SNP support in IOMMU, which checks all prerequisites and determines
if the feature can be safely enabled.

Please see the IOMMU spec section 2.12 for further details.

Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Co-developed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 drivers/iommu/amd/amd_iommu.h |  2 ++
 drivers/iommu/amd/init.c      | 42 +++++++++++++++++++++++++++++++++++
 include/linux/amd-iommu.h     |  4 ++++
 3 files changed, 48 insertions(+)

diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 1b945d47741c..84e5bb1bf01b 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -140,4 +140,6 @@ extern struct dev_table_entry *get_dev_table(struct amd_iommu *iommu);
 
 extern u64 amd_iommu_efr;
 extern u64 amd_iommu_efr2;
+
+extern bool amd_iommu_snp_en;
 #endif
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 2f338c8c3d10..1dd1c2b25898 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -168,6 +168,10 @@ static int amd_iommu_target_ivhd_type;
 u64 amd_iommu_efr;
 u64 amd_iommu_efr2;
 
+/* SNP is enabled on the system? */
+bool amd_iommu_snp_en;
+EXPORT_SYMBOL(amd_iommu_snp_en);
+
 LIST_HEAD(amd_iommu_pci_seg_list);	/* list of all PCI segments */
 LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the
 					   system */
@@ -3553,3 +3557,41 @@ int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, u8 fxn, u64
 
 	return iommu_pc_get_set_reg(iommu, bank, cntr, fxn, value, true);
 }
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+int amd_iommu_snp_enable(void)
+{
+	/*
+	 * The SNP support requires that IOMMU must be enabled, and is
+	 * not configured in the passthrough mode.
+	 */
+	if (no_iommu || iommu_default_passthrough()) {
+		pr_err("SNP: IOMMU is disabled or configured in passthrough mode, SNP cannot be supported");
+		return -EINVAL;
+	}
+
+	/*
+	 * Prevent enabling SNP after IOMMU_ENABLED state because this process
+	 * affect how IOMMU driver sets up data structures and configures
+	 * IOMMU hardware.
+	 */
+	if (init_state > IOMMU_ENABLED) {
+		pr_err("SNP: Too late to enable SNP for IOMMU.\n");
+		return -EINVAL;
+	}
+
+	amd_iommu_snp_en = check_feature_on_all_iommus(FEATURE_SNP);
+	if (!amd_iommu_snp_en)
+		return -EINVAL;
+
+	pr_info("SNP enabled\n");
+
+	/* Enforce IOMMU v1 pagetable when SNP is enabled. */
+	if (amd_iommu_pgtable != AMD_IOMMU_V1) {
+		pr_warn("Force to using AMD IOMMU v1 page table due to SNP\n");
+		amd_iommu_pgtable = AMD_IOMMU_V1;
+	}
+
+	return 0;
+}
+#endif
diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h
index 58e6c3806c09..953e6f12fa1c 100644
--- a/include/linux/amd-iommu.h
+++ b/include/linux/amd-iommu.h
@@ -206,4 +206,8 @@ int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, u8 fxn,
 		u64 *value);
 struct amd_iommu *get_amd_iommu(unsigned int idx);
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+int amd_iommu_snp_enable(void);
+#endif
+
 #endif /* _ASM_X86_AMD_IOMMU_H */
-- 
2.32.0


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

* [PATCH v4 7/9] iommu/amd: Set translation valid bit only when IO page tables are in use
  2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
                   ` (5 preceding siblings ...)
  2022-07-13 22:56 ` [PATCH v4 6/9] iommu/amd: Introduce function to check and enable SNP Suravee Suthikulpanit
@ 2022-07-13 22:56 ` Suravee Suthikulpanit
  2022-07-13 22:56 ` [PATCH v4 8/9] iommu/amd: Do not support IOMMU_DOMAIN_IDENTITY after SNP is enabled Suravee Suthikulpanit
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Suravee Suthikulpanit @ 2022-07-13 22:56 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: joro, robin.murphy, vasant.hegde, ashish.kalra, jon.grimm,
	Suravee Suthikulpanit

On AMD system with SNP enabled, IOMMU hardware checks the host translation
valid (TV) and guest translation valid (GV) bits in the device table entry
(DTE) before accessing the corresponded page tables.

However, current IOMMU driver sets the TV bit for all devices regardless
of whether the host page table is in use. This results in
ILLEGAL_DEV_TABLE_ENTRY event for devices, which do not the host page
table root pointer set up.

Thefore, when SNP is enabled, only set TV bit when DMA remapping is not
used, which is when domain ID in the AMD IOMMU device table entry (DTE)
is zero.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
 drivers/iommu/amd/init.c  |  3 ++-
 drivers/iommu/amd/iommu.c | 16 ++++++++++++++--
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 1dd1c2b25898..959595c49656 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -2566,7 +2566,8 @@ static void init_device_table_dma(struct amd_iommu_pci_seg *pci_seg)
 
 	for (devid = 0; devid <= pci_seg->last_bdf; ++devid) {
 		__set_dev_entry_bit(dev_table, devid, DEV_ENTRY_VALID);
-		__set_dev_entry_bit(dev_table, devid, DEV_ENTRY_TRANSLATION);
+		if (!amd_iommu_snp_en)
+			__set_dev_entry_bit(dev_table, devid, DEV_ENTRY_TRANSLATION);
 	}
 }
 
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index a56a9ad3273e..aedeff8af929 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1552,7 +1552,15 @@ static void set_dte_entry(struct amd_iommu *iommu, u16 devid,
 
 	pte_root |= (domain->iop.mode & DEV_ENTRY_MODE_MASK)
 		    << DEV_ENTRY_MODE_SHIFT;
-	pte_root |= DTE_FLAG_IR | DTE_FLAG_IW | DTE_FLAG_V | DTE_FLAG_TV;
+
+	pte_root |= DTE_FLAG_IR | DTE_FLAG_IW | DTE_FLAG_V;
+
+	/*
+	 * When SNP is enabled, Only set TV bit when IOMMU
+	 * page translation is in use.
+	 */
+	if (!amd_iommu_snp_en || (domain->id != 0))
+		pte_root |= DTE_FLAG_TV;
 
 	flags = dev_table[devid].data[1];
 
@@ -1612,7 +1620,11 @@ static void clear_dte_entry(struct amd_iommu *iommu, u16 devid)
 	struct dev_table_entry *dev_table = get_dev_table(iommu);
 
 	/* remove entry from the device table seen by the hardware */
-	dev_table[devid].data[0]  = DTE_FLAG_V | DTE_FLAG_TV;
+	dev_table[devid].data[0]  = DTE_FLAG_V;
+
+	if (!amd_iommu_snp_en)
+		dev_table[devid].data[0] |= DTE_FLAG_TV;
+
 	dev_table[devid].data[1] &= DTE_FLAG_MASK;
 
 	amd_iommu_apply_erratum_63(iommu, devid);
-- 
2.32.0


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

* [PATCH v4 8/9] iommu/amd: Do not support IOMMU_DOMAIN_IDENTITY after SNP is enabled
  2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
                   ` (6 preceding siblings ...)
  2022-07-13 22:56 ` [PATCH v4 7/9] iommu/amd: Set translation valid bit only when IO page tables are in use Suravee Suthikulpanit
@ 2022-07-13 22:56 ` Suravee Suthikulpanit
  2022-07-15  8:46   ` Joerg Roedel
  2022-07-13 22:56 ` [PATCH v4 9/9] iommu/amd: Do not support IOMMUv2 APIs when " Suravee Suthikulpanit
  2022-07-15  8:44 ` [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Joerg Roedel
  9 siblings, 1 reply; 12+ messages in thread
From: Suravee Suthikulpanit @ 2022-07-13 22:56 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: joro, robin.murphy, vasant.hegde, ashish.kalra, jon.grimm,
	Suravee Suthikulpanit

Once SNP is enabled (by executing SNP_INIT command), IOMMU can no longer
support the passthrough domain (i.e. IOMMU_DOMAIN_IDENTITY).

The SNP_INIT command is called early in the boot process, and would fail
if the kernel is configure to default to passthrough mode.

After the system is already booted, users can try to change IOMMU domain
type of a particular IOMMU group. In this case, the IOMMU driver needs to
check the SNP-enable status and return failure when requesting to change
domain type to identity.

Therefore, return failure when trying to allocate identity domain.

Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
 drivers/iommu/amd/iommu.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index aedeff8af929..59f9607b34bc 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2068,6 +2068,14 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
 {
 	struct protection_domain *domain;
 
+	/*
+	 * Since DTE[Mode]=0 is prohibited on SNP-enabled system,
+	 * default to use IOMMU_DOMAIN_DMA[_FQ].
+	 */
+	if (WARN_ONCE(amd_iommu_snp_en && (type == IOMMU_DOMAIN_IDENTITY),
+		      "Cannot allocate identity domain due to SNP\n"))
+		return NULL;
+
 	domain = protection_domain_alloc(type);
 	if (!domain)
 		return NULL;
-- 
2.32.0


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

* [PATCH v4 9/9] iommu/amd: Do not support IOMMUv2 APIs when SNP is enabled
  2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
                   ` (7 preceding siblings ...)
  2022-07-13 22:56 ` [PATCH v4 8/9] iommu/amd: Do not support IOMMU_DOMAIN_IDENTITY after SNP is enabled Suravee Suthikulpanit
@ 2022-07-13 22:56 ` Suravee Suthikulpanit
  2022-07-15  8:44 ` [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Joerg Roedel
  9 siblings, 0 replies; 12+ messages in thread
From: Suravee Suthikulpanit @ 2022-07-13 22:56 UTC (permalink / raw)
  To: linux-kernel, iommu
  Cc: joro, robin.murphy, vasant.hegde, ashish.kalra, jon.grimm,
	Suravee Suthikulpanit

The IOMMUv2 APIs (for supporting shared virtual memory with PASID)
configures the domain with IOMMU v2 page table, and sets DTE[Mode]=0.
This configuration cannot be supported on SNP-enabled system.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
---
 drivers/iommu/amd/init.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 959595c49656..2cfac23d34a6 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -3455,7 +3455,12 @@ __setup("ivrs_acpihid",		parse_ivrs_acpihid);
 
 bool amd_iommu_v2_supported(void)
 {
-	return amd_iommu_v2_present;
+	/*
+	 * Since DTE[Mode]=0 is prohibited on SNP-enabled system
+	 * (i.e. EFR[SNPSup]=1), IOMMUv2 page table cannot be used without
+	 * setting up IOMMUv1 page table.
+	 */
+	return amd_iommu_v2_present && !amd_iommu_snp_en;
 }
 EXPORT_SYMBOL(amd_iommu_v2_supported);
 
-- 
2.32.0


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

* Re: [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system
  2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
                   ` (8 preceding siblings ...)
  2022-07-13 22:56 ` [PATCH v4 9/9] iommu/amd: Do not support IOMMUv2 APIs when " Suravee Suthikulpanit
@ 2022-07-15  8:44 ` Joerg Roedel
  9 siblings, 0 replies; 12+ messages in thread
From: Joerg Roedel @ 2022-07-15  8:44 UTC (permalink / raw)
  To: Suravee Suthikulpanit
  Cc: linux-kernel, iommu, robin.murphy, vasant.hegde, ashish.kalra,
	jon.grimm

On Wed, Jul 13, 2022 at 05:56:42PM -0500, Suravee Suthikulpanit wrote:
> Brijesh Singh (1):
>   iommu/amd: Introduce function to check and enable SNP
> 
> Suravee Suthikulpanit (8):
>   iommu/amd: Change macro for IOMMU control register bit shift to
>     decimal value
>   iommu/amd: Introduce Support for Extended Feature 2 Register
>   iommu/amd: Introduce global variable for storing common EFR and EFR2
>   iommu/amd: Process all IVHDs before enabling IOMMU features
>   iommu/amd: Globally detect SNP support
>   iommu/amd: Set translation valid bit only when IO page tables are in
>     use
>   iommu/amd: Do not support IOMMU_DOMAIN_IDENTITY after SNP is enabled
>   iommu/amd: Do not support IOMMUv2 APIs when SNP is enabled

Applied, thanks Suravee.


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

* Re: [PATCH v4 8/9] iommu/amd: Do not support IOMMU_DOMAIN_IDENTITY after SNP is enabled
  2022-07-13 22:56 ` [PATCH v4 8/9] iommu/amd: Do not support IOMMU_DOMAIN_IDENTITY after SNP is enabled Suravee Suthikulpanit
@ 2022-07-15  8:46   ` Joerg Roedel
  0 siblings, 0 replies; 12+ messages in thread
From: Joerg Roedel @ 2022-07-15  8:46 UTC (permalink / raw)
  To: Suravee Suthikulpanit
  Cc: linux-kernel, iommu, robin.murphy, vasant.hegde, ashish.kalra,
	jon.grimm

On Wed, Jul 13, 2022 at 05:56:50PM -0500, Suravee Suthikulpanit wrote:
> +	/*
> +	 * Since DTE[Mode]=0 is prohibited on SNP-enabled system,
> +	 * default to use IOMMU_DOMAIN_DMA[_FQ].
> +	 */
> +	if (WARN_ONCE(amd_iommu_snp_en && (type == IOMMU_DOMAIN_IDENTITY),
> +		      "Cannot allocate identity domain due to SNP\n"))

I removed that WARN_ON_ONCE() here, this is really no condition someone
should worry about.

Regards,

	Joerg



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

end of thread, other threads:[~2022-07-15  8:46 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-07-13 22:56 [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Suravee Suthikulpanit
2022-07-13 22:56 ` [PATCH v4 1/9] iommu/amd: Change macro for IOMMU control register bit shift to decimal value Suravee Suthikulpanit
2022-07-13 22:56 ` [PATCH v4 2/9] iommu/amd: Introduce Support for Extended Feature 2 Register Suravee Suthikulpanit
2022-07-13 22:56 ` [PATCH v4 3/9] iommu/amd: Introduce global variable for storing common EFR and EFR2 Suravee Suthikulpanit
2022-07-13 22:56 ` [PATCH v4 4/9] iommu/amd: Process all IVHDs before enabling IOMMU features Suravee Suthikulpanit
2022-07-13 22:56 ` [PATCH v4 5/9] iommu/amd: Globally detect SNP support Suravee Suthikulpanit
2022-07-13 22:56 ` [PATCH v4 6/9] iommu/amd: Introduce function to check and enable SNP Suravee Suthikulpanit
2022-07-13 22:56 ` [PATCH v4 7/9] iommu/amd: Set translation valid bit only when IO page tables are in use Suravee Suthikulpanit
2022-07-13 22:56 ` [PATCH v4 8/9] iommu/amd: Do not support IOMMU_DOMAIN_IDENTITY after SNP is enabled Suravee Suthikulpanit
2022-07-15  8:46   ` Joerg Roedel
2022-07-13 22:56 ` [PATCH v4 9/9] iommu/amd: Do not support IOMMUv2 APIs when " Suravee Suthikulpanit
2022-07-15  8:44 ` [PATCH v4 0/9] iommu/amd: Enforce IOMMU restrictions for SNP-enabled system Joerg Roedel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox