lkml.org 
[lkml]   [2022]   [Mar]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v12 39/46] x86/sev: Use firmware-validated CPUID for SEV-SNP guests
    Date
    From: Michael Roth <michael.roth@amd.com>

    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 a 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 blob 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@amd.com>
    Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
    ---
    arch/x86/boot/compressed/sev.c | 37 ----------------------------------
    arch/x86/kernel/sev-shared.c | 37 ++++++++++++++++++++++++++++++++++
    arch/x86/kernel/sev.c | 24 ++++++++++++++++++++++
    3 files changed, 61 insertions(+), 37 deletions(-)

    diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
    index 2911137bf37f..79a59027f3d8 100644
    --- a/arch/x86/boot/compressed/sev.c
    +++ b/arch/x86/boot/compressed/sev.c
    @@ -381,43 +381,6 @@ static struct cc_blob_sev_info *find_cc_blob(struct boot_params *bp)
    return cc_info;
    }

    -/*
    - * Initialize the kernel's copy of the SNP CPUID table, and set up the
    - * pointer that will be used to access it.
    - *
    - * Maintaining a direct mapping of the SNP CPUID table used by firmware would
    - * be possible as an alternative, but the approach is brittle since the
    - * mapping needs to be updated in sync with all the changes to virtual memory
    - * layout and related mapping facilities throughout the boot process.
    - */
    -static void setup_cpuid_table(const struct cc_blob_sev_info *cc_info)
    -{
    - const struct snp_cpuid_table *cpuid_table_fw, *cpuid_table;
    - int i;
    -
    - if (!cc_info || !cc_info->cpuid_phys || cc_info->cpuid_len < PAGE_SIZE)
    - sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID);
    -
    - cpuid_table_fw = (const struct snp_cpuid_table *)cc_info->cpuid_phys;
    - if (!cpuid_table_fw->count || cpuid_table_fw->count > SNP_CPUID_COUNT_MAX)
    - sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID);
    -
    - cpuid_table = snp_cpuid_get_table();
    - memcpy((void *)cpuid_table, cpuid_table_fw, sizeof(*cpuid_table));
    -
    - /* Initialize CPUID ranges for range-checking. */
    - for (i = 0; i < cpuid_table->count; i++) {
    - const struct snp_cpuid_fn *fn = &cpuid_table->fn[i];
    -
    - if (fn->eax_in == 0x0)
    - cpuid_std_range_max = fn->eax;
    - else if (fn->eax_in == 0x40000000)
    - cpuid_hyp_range_max = fn->eax;
    - else if (fn->eax_in == 0x80000000)
    - cpuid_ext_range_max = fn->eax;
    - }
    -}
    -
    /*
    * Indicate SNP based on presence of SNP-specific CC blob. Subsequent checks
    * will verify the SNP CPUID/MSR bits.
    diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
    index a7a1c0fb298e..2b4270d5559e 100644
    --- a/arch/x86/kernel/sev-shared.c
    +++ b/arch/x86/kernel/sev-shared.c
    @@ -964,3 +964,40 @@ static struct cc_blob_sev_info *find_cc_blob_setup_data(struct boot_params *bp)

    return NULL;
    }
    +
    +/*
    + * Initialize the kernel's copy of the SNP CPUID table, and set up the
    + * pointer that will be used to access it.
    + *
    + * Maintaining a direct mapping of the SNP CPUID table used by firmware would
    + * be possible as an alternative, but the approach is brittle since the
    + * mapping needs to be updated in sync with all the changes to virtual memory
    + * layout and related mapping facilities throughout the boot process.
    + */
    +static void __init setup_cpuid_table(const struct cc_blob_sev_info *cc_info)
    +{
    + const struct snp_cpuid_table *cpuid_table_fw, *cpuid_table;
    + int i;
    +
    + if (!cc_info || !cc_info->cpuid_phys || cc_info->cpuid_len < PAGE_SIZE)
    + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID);
    +
    + cpuid_table_fw = (const struct snp_cpuid_table *)cc_info->cpuid_phys;
    + if (!cpuid_table_fw->count || cpuid_table_fw->count > SNP_CPUID_COUNT_MAX)
    + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID);
    +
    + cpuid_table = snp_cpuid_get_table();
    + memcpy((void *)cpuid_table, cpuid_table_fw, sizeof(*cpuid_table));
    +
    + /* Initialize CPUID ranges for range-checking. */
    + for (i = 0; i < cpuid_table->count; i++) {
    + const struct snp_cpuid_fn *fn = &cpuid_table->fn[i];
    +
    + if (fn->eax_in == 0x0)
    + cpuid_std_range_max = fn->eax;
    + else if (fn->eax_in == 0x40000000)
    + cpuid_hyp_range_max = fn->eax;
    + else if (fn->eax_in == 0x80000000)
    + cpuid_ext_range_max = fn->eax;
    + }
    +}
    diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
    index 5a7df617394b..c6b2e0c58255 100644
    --- a/arch/x86/kernel/sev.c
    +++ b/arch/x86/kernel/sev.c
    @@ -34,6 +34,7 @@
    #include <asm/cpu.h>
    #include <asm/apic.h>
    #include <asm/cpuid.h>
    +#include <asm/cmdline.h>

    #define DR7_RESET_VALUE 0x400

    @@ -2028,6 +2029,8 @@ bool __init snp_init(struct boot_params *bp)
    if (!cc_info)
    return false;

    + setup_cpuid_table(cc_info);
    +
    /*
    * The CC blob will be used later to access the secrets page. Cache
    * it here like the boot kernel does.
    @@ -2041,3 +2044,24 @@ void __init snp_abort(void)
    {
    sev_es_terminate(SEV_TERM_SET_GEN, 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.
    + */
    +static int __init report_cpuid_table(void)
    +{
    + const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
    +
    + if (!cpuid_table->count)
    + return 0;
    +
    + pr_info("Using SNP CPUID table, %d entries present.\n",
    + cpuid_table->count);
    +
    + return 0;
    +}
    +arch_initcall(report_cpuid_table);
    --
    2.25.1
    \
     
     \ /
      Last update: 2022-03-07 22:40    [W:4.079 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site