x86/sev: Add a sev= cmdline option

For debugging purposes it is very useful to have a way to see the full
contents of the SNP CPUID table provided to a guest. Add an sev=debug
kernel command-line option to do so.

Also introduce some infrastructure so that additional options can be
specified via sev=option1[,option2] over time in a consistent manner.

  [ bp: Massage, simplify string parsing. ]

Suggested-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20220307213356.2797205-41-brijesh.singh@amd.com
This commit is contained in:
Michael Roth 2022-03-07 15:33:50 -06:00 committed by Borislav Petkov
parent 30612045e6
commit ba37a1438a
3 changed files with 60 additions and 0 deletions

View file

@ -5308,6 +5308,8 @@
serialnumber [BUGS=X86-32] serialnumber [BUGS=X86-32]
sev=option[,option...] [X86-64] See Documentation/x86/x86_64/boot-options.rst
shapers= [NET] shapers= [NET]
Maximal number of shapers. Maximal number of shapers.

View file

@ -310,3 +310,17 @@ Miscellaneous
Do not use GB pages for kernel direct mappings. Do not use GB pages for kernel direct mappings.
gbpages gbpages
Use GB pages for kernel direct mappings. Use GB pages for kernel direct mappings.
AMD SEV (Secure Encrypted Virtualization)
=========================================
Options relating to AMD SEV, specified via the following format:
::
sev=option1[,option2]
The available options are:
debug
Enable debug messages.

View file

@ -112,6 +112,13 @@ DEFINE_STATIC_KEY_FALSE(sev_es_enable_key);
static DEFINE_PER_CPU(struct sev_es_save_area *, sev_vmsa); static DEFINE_PER_CPU(struct sev_es_save_area *, sev_vmsa);
struct sev_config {
__u64 debug : 1,
__reserved : 63;
};
static struct sev_config sev_cfg __read_mostly;
static __always_inline bool on_vc_stack(struct pt_regs *regs) static __always_inline bool on_vc_stack(struct pt_regs *regs)
{ {
unsigned long sp = regs->sp; unsigned long sp = regs->sp;
@ -2042,6 +2049,23 @@ void __init snp_abort(void)
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED); sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
} }
static void dump_cpuid_table(void)
{
const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
int i = 0;
pr_info("count=%d reserved=0x%x reserved2=0x%llx\n",
cpuid_table->count, cpuid_table->__reserved1, cpuid_table->__reserved2);
for (i = 0; i < SNP_CPUID_COUNT_MAX; i++) {
const struct snp_cpuid_fn *fn = &cpuid_table->fn[i];
pr_info("index=%3d fn=0x%08x subfn=0x%08x: eax=0x%08x ebx=0x%08x ecx=0x%08x edx=0x%08x xcr0_in=0x%016llx xss_in=0x%016llx reserved=0x%016llx\n",
i, fn->eax_in, fn->ecx_in, fn->eax, fn->ebx, fn->ecx,
fn->edx, fn->xcr0_in, fn->xss_in, fn->__reserved);
}
}
/* /*
* It is useful from an auditing/testing perspective to provide an easy way * It is useful from an auditing/testing perspective to provide an easy way
* for the guest owner to know that the CPUID table has been initialized as * for the guest owner to know that the CPUID table has been initialized as
@ -2059,6 +2083,26 @@ static int __init report_cpuid_table(void)
pr_info("Using SNP CPUID table, %d entries present.\n", pr_info("Using SNP CPUID table, %d entries present.\n",
cpuid_table->count); cpuid_table->count);
if (sev_cfg.debug)
dump_cpuid_table();
return 0; return 0;
} }
arch_initcall(report_cpuid_table); arch_initcall(report_cpuid_table);
static int __init init_sev_config(char *str)
{
char *s;
while ((s = strsep(&str, ","))) {
if (!strcmp(s, "debug")) {
sev_cfg.debug = true;
continue;
}
pr_info("SEV command-line option '%s' was not recognized\n", s);
}
return 1;
}
__setup("sev=", init_sev_config);