diff mbox series

[RFC,13/26] migration: Add helpers to load confidential RAM

Message ID 20210302204822.81901-14-dovmurik@linux.vnet.ibm.com
State New
Headers show
Series Confidential guest live migration | expand

Commit Message

Dov Murik March 2, 2021, 8:48 p.m. UTC
QEMU cannot write directly to the memory of memory-encrypted guests;
this breaks normal RAM-load in the migration target.  Instead, QEMU
asks a migration helper running on an auxiliary vcpu in the guest to
restore encrypted pages as they were received from the source to a
specific GPA.

The migration helper running inside the guest can safely decrypt the
pages arrived from the source and load them into their proper location
in the guest's memory.

Loading pages uses the same shared (unencrypted) pages which both QEMU
and the guest can read from and write to.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 migration/confidential-ram.h |  2 ++
 migration/confidential-ram.c | 37 ++++++++++++++++++++++++++++++++++++
 migration/trace-events       |  1 +
 3 files changed, 40 insertions(+)
diff mbox series

Patch

diff --git a/migration/confidential-ram.h b/migration/confidential-ram.h
index 0d49718d31..ebe4073bce 100644
--- a/migration/confidential-ram.h
+++ b/migration/confidential-ram.h
@@ -14,4 +14,6 @@  void cgs_mh_cleanup(void);
 int cgs_mh_save_encrypted_page(QEMUFile *f, ram_addr_t src_gpa, uint32_t size,
                                uint64_t *bytes_sent);
 
+int cgs_mh_load_encrypted_page(QEMUFile *f, ram_addr_t dest_gpa);
+
 #endif
diff --git a/migration/confidential-ram.c b/migration/confidential-ram.c
index 65a588e7f6..fe317ee74b 100644
--- a/migration/confidential-ram.c
+++ b/migration/confidential-ram.c
@@ -182,3 +182,40 @@  int cgs_mh_save_encrypted_page(QEMUFile *f, ram_addr_t src_gpa, uint32_t size,
 
     return ret;
 }
+
+int cgs_mh_load_encrypted_page(QEMUFile *f, ram_addr_t dest_gpa)
+{
+    int ret = 1;
+    uint32_t page_hdr_len, enc_page_len;
+
+    init_cgs_mig_helper_if_needed();
+
+    assert((dest_gpa & TARGET_PAGE_MASK) == dest_gpa);
+
+    /* Read page header */
+    page_hdr_len = qemu_get_be32(f);
+    if (page_hdr_len > 1024) {
+        error_report("confidential-ram: page header is too large (%d bytes) "
+                     "when loading gpa %" PRIu64, page_hdr_len, dest_gpa);
+        return -EINVAL;
+    }
+    cmhs.io_page_hdr->len = page_hdr_len;
+    qemu_get_buffer(f, cmhs.io_page_hdr->data, page_hdr_len);
+
+    /* Read encrypted page */
+    enc_page_len = qemu_get_be32(f);
+    if (enc_page_len != TARGET_PAGE_SIZE) {
+        error_report("confidential-ram: encrypted page is too large (%d bytes) "
+                     "when loading gpa %" PRIu64, enc_page_len, dest_gpa);
+        return -EINVAL;
+    }
+    qemu_get_buffer(f, cmhs.io_page, enc_page_len);
+
+    trace_encrypted_ram_load_page(page_hdr_len, enc_page_len, dest_gpa);
+    ret = send_command_to_cgs_mig_helper(CGS_MIG_HELPER_CMD_DECRYPT, dest_gpa);
+    if (ret) {
+        error_report("confidential-ram: failed loading page at dest_gpa "
+                     "%" PRIu64 ": ret=%d", dest_gpa, ret);
+    }
+    return ret;
+}
diff --git a/migration/trace-events b/migration/trace-events
index 929de4ca98..ef31cf78cb 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -345,4 +345,5 @@  migration_pagecache_init(int64_t max_num_items) "Setting cache buckets to %" PRI
 migration_pagecache_insert(void) "Error allocating page"
 
 # confidential-ram.c
+encrypted_ram_load_page(uint32_t hdr_len, uint32_t trans_len, uint64_t gpa) "hdr_len: %u, trans_len: %u, gpa: 0x%" PRIx64
 encrypted_ram_save_page(uint32_t size, uint64_t gpa) "size: %u, gpa: 0x%" PRIx64