IOMMU support for SNP feature is detected via the EFR[SNPSup] bit.
Also, it is required that EFR[SNPSup] are consistent across all IOMMU
instances.

This information is needed early in the boot process,
since it is used to determine how IOMMU driver configures several other
IOMMU features and data structures (e.g. as soon as the IOMMU driver
finishes parsing IVHDs).

Introduce a global variable for tracking the SNP support status, which is
initialized before enabling the rest of IOMMU features.

Also throw a warning if found inconsistency EFR[SNPSup] among IOMMU
instances.

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

diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 6a4a019f1e1d..3965bd3f4f67 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -164,6 +164,8 @@ static bool amd_iommu_disabled __initdata;
 static bool amd_iommu_force_enable __initdata;
 static int amd_iommu_target_ivhd_type;
 
+static bool amd_iommu_snp_sup;
+
 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 */
@@ -355,7 +357,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 (!amd_iommu_snp_sup)
                return;
 
        /* Note:
@@ -770,7 +772,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) &&
+           amd_iommu_snp_sup &&
            set_memory_4k((unsigned long)buf, (1 << order))) {
                free_pages((unsigned long)buf, order);
                buf = NULL;
@@ -1836,6 +1838,37 @@ static u8 get_highest_supported_ivhd_type(struct 
acpi_table_header *ivrs)
        return last_type;
 }
 
+/*
+ * SNP is enabled system-wide. So, iterate through all the IOMMUs to
+ * verify all EFR[SNPSup] bits are set, and use global variable to track
+ * whether the feature is supported.
+ */
+static void __init init_snp_global(void)
+{
+       struct amd_iommu *iommu;
+
+       for_each_iommu(iommu) {
+               if (iommu_feature(iommu, FEATURE_SNP)) {
+                       amd_iommu_snp_sup = true;
+                       continue;
+               }
+
+               /*
+                * Warn and mark SNP as not supported if there is inconsistency
+                * in any of the IOMMU.
+                */
+               if (amd_iommu_snp_sup && !list_is_first(&iommu->list, 
&amd_iommu_list)) {
+                       pr_err(FW_BUG "iommu%d (%04x:%02x:%02x.%01x): Found 
inconsistent EFR[SNPSup].\n",
+                              iommu->index, iommu->pci_seg->id, 
PCI_BUS_NUM(iommu->devid),
+                              PCI_SLOT(iommu->devid), PCI_FUNC(iommu->devid));
+                       pr_err(FW_BUG "Disable SNP support\n");
+                       amd_iommu_snp_sup = false;
+               }
+               return;
+       }
+       amd_iommu_snp_sup = true;
+}
+
 /*
  * Iterates over all IOMMU entries in the ACPI table, allocates the
  * IOMMU structure and initializes it with init_iommu_one()
@@ -1875,6 +1908,8 @@ static int __init init_iommu_all(struct acpi_table_header 
*table)
        }
        WARN_ON(p != end);
 
+       init_snp_global();
+
        for_each_iommu(iommu) {
                ret = init_iommu_one_late(iommu);
                if (ret)
@@ -2095,6 +2130,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

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

Reply via email to