From: Brijesh Singh <brijesh.si...@amd.com> The SEV-SNP support requires that IOMMU must to enabled. It also prohibits IOMMU configurations where DTE[Mode]=0, which means the SEV-SNP feature is not supported with IOMMU passthrough domain (a.k.a IOMMU_DOMAIN_IDENTITY), or when AMD IOMMU driver is configured to not use the IOMMU host (v1) page table.
Otherwise, the SNP_INIT command (used for initializing firmware) will fail. Unlike other IOMMU features, SNP feature does not have an enable bit in the IOMMU control register. Instead, the feature is considered enabled when SNP_INIT command is executed, which is done by a separte driver. Introduce iommu_sev_snp_supported() for checking if IOMMU supports the SEV-SNP feature, and an amd_iommu_snp_en global variable to keep track of SNP enable status. Please see the IOMMU spec section 2.12 for further details. Tested-by: Ashish Kalra <vashish.ka...@amd.com> Co-developed-by: Suravee Suthikulpanit <suravee.suthikulpa...@amd.com> Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpa...@amd.com> Signed-off-by: Brijesh Singh <brijesh.si...@amd.com> --- drivers/iommu/amd/amd_iommu_types.h | 11 ++++++++ drivers/iommu/amd/init.c | 39 ++++++++++++++++++++++------- drivers/iommu/amd/iommu.c | 4 +-- include/linux/iommu.h | 9 +++++++ 4 files changed, 52 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index 328572cf6fa5..6552c0da8f32 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -450,6 +450,9 @@ extern bool amd_iommu_irq_remap; /* kmem_cache to get tables with 128 byte alignement */ extern struct kmem_cache *amd_iommu_irq_cache; +/* SNP is enabled on the system? */ +extern bool amd_iommu_snp_en; + #define PCI_SBDF_TO_SEGID(sbdf) (((sbdf) >> 16) & 0xffff) #define PCI_SBDF_TO_DEVID(sbdf) ((sbdf) & 0xffff) #define PCI_SEG_DEVID_TO_SBDF(seg, devid) ((((u32)(seg) & 0xffff) << 16) | \ @@ -999,4 +1002,12 @@ extern struct amd_irte_ops irte_32_ops; extern struct amd_irte_ops irte_128_ops; #endif +/* + * ACPI table definitions + * + * These data structures are laid over the table to parse the important values + * out of it. + */ +extern struct iommu_ops amd_iommu_ops; + #endif /* _ASM_X86_AMD_IOMMU_TYPES_H */ diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 3965bd3f4f67..da32e7bdd1fa 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -88,15 +88,6 @@ #define IVRS_GET_SBDF_ID(seg, bus, dev, fd) (((seg & 0xffff) << 16) | ((bus & 0xff) << 8) \ | ((dev & 0x1f) << 3) | (fn & 0x7)) -/* - * ACPI table definitions - * - * These data structures are laid over the table to parse the important values - * out of it. - */ - -extern const struct iommu_ops amd_iommu_ops; - /* * structure describing one IOMMU in the ACPI table. Typically followed by one * or more ivhd_entrys. @@ -166,6 +157,9 @@ static int amd_iommu_target_ivhd_type; static bool amd_iommu_snp_sup; +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 */ @@ -3543,3 +3537,30 @@ 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); } + +bool iommu_sev_snp_supported(void) +{ + /* + * The SEV-SNP support requires that IOMMU must be enabled, and is + * not configured in the passthrough mode. + */ + if (no_iommu || iommu_default_passthrough()) { + pr_err("SEV-SNP: IOMMU is either disabled or configured in passthrough mode.\n"); + return false; + } + + amd_iommu_snp_en = amd_iommu_snp_sup; + if (amd_iommu_snp_en) + pr_info("SNP enabled\n"); + + /* Enforce IOMMU v1 pagetable when SNP is enabled. */ + if ((amd_iommu_pgtable != AMD_IOMMU_V1) && + amd_iommu_snp_en) { + pr_info("Force to using AMD IOMMU v1 page table due to SNP\n"); + amd_iommu_pgtable = AMD_IOMMU_V1; + amd_iommu_ops.pgsize_bitmap = AMD_IOMMU_PGSIZES; + } + + return amd_iommu_snp_en; +} +EXPORT_SYMBOL_GPL(iommu_sev_snp_supported); diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 3e1f0fa42ec3..b9dc0d4b6d77 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -70,7 +70,7 @@ LIST_HEAD(acpihid_map); * Domain for untranslated devices - only allocated * if iommu=pt passed on kernel cmd line. */ -const struct iommu_ops amd_iommu_ops; +struct iommu_ops amd_iommu_ops; static ATOMIC_NOTIFIER_HEAD(ppr_notifier); int amd_iommu_max_glx_val = -1; @@ -2368,7 +2368,7 @@ static int amd_iommu_def_domain_type(struct device *dev) return 0; } -const struct iommu_ops amd_iommu_ops = { +struct iommu_ops amd_iommu_ops = { .capable = amd_iommu_capable, .domain_alloc = amd_iommu_domain_alloc, .probe_device = amd_iommu_probe_device, diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 9208eca4b0d1..fecb72e1b11b 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -675,6 +675,12 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, void iommu_sva_unbind_device(struct iommu_sva *handle); u32 iommu_sva_get_pasid(struct iommu_sva *handle); +#ifdef CONFIG_AMD_MEM_ENCRYPT +bool iommu_sev_snp_supported(void); +#else +static inline bool iommu_sev_snp_supported(void) { return false; } +#endif + #else /* CONFIG_IOMMU_API */ struct iommu_ops {}; @@ -1031,6 +1037,9 @@ static inline struct iommu_fwspec *dev_iommu_fwspec_get(struct device *dev) { return NULL; } + +static inline bool iommu_sev_snp_supported(void) { return false; } + #endif /* CONFIG_IOMMU_API */ /** -- 2.32.0 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu