[PATCH v7 40/45] x86/sev: use firmware-validated CPUID for SEV-SNP guests

From: Brijesh Singh
Date: Wed Nov 10 2021 - 17:10:46 EST


From: Michael Roth <michael.roth@xxxxxxx>

SEV-SNP guests will be provided the location of special 'secrets' and
'CPUID' pages via the Confidential Computing blob. This blob is
provided to the run-time kernel either through bootparams field that
was initialized by the boot/compressed kernel, or via a setup_data
structure as defined by the Linux Boot Protocol.

Locate the Confidential Computing from these sources and, if found,
use the provided CPUID page/table address to create a copy that the
run-time kernel will use when servicing cpuid instructions via a #VC
handler.

Signed-off-by: Michael Roth <michael.roth@xxxxxxx>
Signed-off-by: Brijesh Singh <brijesh.singh@xxxxxxx>
---
arch/x86/include/asm/sev.h | 10 ----------
arch/x86/kernel/sev-shared.c | 2 +-
arch/x86/kernel/sev.c | 37 ++++++++++++++++++++++++++++++++++++
3 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 2c382533aeea..76a208fd451b 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -148,16 +148,6 @@ void snp_set_memory_private(unsigned long vaddr, unsigned int npages);
void snp_set_wakeup_secondary_cpu(void);
bool snp_init(struct boot_params *bp);
void snp_abort(void);
-/*
- * TODO: These are exported only temporarily while boot/compressed/sev.c is
- * the only user. This is to avoid unused function warnings for kernel/sev.c
- * during the build of kernel proper.
- *
- * Once the code is added to consume these in kernel proper these functions
- * can be moved back to being statically-scoped to units that pull in
- * sev-shared.c via #include and these declarations can be dropped.
- */
-void __init snp_cpuid_info_create(const struct cc_blob_sev_info *cc_info);
#else
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
static inline void sev_es_ist_exit(void) { }
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
index d91b61061b1d..ce06cb7c8ed0 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/kernel/sev-shared.c
@@ -1010,7 +1010,7 @@ snp_find_cc_blob_setup_data(struct boot_params *bp)
* mapping needs to be updated in sync with all the changes to virtual memory
* layout and related mapping facilities throughout the boot process.
*/
-void __init snp_cpuid_info_create(const struct cc_blob_sev_info *cc_info)
+static void __init snp_cpuid_info_create(const struct cc_blob_sev_info *cc_info)
{
const struct snp_cpuid_info *cpuid_info_fw, *cpuid_info;

diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index b794606c7ab2..5d17f665124a 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -2062,6 +2062,12 @@ bool __init snp_init(struct boot_params *bp)
if (!cc_info)
return false;

+ snp_cpuid_info_create(cc_info);
+
+ /* SEV-SNP CPUID table is set up now. Do some sanity checks. */
+ if (!snp_cpuid_active())
+ sev_es_terminate(1, GHCB_TERM_CPUID);
+
/*
* The CC blob will be used later to access the secrets page. Cache
* it here like the boot kernel does.
@@ -2075,3 +2081,34 @@ void __init snp_abort(void)
{
sev_es_terminate(1, GHCB_SNP_UNSUPPORTED);
}
+
+/*
+ * 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
+ * expected, but that initialization happens too early in boot to print any
+ * sort of indicator, and there's not really any other good place to do it. So
+ * do it here, and while at it, go ahead and re-verify that nothing strange has
+ * happened between early boot and now.
+ */
+static int __init snp_cpuid_check_status(void)
+{
+ const struct snp_cpuid_info *cpuid_info = snp_cpuid_info_get_ptr();
+
+ if (!cc_platform_has(CC_ATTR_SEV_SNP)) {
+ /* Firmware should not have advertised the feature. */
+ if (snp_cpuid_active())
+ panic("Invalid use of SEV-SNP CPUID table.");
+ return 0;
+ }
+
+ /* CPUID table should always be available when SEV-SNP is enabled. */
+ if (!snp_cpuid_active())
+ sev_es_terminate(1, GHCB_TERM_CPUID);
+
+ pr_info("Using SEV-SNP CPUID table, %d entries present.\n",
+ cpuid_info->count);
+
+ return 0;
+}
+
+arch_initcall(snp_cpuid_check_status);
--
2.25.1