On Fri, Jan 24, 2025, Ashish Kalra wrote: > With discussions with the AMD IOMMU team, here is the AMD IOMMU > initialization flow: .. > IOMMU SNP check > Core IOMMU subsystem init is done during iommu_subsys_init() via > subsys_initcall. This function does change the DMA mode depending on > kernel config. Hence, SNP check should be done after subsys_initcall. > That's why its done currently during IOMMU PCI init (IOMMU_PCI_INIT stage). > And for that reason snp_rmptable_init() is currently invoked via > device_initcall(). > > The summary is that we cannot move snp_rmptable_init() to subsys_initcall as > core IOMMU subsystem gets initialized via subsys_initcall. Just explicitly invoke RMP initialization during IOMMU SNP setup. Pretending there's no connection when snp_rmptable_init() checks amd_iommu_snp_en and has a comment saying it needs to come after IOMMU SNP setup is ridiculous. Compile tested only. --- From: Sean Christopherson <seanjc@xxxxxxxxxx> Date: Fri, 24 Jan 2025 16:25:58 -0800 Subject: [PATCH] x86/sev: iommu/amd: Explicitly init SNP's RMP table during IOMMU SNP setup Explicitly initialize the RMP table during IOMMU SNP setup, as there is a hard dependency on the IOMMU being configured first, and dancing around the dependency with initcall shenanigans and a comment is all kinds of stupid. The RMP is blatantly not a device; initializing it via a device_initcall() is confusing and "works" only because of dumb luck: due to kernel build order, when the the PSP driver is built-in, its effective device_initcall() just so happens to be invoked after snp_rmptable_init(). That all falls apart if the order is changed in any way. E.g. if KVM is built-in and attempts to access the RMP during its device_initcall(), chaos ensues. Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> --- arch/x86/include/asm/sev.h | 1 + arch/x86/virt/svm/sev.c | 25 ++++++++----------------- drivers/iommu/amd/init.c | 7 ++++++- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 91f08af31078..30da0fc15923 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -503,6 +503,7 @@ static inline void snp_kexec_begin(void) { } #ifdef CONFIG_KVM_AMD_SEV bool snp_probe_rmptable_info(void); +int __init snp_rmptable_init(void); int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level); void snp_dump_hva_rmpentry(unsigned long address); int psmash(u64 pfn); diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c index 9a6a943d8e41..d932aa21340b 100644 --- a/arch/x86/virt/svm/sev.c +++ b/arch/x86/virt/svm/sev.c @@ -189,19 +189,19 @@ void __init snp_fixup_e820_tables(void) * described in the SNP_INIT_EX firmware command description in the SNP * firmware ABI spec. */ -static int __init snp_rmptable_init(void) +int __init snp_rmptable_init(void) { u64 max_rmp_pfn, calc_rmp_sz, rmptable_size, rmp_end, val; void *rmptable_start; - if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) - return 0; + if (WARN_ON_ONCE(!cc_platform_has(CC_ATTR_HOST_SEV_SNP))) + return -ENOSYS; - if (!amd_iommu_snp_en) - goto nosnp; + if (WARN_ON_ONCE(!amd_iommu_snp_en)) + return -ENOSYS; if (!probed_rmp_size) - goto nosnp; + return -ENOSYS; rmp_end = probed_rmp_base + probed_rmp_size - 1; @@ -218,13 +218,13 @@ static int __init snp_rmptable_init(void) if (calc_rmp_sz > probed_rmp_size) { pr_err("Memory reserved for the RMP table does not cover full system RAM (expected 0x%llx got 0x%llx)\n", calc_rmp_sz, probed_rmp_size); - goto nosnp; + return -ENOSYS; } rmptable_start = memremap(probed_rmp_base, probed_rmp_size, MEMREMAP_WB); if (!rmptable_start) { pr_err("Failed to map RMP table\n"); - goto nosnp; + return -ENOMEM; } /* @@ -261,17 +261,8 @@ static int __init snp_rmptable_init(void) crash_kexec_post_notifiers = true; return 0; - -nosnp: - cc_platform_clear(CC_ATTR_HOST_SEV_SNP); - return -ENOSYS; } -/* - * This must be called after the IOMMU has been initialized. - */ -device_initcall(snp_rmptable_init); - static struct rmpentry *get_rmpentry(u64 pfn) { if (WARN_ON_ONCE(pfn > rmptable_max_pfn)) diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 0e0a531042ac..d00530156a72 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -3171,7 +3171,7 @@ static bool __init detect_ivrs(void) return true; } -static void iommu_snp_enable(void) +static __init void iommu_snp_enable(void) { #ifdef CONFIG_KVM_AMD_SEV if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) @@ -3196,6 +3196,11 @@ static void iommu_snp_enable(void) goto disable_snp; } + if (snp_rmptable_init()) { + pr_warn("SNP: RMP initialization failed, SNP cannot be supported.\n"); + goto disable_snp; + } + pr_info("IOMMU SNP support enabled.\n"); return; base-commit: ac80076177131f6e3291737c851a6fe32cc03fd3 --