lkml.org 
[lkml]   [2022]   [Feb]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v11 38/45] x86/sev: Add SEV-SNP feature detection/setup
    Date
    From: Michael Roth <michael.roth@amd.com>

    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>
    ---
    arch/x86/boot/compressed/sev.c | 27 -------------
    arch/x86/include/asm/sev.h | 2 +
    arch/x86/kernel/sev-shared.c | 27 +++++++++++++
    arch/x86/kernel/sev.c | 64 ++++++++++++++++++++++++++++++
    arch/x86/mm/mem_encrypt_identity.c | 8 ++++
    5 files changed, 101 insertions(+), 27 deletions(-)

    diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
    index 2a48f3a3f372..2911137bf37f 100644
    --- a/arch/x86/boot/compressed/sev.c
    +++ b/arch/x86/boot/compressed/sev.c
    @@ -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
    diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
    index 4e3909042001..219abb4590f2 100644
    --- a/arch/x86/include/asm/sev.h
    +++ b/arch/x86/include/asm/sev.h
    @@ -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
    diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
    index 0f1375164ff0..a7a1c0fb298e 100644
    --- a/arch/x86/kernel/sev-shared.c
    +++ b/arch/x86/kernel/sev-shared.c
    @@ -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;
    +}
    diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
    index b876b1d989eb..a79ddacf0478 100644
    --- a/arch/x86/kernel/sev.c
    +++ b/arch/x86/kernel/sev.c
    @@ -1984,3 +1984,67 @@ bool __init handle_vc_boot_ghcb(struct pt_regs *regs)
    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);
    +}
    diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c
    index b43bc24d2bb6..f415498d3175 100644
    --- a/arch/x86/mm/mem_encrypt_identity.c
    +++ b/arch/x86/mm/mem_encrypt_identity.c
    @@ -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) {
    /*
    --
    2.25.1
    \
     
     \ /
      Last update: 2022-02-24 18:05    [W:4.079 / U:0.044 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site