@@ -1818,6 +1818,8 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
uint8_t initrd_hash[HASH_SIZE];
uint8_t kernel_hash[HASH_SIZE];
uint8_t *hashp;
+ uint8_t *full_page = NULL;
+ int ret;
size_t hash_len = HASH_SIZE;
int aligned_len;
@@ -1826,12 +1828,25 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
return false;
}
- if (sev_snp_enabled()) {
- return false;
- }
-
area = (SevHashTableDescriptor *)data;
+ /*
+ * TODO: this is an RFC patch on top of an old tree that doesn't support
+ * the kernel-hashes=on flag.
+ *
+ * But, when kernel-hashes=off and SNP is active, we need to mark the
+ * pre-validate the hashes page as a zero page:
+ *
+ * if (kernel_hashes flag is off) {
+ * uint32_t gpa = area->base & TARGET_PAGE_MASK
+ * void *hva = gpa2hva(&mr, gpa, TARGET_PAGE_SIZE, NULL);
+ * if (!hva) { ... }
+ * ret = sev_snp_launch_update(sev_snp, gpa, hva, TARGET_PAGE_SIZE,
+ * KVM_SEV_SNP_PAGE_TYPE_ZERO);
+ * return ret == 0;
+ * }
+ */
+
/*
* Calculate hash of kernel command-line with the terminating null byte. If
* the user doesn't supply a command-line via -append, the 1-byte "\0" will
@@ -1871,7 +1886,13 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
* Populate the hashes table in the guest's memory at the OVMF-designated
* area for the SEV hashes table
*/
- ht = qemu_map_ram_ptr(NULL, area->base);
+ if (sev_snp_enabled()) {
+ full_page = qemu_map_ram_ptr(NULL, area->base & TARGET_PAGE_MASK);
+ memset(full_page, 0, TARGET_PAGE_SIZE);
+ ht = (SevHashTable *)(full_page + (area->base & ~TARGET_PAGE_MASK));
+ } else {
+ ht = (SevHashTable *)qemu_map_ram_ptr(NULL, area->base);
+ }
ht->guid = sev_hash_table_header_guid;
ht->len = sizeof(*ht);
@@ -1895,11 +1916,14 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
memset(ht->padding, 0, aligned_len - ht->len);
}
- if (sev_encrypt_flash(area->base, (uint8_t *)ht, aligned_len, errp) < 0) {
- return false;
+ if (sev_snp_enabled()) {
+ ret = sev_encrypt_flash(area->base & TARGET_PAGE_MASK, full_page,
+ TARGET_PAGE_SIZE, errp);
+ } else {
+ ret = sev_encrypt_flash(area->base, (uint8_t *)ht, aligned_len, errp);
}
- return true;
+ return ret >= 0;
}
static void
This is an RFC patch based on AMD's RFC snp-v3 tree [1]. In SNP, the hashes page is not included in the ranges to pre-validate that appear in the SNP metadata published by OVMF (See [2] for proposed OVMF patches). Therefore, if the user enabled kernel hashes (for measured direct boot), we should fill hashes table and encrypt the page. Note that in SNP (unlike SEV and SEV-ES) the measurements is done in whole 4KB pages. Therefore we zero the whole page that includes the hashes table, and fill in the kernel hashes area in that page, and then encrypt 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 page as a zero page. Note that the base branch [1] doesn't yet include the kernel-hashes flag. [1] https://github.com/AMDESE/qemu/tree/snp-v3 [2] https://edk2.groups.io/g/devel/message/88137 Signed-off-by: Dov Murik <dovmurik@linux.ibm.com> --- target/i386/sev.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-)