iommu/amd: Add support for AVIC when SNP is enabled
authorSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Tue, 26 Jul 2022 13:43:48 +0000 (08:43 -0500)
committerJoerg Roedel <jroedel@suse.de>
Fri, 29 Jul 2022 08:31:06 +0000 (10:31 +0200)
In order to support AVIC on SNP-enabled system, The IOMMU driver needs to
check EFR2[SNPAVICSup] and enables the support by setting SNPAVICEn bit
in the IOMMU control register (MMIO offset 18h).

For detail, please see section "SEV-SNP Guest Virtual APIC Support" of the
AMD I/O Virtualization Technology (IOMMU) Specification.
(https://www.amd.com/system/files/TechDocs/48882_IOMMU.pdf)

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
Link: https://lore.kernel.org/r/20220726134348.6438-3-suravee.suthikulpanit@amd.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/amd/amd_iommu_types.h
drivers/iommu/amd/init.c

index 3c1205b..5b1019d 100644 (file)
 #define FEATURE_GLXVAL_SHIFT   14
 #define FEATURE_GLXVAL_MASK    (0x03ULL << FEATURE_GLXVAL_SHIFT)
 
+/* Extended Feature 2 Bits */
+#define FEATURE_SNPAVICSUP_SHIFT       5
+#define FEATURE_SNPAVICSUP_MASK                (0x07ULL << FEATURE_SNPAVICSUP_SHIFT)
+#define FEATURE_SNPAVICSUP_GAM(x) \
+       ((x & FEATURE_SNPAVICSUP_MASK) >> FEATURE_SNPAVICSUP_SHIFT == 0x1)
+
 /* Note:
  * The current driver only support 16-bit PASID.
  * Currently, hardware only implement upto 16-bit PASID
 #define CONTROL_GAINT_EN       29
 #define CONTROL_XT_EN          50
 #define CONTROL_INTCAPXT_EN    51
+#define CONTROL_SNPAVIC_EN     61
 
 #define CTRL_INV_TO_MASK       (7 << CONTROL_INV_TIMEOUT)
 #define CTRL_INV_TO_NONE       0
index 4cd94d7..6bbaf6b 100644 (file)
@@ -2794,13 +2794,22 @@ static void enable_iommus_vapic(void)
                return;
        }
 
-       /* Enabling GAM support */
+       if (amd_iommu_snp_en &&
+           !FEATURE_SNPAVICSUP_GAM(amd_iommu_efr2)) {
+               pr_warn("Force to disable Virtual APIC due to SNP\n");
+               amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA;
+               return;
+       }
+
+       /* Enabling GAM and SNPAVIC support */
        for_each_iommu(iommu) {
                if (iommu_init_ga_log(iommu) ||
                    iommu_ga_log_enable(iommu))
                        return;
 
                iommu_feature_enable(iommu, CONTROL_GAM_EN);
+               if (amd_iommu_snp_en)
+                       iommu_feature_enable(iommu, CONTROL_SNPAVIC_EN);
        }
 
        amd_iommu_irq_ops.capability |= (1 << IRQ_POSTING_CAP);