]> www.infradead.org Git - users/hch/misc.git/commitdiff
x86/sev: Avoid global variable to store virtual address of SVSM area
authorArd Biesheuvel <ardb@kernel.org>
Thu, 28 Aug 2025 10:22:09 +0000 (12:22 +0200)
committerBorislav Petkov (AMD) <bp@alien8.de>
Wed, 3 Sep 2025 15:58:15 +0000 (17:58 +0200)
The boottime SVSM calling area is used both by the startup code running from
a 1:1 mapping, and potentially later on running from the ordinary kernel
mapping.

This SVSM calling area is statically allocated, and so its physical address
doesn't change. However, its virtual address depends on the calling context
(1:1 mapping or kernel virtual mapping), and even though the variable that
holds the virtual address of this calling area gets updated from 1:1 address
to kernel address during the boot, it is hard to reason about why this is
guaranteed to be safe.

So instead, take the RIP-relative address of the boottime SVSM calling area
whenever its virtual address is required, and only use a global variable for
the physical address.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Link: https://lore.kernel.org/20250828102202.1849035-30-ardb+git@google.com
arch/x86/boot/compressed/sev.c
arch/x86/boot/startup/sev-shared.c
arch/x86/boot/startup/sev-startup.c
arch/x86/coco/sev/core.c
arch/x86/include/asm/sev-internal.h
arch/x86/include/asm/sev.h
arch/x86/mm/mem_encrypt_amd.c

index f197173d60e67135ef92d1d807b1baa37e1986f9..f2b8dfbd453ccca35de8aff0d5ab5b4c29fb681b 100644 (file)
@@ -37,12 +37,12 @@ struct ghcb *boot_ghcb;
 
 #define __BOOT_COMPRESSED
 
-extern struct svsm_ca *boot_svsm_caa;
 extern u64 boot_svsm_caa_pa;
 
 struct svsm_ca *svsm_get_caa(void)
 {
-       return boot_svsm_caa;
+       /* The decompressor is mapped 1:1 so VA == PA */
+       return (struct svsm_ca *)boot_svsm_caa_pa;
 }
 
 u64 svsm_get_caa_pa(void)
@@ -532,7 +532,6 @@ bool early_is_sevsnp_guest(void)
 
                        /* Obtain the address of the calling area to use */
                        boot_rdmsr(MSR_SVSM_CAA, &m);
-                       boot_svsm_caa = (void *)m.q;
                        boot_svsm_caa_pa = m.q;
 
                        /*
index 348811aa784713e94caa86f2c3e17df9d5f0cdf3..80d4fdada33a8224c1febf1464764138a5cd2089 100644 (file)
@@ -13,6 +13,7 @@
 
 #ifndef __BOOT_COMPRESSED
 #define error(v)                       pr_err(v)
+#define has_cpuflag(f)                 boot_cpu_has(f)
 #else
 #undef WARN
 #define WARN(condition, format...) (!!(condition))
@@ -26,7 +27,6 @@
  *   early boot, both with identity mapped virtual addresses and proper kernel
  *   virtual addresses.
  */
-struct svsm_ca *boot_svsm_caa __ro_after_init;
 u64 boot_svsm_caa_pa __ro_after_init;
 
 /*
@@ -720,11 +720,6 @@ static bool __head svsm_setup_ca(const struct cc_blob_sev_info *cc_info,
        if (caa & (PAGE_SIZE - 1))
                sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SVSM_CAA);
 
-       /*
-        * The CA is identity mapped when this routine is called, both by the
-        * decompressor code and the early kernel code.
-        */
-       boot_svsm_caa = (struct svsm_ca *)caa;
        boot_svsm_caa_pa = caa;
 
        /* Advertise the SVSM presence via CPUID. */
