Skip to content

Commit 99ef9f5

Browse files
tlendackybp3tk0v
authored andcommitted
x86/sev: Allow non-VMPL0 execution when an SVSM is present
To allow execution at a level other than VMPL0, an SVSM must be present. Allow the SEV-SNP guest to continue booting if an SVSM is detected and the hypervisor supports the SVSM feature as indicated in the GHCB hypervisor features bitmap. [ bp: Massage a bit. ] Signed-off-by: Tom Lendacky <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Link: https://lore.kernel.org/r/2ce7cf281cce1d0cba88f3f576687ef75dc3c953.1717600736.git.thomas.lendacky@amd.com
1 parent 627dc67 commit 99ef9f5

File tree

3 files changed

+27
-11
lines changed

3 files changed

+27
-11
lines changed

arch/x86/boot/compressed/sev.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -610,11 +610,15 @@ void sev_enable(struct boot_params *bp)
610610
* features.
611611
*/
612612
if (sev_status & MSR_AMD64_SEV_SNP_ENABLED) {
613-
if (!(get_hv_features() & GHCB_HV_FT_SNP))
613+
u64 hv_features;
614+
int ret;
615+
616+
hv_features = get_hv_features();
617+
if (!(hv_features & GHCB_HV_FT_SNP))
614618
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
615619

616620
/*
617-
* Enforce running at VMPL0.
621+
* Enforce running at VMPL0 or with an SVSM.
618622
*
619623
* Use RMPADJUST (see the rmpadjust() function for a description of
620624
* what the instruction does) to update the VMPL1 permissions of a
@@ -623,7 +627,14 @@ void sev_enable(struct boot_params *bp)
623627
* only ever run at a single VMPL level so permission mask changes of a
624628
* lesser-privileged VMPL are a don't-care.
625629
*/
626-
if (rmpadjust((unsigned long)&boot_ghcb_page, RMP_PG_SIZE_4K, 1))
630+
ret = rmpadjust((unsigned long)&boot_ghcb_page, RMP_PG_SIZE_4K, 1);
631+
632+
/*
633+
* Running at VMPL0 is not required if an SVSM is present and the hypervisor
634+
* supports the required SVSM GHCB events.
635+
*/
636+
if (ret &&
637+
!(snp_vmpl && (hv_features & GHCB_HV_FT_SNP_MULTI_VMPL)))
627638
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NOT_VMPL0);
628639
}
629640

arch/x86/include/asm/sev-common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ enum psc_op {
122122

123123
#define GHCB_HV_FT_SNP BIT_ULL(0)
124124
#define GHCB_HV_FT_SNP_AP_CREATION BIT_ULL(1)
125+
#define GHCB_HV_FT_SNP_MULTI_VMPL BIT_ULL(5)
125126

126127
/*
127128
* SNP Page State Change NAE event

arch/x86/kernel/sev.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2352,23 +2352,27 @@ static void dump_cpuid_table(void)
23522352
* expected, but that initialization happens too early in boot to print any
23532353
* sort of indicator, and there's not really any other good place to do it,
23542354
* so do it here.
2355+
*
2356+
* If running as an SNP guest, report the current VM privilege level (VMPL).
23552357
*/
2356-
static int __init report_cpuid_table(void)
2358+
static int __init report_snp_info(void)
23572359
{
23582360
const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
23592361

2360-
if (!cpuid_table->count)
2361-
return 0;
2362+
if (cpuid_table->count) {
2363+
pr_info("Using SNP CPUID table, %d entries present.\n",
2364+
cpuid_table->count);
23622365

2363-
pr_info("Using SNP CPUID table, %d entries present.\n",
2364-
cpuid_table->count);
2366+
if (sev_cfg.debug)
2367+
dump_cpuid_table();
2368+
}
23652369

2366-
if (sev_cfg.debug)
2367-
dump_cpuid_table();
2370+
if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
2371+
pr_info("SNP running at VMPL%u.\n", snp_vmpl);
23682372

23692373
return 0;
23702374
}
2371-
arch_initcall(report_cpuid_table);
2375+
arch_initcall(report_snp_info);
23722376

23732377
static int __init init_sev_config(char *str)
23742378
{

0 commit comments

Comments
 (0)