[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v4 23/31] i386/sev: Allow measured direct kernel boot on SNP
From: |
Pankaj Gupta |
Subject: |
[PATCH v4 23/31] i386/sev: Allow measured direct kernel boot on SNP |
Date: |
Thu, 30 May 2024 06:16:35 -0500 |
From: Dov Murik <dovmurik@linux.ibm.com>
In SNP, the hashes page designated with a specific metadata entry
published in AmdSev OVMF.
Therefore, if the user enabled kernel hashes (for measured direct boot),
QEMU should prepare the content of hashes table, and during the
processing of the metadata entry it copy the content into the designated
page and encrypt it.
Note that in SNP (unlike SEV and SEV-ES) the measurements is done in
whole 4KB pages. Therefore QEMU zeros the whole page that includes the
hashes table, and fills in the kernel hashes area in that page, and then
encrypts the whole page. The rest of the page is reserved for SEV
launch secrets which are not usable anyway on SNP.
If the user disabled kernel hashes, QEMU pre-validates the kernel hashes
page as a zero page.
Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
Signed-off-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
---
include/hw/i386/pc.h | 2 ++
target/i386/sev.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index c653b8eeb2..ca7904ac2c 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -172,6 +172,8 @@ typedef enum {
SEV_DESC_TYPE_SNP_SECRETS,
/* The section contains address that can be used as a CPUID page */
SEV_DESC_TYPE_CPUID,
+ /* The section contains the region for kernel hashes for measured direct
boot */
+ SEV_DESC_TYPE_SNP_KERNEL_HASHES = 0x10,
} ovmf_sev_metadata_desc_type;
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 1b29fdbc9a..1a78e98751 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -145,6 +145,9 @@ struct SevSnpGuestState {
struct kvm_sev_snp_launch_start kvm_start_conf;
struct kvm_sev_snp_launch_finish kvm_finish_conf;
+
+ uint32_t kernel_hashes_offset;
+ PaddedSevHashTable *kernel_hashes_data;
};
struct SevSnpGuestStateClass {
@@ -1187,6 +1190,23 @@ snp_launch_update_cpuid(uint32_t cpuid_addr, void *hva,
uint32_t cpuid_len)
KVM_SEV_SNP_PAGE_TYPE_CPUID);
}
+static int
+snp_launch_update_kernel_hashes(SevSnpGuestState *sev_snp, uint32_t addr,
+ void *hva, uint32_t len)
+{
+ int type = KVM_SEV_SNP_PAGE_TYPE_ZERO;
+ if (sev_snp->parent_obj.kernel_hashes) {
+ assert(sev_snp->kernel_hashes_data);
+ assert((sev_snp->kernel_hashes_offset +
+ sizeof(*sev_snp->kernel_hashes_data)) <= len);
+ memset(hva, 0, len);
+ memcpy(hva + sev_snp->kernel_hashes_offset,
sev_snp->kernel_hashes_data,
+ sizeof(*sev_snp->kernel_hashes_data));
+ type = KVM_SEV_SNP_PAGE_TYPE_NORMAL;
+ }
+ return snp_launch_update_data(addr, hva, len, type);
+}
+
static int
snp_metadata_desc_to_page_type(int desc_type)
{
@@ -1223,6 +1243,9 @@ snp_populate_metadata_pages(SevSnpGuestState *sev_snp,
if (type == KVM_SEV_SNP_PAGE_TYPE_CPUID) {
ret = snp_launch_update_cpuid(desc->base, hva, desc->len);
+ } else if (desc->type == SEV_DESC_TYPE_SNP_KERNEL_HASHES) {
+ ret = snp_launch_update_kernel_hashes(sev_snp, desc->base, hva,
+ desc->len);
} else {
ret = snp_launch_update_data(desc->base, hva, desc->len, type);
}
@@ -1855,6 +1878,18 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext
*ctx, Error **errp)
return false;
}
+ if (sev_snp_enabled()) {
+ /*
+ * SNP: Populate the hashes table in an area that later in
+ * snp_launch_update_kernel_hashes() will be copied to the guest memory
+ * and encrypted.
+ */
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(sev_common);
+ sev_snp_guest->kernel_hashes_offset = area->base & ~TARGET_PAGE_MASK;
+ sev_snp_guest->kernel_hashes_data = g_new0(PaddedSevHashTable, 1);
+ return build_kernel_loader_hashes(sev_snp_guest->kernel_hashes_data,
ctx, errp);
+ }
+
/*
* Populate the hashes table in the guest's memory at the OVMF-designated
* area for the SEV hashes table
--
2.34.1
- [PATCH v4 21/31] i386/sev: Extract build_kernel_loader_hashes, (continued)
- [PATCH v4 21/31] i386/sev: Extract build_kernel_loader_hashes, Pankaj Gupta, 2024/05/30
- [PATCH v4 16/31] i386/sev: Add handling to encrypt/finalize guest launch data, Pankaj Gupta, 2024/05/30
- [PATCH v4 24/31] hw/i386/sev: Add support to encrypt BIOS when SEV-SNP is enabled, Pankaj Gupta, 2024/05/30
- [PATCH v4 22/31] i386/sev: Reorder struct declarations, Pankaj Gupta, 2024/05/30
- [PATCH v4 18/31] hw/i386/sev: Add function to get SEV metadata from OVMF header, Pankaj Gupta, 2024/05/30
- [PATCH v4 27/31] hw/i386/sev: Use guest_memfd for legacy ROMs, Pankaj Gupta, 2024/05/30
- [PATCH v4 26/31] i386/sev: Invoke launch_updata_data() for SNP class, Pankaj Gupta, 2024/05/30
- [PATCH v4 19/31] i386/sev: Add support for populating OVMF metadata pages, Pankaj Gupta, 2024/05/30
- [PATCH v4 23/31] i386/sev: Allow measured direct kernel boot on SNP,
Pankaj Gupta <=
- [PATCH v4 25/31] i386/sev: Invoke launch_updata_data() for SEV class, Pankaj Gupta, 2024/05/30
- [PATCH v4 30/31] i386/kvm: Add KVM_EXIT_HYPERCALL handling for KVM_HC_MAP_GPA_RANGE, Pankaj Gupta, 2024/05/30
- [PATCH v4 28/31] hw/i386: Add support for loading BIOS using guest_memfd, Pankaj Gupta, 2024/05/30
- [PATCH v4 29/31] hw/i386/sev: Allow use of pflash in conjunction with -bios, Pankaj Gupta, 2024/05/30
- [PATCH v4 31/31] i386/sev: Enable KVM_HC_MAP_GPA_RANGE hcall for SNP guests, Pankaj Gupta, 2024/05/30
- [PATCH v4 01/31] i386/sev: Replace error_report with error_setg, Pankaj Gupta, 2024/05/30