]> git.baikalelectronics.ru Git - kernel.git/commitdiff
x86/sev: Add SEV-SNP feature detection/setup
authorMichael Roth <michael.roth@amd.com>
Thu, 24 Feb 2022 16:56:18 +0000 (10:56 -0600)
committerBorislav Petkov <bp@suse.de>
Thu, 7 Apr 2022 14:47:11 +0000 (16:47 +0200)
Initial/preliminary detection of SEV-SNP is done via the Confidential
Computing blob. Check for it prior to the normal SEV/SME feature
initialization, and add some sanity checks to confirm it agrees with
SEV-SNP CPUID/MSR bits.

Signed-off-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20220307213356.2797205-39-brijesh.singh@amd.com
arch/x86/boot/compressed/sev.c
arch/x86/include/asm/sev.h
arch/x86/kernel/sev-shared.c
arch/x86/kernel/sev.c
arch/x86/mm/mem_encrypt_identity.c

index 1e4930ce2c958533c4b353093cd219261b909896..82079ce7be06957a7a91f05143bde67ca224a99b 100644 (file)
@@ -352,33 +352,6 @@ static struct cc_blob_sev_info *find_cc_blob_efi(struct boot_params *bp)
                                                                EFI_CC_BLOB_GUID);
 }
 
-struct cc_setup_data {
-       struct setup_data header;
-       u32 cc_blob_address;
-};
-
-/*
- * Search for a Confidential Computing blob passed in as a setup_data entry
- * via the Linux Boot Protocol.
- */
-static struct cc_blob_sev_info *find_cc_blob_setup_data(struct boot_params *bp)
-{
-       struct cc_setup_data *sd = NULL;
-       struct setup_data *hdr;
-
-       hdr = (struct setup_data *)bp->hdr.setup_data;
-
-       while (hdr) {
-               if (hdr->type == SETUP_CC_BLOB) {
-                       sd = (struct cc_setup_data *)hdr;
-                       return (struct cc_blob_sev_info *)(unsigned long)sd->cc_blob_address;
-               }
-               hdr = (struct setup_data *)hdr->next;
-       }
-
-       return NULL;
-}
-
 /*
  * Initial set up of SNP relies on information provided by the
  * Confidential Computing blob, which can be passed to the boot kernel
index 31b3b10323b601655533ca23456b28597f89a5bd..84d3d5121e9c9afac1e1f0fc21d430486355bd02 100644 (file)
@@ -153,6 +153,7 @@ void snp_set_memory_shared(unsigned long vaddr, unsigned int npages);
 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);
 #else
 static inline void sev_es_ist_enter(struct pt_regs *regs) { }
 static inline void sev_es_ist_exit(void) { }
@@ -171,6 +172,7 @@ static inline void snp_set_memory_shared(unsigned long vaddr, unsigned int npage
 static inline void snp_set_memory_private(unsigned long vaddr, unsigned int npages) { }
 static inline void snp_set_wakeup_secondary_cpu(void) { }
 static inline bool snp_init(struct boot_params *bp) { return false; }
+static inline void snp_abort(void) { }
 #endif
 
 #endif
index 0f1375164ff0bc53bf73c3e1c175db05caf21817..a7a1c0fb298e018644d946b9a6f37234d5a93626 100644 (file)
@@ -937,3 +937,30 @@ static enum es_result vc_handle_rdtsc(struct ghcb *ghcb,
 
        return ES_OK;
 }
+
+struct cc_setup_data {
+       struct setup_data header;
+       u32 cc_blob_address;
+};
+
+/*
+ * Search for a Confidential Computing blob passed in as a setup_data entry
+ * via the Linux Boot Protocol.
+ */
+static struct cc_blob_sev_info *find_cc_blob_setup_data(struct boot_params *bp)
+{
+       struct cc_setup_data *sd = NULL;
+       struct setup_data *hdr;
+
+       hdr = (struct setup_data *)bp->hdr.setup_data;
+
+       while (hdr) {
+               if (hdr->type == SETUP_CC_BLOB) {
+                       sd = (struct cc_setup_data *)hdr;
+                       return (struct cc_blob_sev_info *)(unsigned long)sd->cc_blob_address;
+               }
+               hdr = (struct setup_data *)hdr->next;
+       }
+
+       return NULL;
+}
index 0c2bf39c4a8f52b72374ca6159017f5b564ea620..692da7b291276314db13131dabe89a951bb53387 100644 (file)
@@ -1974,3 +1974,67 @@ fail:
        while (true)
                halt();
 }
+
+/*
+ * Initial set up of SNP relies on information provided by the
+ * Confidential Computing blob, which can be passed to the kernel
+ * in the following ways, depending on how it is booted:
+ *
+ * - when booted via the boot/decompress kernel:
+ *   - via boot_params
+ *
+ * - when booted directly by firmware/bootloader (e.g. CONFIG_PVH):
+ *   - via a setup_data entry, as defined by the Linux Boot Protocol
+ *
+ * Scan for the blob in that order.
+ */
+static __init struct cc_blob_sev_info *find_cc_blob(struct boot_params *bp)
+{
+       struct cc_blob_sev_info *cc_info;
+
+       /* Boot kernel would have passed the CC blob via boot_params. */
+       if (bp->cc_blob_address) {
+               cc_info = (struct cc_blob_sev_info *)(unsigned long)bp->cc_blob_address;
+               goto found_cc_info;
+       }
+
+       /*
+        * If kernel was booted directly, without the use of the
+        * boot/decompression kernel, the CC blob may have been passed via
+        * setup_data instead.
+        */
+       cc_info = find_cc_blob_setup_data(bp);
+       if (!cc_info)
+               return NULL;
+
+found_cc_info:
+       if (cc_info->magic != CC_BLOB_SEV_HDR_MAGIC)
+               snp_abort();
+
+       return cc_info;
+}
+
+bool __init snp_init(struct boot_params *bp)
+{
+       struct cc_blob_sev_info *cc_info;
+
+       if (!bp)
+               return false;
+
+       cc_info = find_cc_blob(bp);
+       if (!cc_info)
+               return false;
+
+       /*
+        * The CC blob will be used later to access the secrets page. Cache
+        * it here like the boot kernel does.
+        */
+       bp->cc_blob_address = (u32)(unsigned long)cc_info;
+
+       return true;
+}
+
+void __init snp_abort(void)
+{
+       sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+}
index b43bc24d2bb6415e4fe5eb7a4bec1914d5767fb1..f415498d3175cf7f67eef6f20c72a5f247a24a2f 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/sections.h>
 #include <asm/cmdline.h>
 #include <asm/coco.h>
+#include <asm/sev.h>
 
 #include "mm_internal.h"
 
@@ -509,8 +510,11 @@ void __init sme_enable(struct boot_params *bp)
        bool active_by_default;
        unsigned long me_mask;
        char buffer[16];
+       bool snp;
        u64 msr;
 
+       snp = snp_init(bp);
+
        /* Check for the SME/SEV support leaf */
        eax = 0x80000000;
        ecx = 0;
@@ -542,6 +546,10 @@ void __init sme_enable(struct boot_params *bp)
        sev_status   = __rdmsr(MSR_AMD64_SEV);
        feature_mask = (sev_status & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT;
 
+       /* The SEV-SNP CC blob should never be present unless SEV-SNP is enabled. */
+       if (snp && !(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
+               snp_abort();
+
        /* Check if memory encryption is enabled */
        if (feature_mask == AMD_SME_BIT) {
                /*