]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
x86/sev: Do not initialize SNP if missing CPUs
authorTycho Andersen (AMD) <tycho@kernel.org>
Wed, 29 Apr 2026 15:56:35 +0000 (09:56 -0600)
committerBorislav Petkov (AMD) <bp@alien8.de>
Fri, 8 May 2026 18:28:49 +0000 (20:28 +0200)
The SEV firmware checks that the SNP enable bit is set on each CPU during SNP
initialization, and will fail if not. If there are some CPUs offline, they
will not run the setup functions, so SNP initialization will always fail.

Skip the IPIs in this case and return an error so that the CCP driver can
skip the SNP_INIT that will fail. Also print the CPU masks in order to leave
breadcrumbs so people can figure out what happened.

  [ bp: Massage commit message. ]

Suggested-by: Borislav Petkov (AMD) <bp@alien8.de>
Signed-off-by: Tycho Andersen (AMD) <tycho@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Nikunj A Dadhania <nikunj@amd.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Link: https://20260429155636.540040-1-tycho@kernel.org
arch/x86/include/asm/sev.h
arch/x86/virt/svm/sev.c

index 09e605c85de4cdf50edbdef23a87dc6be9c23d15..594cfa19cbd4bad71658c286dd71a2f3b4a1b977 100644 (file)
@@ -661,7 +661,7 @@ static inline void snp_leak_pages(u64 pfn, unsigned int pages)
 {
        __snp_leak_pages(pfn, pages, true);
 }
-void snp_prepare(void);
+int snp_prepare(void);
 void snp_shutdown(void);
 #else
 static inline bool snp_probe_rmptable_info(void) { return false; }
@@ -679,7 +679,7 @@ static inline void __snp_leak_pages(u64 pfn, unsigned int npages, bool dump_rmp)
 static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
 static inline void kdump_sev_callback(void) { }
 static inline void snp_fixup_e820_tables(void) {}
-static inline void snp_prepare(void) {}
+static inline int snp_prepare(void) { return -ENODEV; }
 static inline void snp_shutdown(void) {}
 #endif
 
index 41f76f15caa131544fbd8afb644715ee0dd850f9..8bcdce98f6dce4c2b5d0e5ca3be6f020d60d2d03 100644 (file)
@@ -511,8 +511,9 @@ static void clear_hsave_pa(void *arg)
        wrmsrq(MSR_VM_HSAVE_PA, 0);
 }
 
-void snp_prepare(void)
+int snp_prepare(void)
 {
+       int ret;
        u64 val;
 
        /*
@@ -521,12 +522,20 @@ void snp_prepare(void)
         */
        rdmsrq(MSR_AMD64_SYSCFG, val);
        if (val & MSR_AMD64_SYSCFG_SNP_EN)
-               return;
+               return 0;
 
        clear_rmp();
 
        cpus_read_lock();
 
+       if (!cpumask_equal(cpu_online_mask, cpu_present_mask)) {
+               ret = -EOPNOTSUPP;
+               pr_warn("SNP init failed: not all CPUs online. (%*pbl online <-> %*pbl present masks).\n",
+                       cpumask_pr_args(cpu_online_mask),
+                       cpumask_pr_args(cpu_present_mask));
+               goto unlock;
+       }
+
        /*
         * MtrrFixDramModEn is not shared between threads on a core,
         * therefore it must be set on all CPUs prior to enabling SNP.
@@ -537,7 +546,12 @@ void snp_prepare(void)
        /* SNP_INIT requires MSR_VM_HSAVE_PA to be cleared on all CPUs. */
        on_each_cpu(clear_hsave_pa, NULL, 1);
 
+       ret = 0;
+
+unlock:
        cpus_read_unlock();
+
+       return ret;
 }
 EXPORT_SYMBOL_FOR_MODULES(snp_prepare, "ccp");