Commit a5f03880 authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Borislav Petkov (AMD)
Browse files

x86/sev: Avoid global variable to store virtual address of SVSM area



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: default avatarArd Biesheuvel <ardb@kernel.org>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Link: https://lore.kernel.org/20250828102202.1849035-30-ardb+git@google.com
parent 37dbd78f
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -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;

			/*
+1 −6
Original line number Diff line number Diff line
@@ -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. */
+5 −4
Original line number Diff line number Diff line
@@ -252,6 +252,7 @@ static __head struct cc_blob_sev_info *find_cc_blob(struct boot_params *bp)

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;
}

+0 −9
Original line number Diff line number Diff line
@@ -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)
+1 −2
Original line number Diff line number Diff line
@@ -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)
Loading