Commit ba37a143 authored by Michael Roth's avatar Michael Roth Committed by Borislav Petkov
Browse files

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: default avatarBorislav Petkov <bp@alien8.de>
Signed-off-by: default avatarMichael Roth <michael.roth@amd.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20220307213356.2797205-41-brijesh.singh@amd.com
parent 30612045
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -5308,6 +5308,8 @@

	serialnumber	[BUGS=X86-32]

	sev=option[,option...] [X86-64] See Documentation/x86/x86_64/boot-options.rst

	shapers=	[NET]
			Maximal number of shapers.

+14 −0
Original line number Diff line number Diff line
@@ -310,3 +310,17 @@ Miscellaneous
    Do not use GB pages for kernel direct mappings.
  gbpages
    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.
+44 −0
Original line number Diff line number Diff line
@@ -112,6 +112,13 @@ DEFINE_STATIC_KEY_FALSE(sev_es_enable_key);

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)
{
	unsigned long sp = regs->sp;
@@ -2042,6 +2049,23 @@ void __init snp_abort(void)
	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
 * 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",
		cpuid_table->count);

	if (sev_cfg.debug)
		dump_cpuid_table();

	return 0;
}
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);