index fd18a00f000e87dd12fd1ea2c78c01ec140c27e8..8a06f6026101321c0c46840977ee629d09221b61 100644 (file)
@@ -252,6 +252,7 @@ found_cc_info:
 
 static __head void svsm_setup(struct cc_blob_sev_info *cc_info)
 {
+       struct snp_secrets_page *secrets = (void *)cc_info->secrets_phys;
        struct svsm_call call = {};
        u64 pa;
 
@@ -272,21 +273,21 @@ static __head void svsm_setup(struct cc_blob_sev_info *cc_info)
        pa = (u64)rip_rel_ptr(&boot_svsm_ca_page);
 
        /*
-        * Switch over to the boot SVSM CA while the current CA is still
-        * addressable. There is no GHCB at this point so use the MSR protocol.
+        * Switch over to the boot SVSM CA while the current CA is still 1:1
+        * mapped and thus addressable with VA == PA. There is no GHCB at this
+        * point so use the MSR protocol.
         *
         * SVSM_CORE_REMAP_CA call:
         *   RAX = 0 (Protocol=0, CallID=0)
         *   RCX = New CA GPA
         */
-       call.caa = svsm_get_caa();
+       call.caa = (struct svsm_ca *)secrets->svsm_caa;
        call.rax = SVSM_CORE_CALL(SVSM_CORE_REMAP_CA);
        call.rcx = pa;
 
        if (svsm_call_msr_protocol(&call))
                sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SVSM_CA_REMAP_FAIL);
 
-       boot_svsm_caa = (struct svsm_ca *)pa;
        boot_svsm_caa_pa = pa;
 }
 
index 2a28d14425d497026f8cae79817b7966e3ad950d..ff1e2be8b5a844d936c57f00a9fe1b45ab1e4001 100644 (file)
@@ -1666,15 +1666,6 @@ void sev_show_status(void)
        pr_cont("\n");
 }
 
-void __init snp_update_svsm_ca(void)
-{
-       if (!snp_vmpl)
-               return;
-
-       /* Update the CAA to a proper kernel address */
-       boot_svsm_caa = &boot_svsm_ca_page;
-}
-
 #ifdef CONFIG_SYSFS
 static ssize_t vmpl_show(struct kobject *kobj,
                         struct kobj_attribute *attr, char *buf)
index 6199b35a82e4e4d7b6b7ef0de4ccd0d91a87cc54..ffe4755962fe8ee8d0e27ecb1e826f47f23b65b6 100644 (file)
@@ -60,7 +60,6 @@ void early_set_pages_state(unsigned long vaddr, unsigned long paddr,
 DECLARE_PER_CPU(struct svsm_ca *, svsm_caa);
 DECLARE_PER_CPU(u64, svsm_caa_pa);
 
-extern struct svsm_ca *boot_svsm_caa;
 extern u64 boot_svsm_caa_pa;
 
 static __always_inline struct svsm_ca *svsm_get_caa(void)
@@ -68,7 +67,7 @@ static __always_inline struct svsm_ca *svsm_get_caa(void)
        if (sev_cfg.use_cas)
                return this_cpu_read(svsm_caa);
        else
-               return boot_svsm_caa;
+               return rip_rel_ptr(&boot_svsm_ca_page);
 }
 
 static __always_inline u64 svsm_get_caa_pa(void)
index be9d7cb87ad0e7f2839141164e6bcd4f6e5f3205..92b1269c877e4156315f97a2a19b17de6facd055 100644 (file)
@@ -519,7 +519,6 @@ void snp_accept_memory(phys_addr_t start, phys_addr_t end);
 u64 snp_get_unsupported_features(u64 status);
 u64 sev_get_status(void);
 void sev_show_status(void);
-void snp_update_svsm_ca(void);
 int prepare_pte_enc(struct pte_enc_desc *d);
 void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot);
 void snp_kexec_finish(void);
@@ -601,7 +600,6 @@ static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
 static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
 static inline u64 sev_get_status(void) { return 0; }
 static inline void sev_show_status(void) { }
-static inline void snp_update_svsm_ca(void) { }
 static inline int prepare_pte_enc(struct pte_enc_desc *d) { return 0; }
 static inline void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot) { }
 static inline void snp_kexec_finish(void) { }
index faf3a13fb6ba0b19e2e8f6ee9c21133138acf404..2f8c32173972d6e5aad691f421e776def448dd42 100644 (file)
@@ -536,12 +536,6 @@ void __init sme_early_init(void)
                x86_init.resources.dmi_setup = snp_dmi_setup;
        }
 
-       /*
-        * Switch the SVSM CA mapping (if active) from identity mapped to
-        * kernel mapped.
-        */
-       snp_update_svsm_ca();
-
        if (sev_status & MSR_AMD64_SNP_SECURE_TSC)
                setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
 }