Commit 5f211f4f authored by Michael Roth's avatar Michael Roth Committed by Borislav Petkov

x86/compressed: Use firmware-validated CPUID leaves for SEV-SNP guests

SEV-SNP guests will be provided the location of special 'secrets'
'CPUID' pages via the Confidential Computing blob. This blob is
provided to the boot kernel either through an EFI config table entry,
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
boot kernel will use when servicing CPUID instructions via a #VC CPUID
handler.

  [ bp: s/cpuid/CPUID/ ]
Signed-off-by: default avatarMichael Roth <michael.roth@amd.com>
Signed-off-by: default avatarBrijesh Singh <brijesh.singh@amd.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20220307213356.2797205-36-brijesh.singh@amd.com
parent c01fce9c
...@@ -408,6 +408,43 @@ static struct cc_blob_sev_info *find_cc_blob(struct boot_params *bp) ...@@ -408,6 +408,43 @@ static struct cc_blob_sev_info *find_cc_blob(struct boot_params *bp)
return cc_info; 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 * Indicate SNP based on presence of SNP-specific CC blob. Subsequent checks
* will verify the SNP CPUID/MSR bits. * will verify the SNP CPUID/MSR bits.
...@@ -423,6 +460,15 @@ bool snp_init(struct boot_params *bp) ...@@ -423,6 +460,15 @@ bool snp_init(struct boot_params *bp)
if (!cc_info) if (!cc_info)
return false; return false;
/*
* If a SNP-specific Confidential Computing blob is present, then
* firmware/bootloader have indicated SNP support. Verifying this
* involves CPUID checks which will be more reliable if the SNP
* CPUID table is used. See comments over snp_setup_cpuid_table() for
* more details.
*/
setup_cpuid_table(cc_info);
/* /*
* Pass run-time kernel a pointer to CC info via boot_params so EFI * Pass run-time kernel a pointer to CC info via boot_params so EFI
* config table doesn't need to be searched again during early startup * config table doesn't need to be searched again during early startup
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment