diff mbox series

[RFC] i386/sev: Support measured direct -kernel boot on SNP

Message ID 20220329064038.96006-1-dovmurik@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series [RFC] i386/sev: Support measured direct -kernel boot on SNP | expand

Commit Message

Dov Murik March 29, 2022, 6:40 a.m. UTC
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(-)
diff mbox series

Patch

diff --git a/target/i386/sev.c b/target/i386/sev.c
index 3c296a59ae..dbc9d570a9 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -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