lkml.org 
[lkml]   [2021]   [Nov]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v7 11/45] x86/sev: Check SEV-SNP features support
    Date
    Version 2 of the GHCB specification added the advertisement of features
    that are supported by the hypervisor. If hypervisor supports the SEV-SNP
    then it must set the SEV-SNP features bit to indicate that the base
    SEV-SNP is supported.

    Check the SEV-SNP feature while establishing the GHCB, if failed,
    terminate the guest.

    Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
    ---
    arch/x86/boot/compressed/sev.c | 17 +++++++++++++++--
    arch/x86/include/asm/sev-common.h | 3 +++
    arch/x86/kernel/sev.c | 12 ++++++++++--
    3 files changed, 28 insertions(+), 4 deletions(-)

    diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
    index 78f8502e09b5..e525fa74a551 100644
    --- a/arch/x86/boot/compressed/sev.c
    +++ b/arch/x86/boot/compressed/sev.c
    @@ -119,11 +119,24 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
    /* Include code for early handlers */
    #include "../../kernel/sev-shared.c"

    -static bool early_setup_sev_es(void)
    +static inline bool sev_snp_enabled(void)
    +{
    + return sev_status & MSR_AMD64_SEV_SNP_ENABLED;
    +}
    +
    +static bool do_early_sev_setup(void)
    {
    if (!sev_es_negotiate_protocol())
    sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_PROT_UNSUPPORTED);

    + /*
    + * SNP is supported in v2 of the GHCB spec which mandates support for HV
    + * features. If SEV-SNP is enabled, then check if the hypervisor supports
    + * the SEV-SNP features.
    + */
    + if (sev_snp_enabled() && !(sev_hv_features & GHCB_HV_FT_SNP))
    + sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
    +
    if (set_page_decrypted((unsigned long)&boot_ghcb_page))
    return false;

    @@ -174,7 +187,7 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
    struct es_em_ctxt ctxt;
    enum es_result result;

    - if (!boot_ghcb && !early_setup_sev_es())
    + if (!boot_ghcb && !do_early_sev_setup())
    sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);

    vc_ghcb_invalidate(boot_ghcb);
    diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
    index 891569c07ed7..f80a3cde2086 100644
    --- a/arch/x86/include/asm/sev-common.h
    +++ b/arch/x86/include/asm/sev-common.h
    @@ -64,6 +64,8 @@
    /* GHCBData[63:12] */ \
    (((u64)(v) & GENMASK_ULL(63, 12)) >> 12)

    +#define GHCB_HV_FT_SNP BIT_ULL(0)
    +
    #define GHCB_MSR_TERM_REQ 0x100
    #define GHCB_MSR_TERM_REASON_SET_POS 12
    #define GHCB_MSR_TERM_REASON_SET_MASK 0xf
    @@ -80,6 +82,7 @@
    #define SEV_TERM_SET_GEN 0
    #define GHCB_SEV_ES_GEN_REQ 0
    #define GHCB_SEV_ES_PROT_UNSUPPORTED 1
    +#define GHCB_SNP_UNSUPPORTED 2

    /* Linux-specific reason codes (used with reason set 1) */
    #define SEV_TERM_SET_LINUX 1
    diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
    index fb48e4ddd474..80a41e413cb8 100644
    --- a/arch/x86/kernel/sev.c
    +++ b/arch/x86/kernel/sev.c
    @@ -627,12 +627,20 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
    * This function runs on the first #VC exception after the kernel
    * switched to virtual addresses.
    */
    -static bool __init sev_es_setup_ghcb(void)
    +static bool __init setup_ghcb(void)
    {
    /* First make sure the hypervisor talks a supported protocol. */
    if (!sev_es_negotiate_protocol())
    return false;

    + /*
    + * SNP is supported in v2 of the GHCB spec which mandates support for HV
    + * features. If SEV-SNP is enabled, then check if the hypervisor supports
    + * the SEV-SNP features.
    + */
    + if (cc_platform_has(CC_ATTR_SEV_SNP) && !(sev_hv_features & GHCB_HV_FT_SNP))
    + sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
    +
    /*
    * Clear the boot_ghcb. The first exception comes in before the bss
    * section is cleared.
    @@ -1453,7 +1461,7 @@ bool __init handle_vc_boot_ghcb(struct pt_regs *regs)
    enum es_result result;

    /* Do initial setup or terminate the guest */
    - if (unlikely(boot_ghcb == NULL && !sev_es_setup_ghcb()))
    + if (unlikely(!boot_ghcb && !setup_ghcb()))
    sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);

    vc_ghcb_invalidate(boot_ghcb);
    --
    2.25.1
    \
     
     \ /
      Last update: 2021-11-10 23:09    [W:2.240 / U:1.344 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site