[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH 15/26] migration: Save confidential guest RAM using migration
From: |
Dov Murik |
Subject: |
[RFC PATCH 15/26] migration: Save confidential guest RAM using migration helper |
Date: |
Tue, 2 Mar 2021 15:48:11 -0500 |
When saving RAM pages of a confidential guest, check whether a page is
encrypted. If it is, ask the in-guest migration helper to encrypt the
page for transmission.
This relies on ability to track the encryption status of each page
according to guest's reports, and thus requires the relevant patches in
the guest OS and OVMF and the host KVM and QEMU. This is all
encapsulated in is_page_encrypted; the implementation can be modified
according to the underlying implementation of page encryption status
tracking (bitmap / KVM shared regions list / user-side list)
Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
migration/ram.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/migration/ram.c b/migration/ram.c
index 997f90cc5b..8e55ed49fd 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -53,10 +53,13 @@
#include "block.h"
#include "sysemu/sysemu.h"
#include "sysemu/cpu-throttle.h"
+#include "sysemu/kvm.h"
#include "savevm.h"
#include "qemu/iov.h"
#include "multifd.h"
#include "sysemu/runstate.h"
+#include "hw/boards.h"
+#include "confidential-ram.h"
#if defined(__linux__)
#include "qemu/userfaultfd.h"
@@ -81,6 +84,7 @@
#define RAM_SAVE_FLAG_XBZRLE 0x40
/* 0x80 is reserved in migration.h start with 0x100 next */
#define RAM_SAVE_FLAG_COMPRESS_PAGE 0x100
+#define RAM_SAVE_FLAG_GUEST_ENCRYPTED_PAGE 0x200
static inline bool memcrypt_enabled(void)
{
@@ -94,6 +98,13 @@ static inline bool is_zero_range(uint8_t *p, uint64_t size)
return buffer_is_zero(p, size);
}
+static inline bool confidential_guest(void)
+{
+ MachineState *ms = MACHINE(qdev_get_machine());
+
+ return ms->cgs;
+}
+
XBZRLECacheStats xbzrle_counters;
/* struct contains XBZRLE cache and a static page
@@ -660,6 +671,23 @@ static void mig_throttle_guest_down(uint64_t
bytes_dirty_period,
}
}
+/**
+ * is_page_encrypted: check if the page is encrypted
+ *
+ * Returns a bool indicating whether the page is encrypted.
+ */
+static bool is_page_encrypted(RAMState *rs, RAMBlock *block, unsigned long
page)
+{
+ /* ROM devices contain unencrypted data */
+ if (memory_region_is_romd(block->mr) ||
+ memory_region_is_rom(block->mr) ||
+ !memory_region_is_ram(block->mr)) {
+ return false;
+ }
+
+ return test_bit(page, block->encbmap);
+}
+
/**
* xbzrle_cache_zero_page: insert a zero page in the XBZRLE cache
*
@@ -1928,6 +1956,45 @@ static bool save_compress_page(RAMState *rs, RAMBlock
*block, ram_addr_t offset)
return false;
}
+/**
+ * ram_save_encrypted_page - send the given encrypted page to the stream
+ *
+ * Return the number of pages written (=1).
+ */
+static int ram_save_encrypted_page(RAMState *rs, PageSearchStatus *pss,
+ bool last_stage)
+{
+ int ret;
+ uint8_t *p;
+ RAMBlock *block = pss->block;
+ ram_addr_t offset = pss->page << TARGET_PAGE_BITS;
+ ram_addr_t gpa;
+ uint64_t bytes_sent;
+
+ p = block->host + offset;
+
+ /* Find the GPA of the page */
+ if (!kvm_physical_memory_addr_from_host(kvm_state, p, &gpa)) {
+ error_report("%s failed to get gpa for offset %" PRIu64 " block %s",
+ __func__, offset, memory_region_name(block->mr));
+ return -1;
+ }
+
+ ram_counters.transferred +=
+ save_page_header(rs, rs->f, block,
+ offset | RAM_SAVE_FLAG_GUEST_ENCRYPTED_PAGE);
+
+ ret = cgs_mh_save_encrypted_page(rs->f, gpa, TARGET_PAGE_SIZE,
&bytes_sent);
+ if (ret) {
+ return -1;
+ }
+
+ ram_counters.transferred += bytes_sent;
+ ram_counters.normal++;
+
+ return 1;
+}
+
/**
* ram_save_target_page: save one target page
*
@@ -1948,6 +2015,26 @@ static int ram_save_target_page(RAMState *rs,
PageSearchStatus *pss,
return res;
}
+ /*
+ * If memory encryption is enabled then skip saving the data pages used by
+ * the migration handler.
+ */
+ if (confidential_guest() &&
+ gpa_inside_migration_helper_shared_area(offset)) {
+ return 0;
+ }
+
+ /*
+ * If memory encryption is enabled then use memory encryption APIs
+ * to write the outgoing buffer to the wire. The encryption APIs
+ * will take care of accessing the guest memory and re-encrypt it
+ * for the transport purposes.
+ */
+ if (confidential_guest() &&
+ is_page_encrypted(rs, pss->block, pss->page)) {
+ return ram_save_encrypted_page(rs, pss, last_stage);
+ }
+
if (save_compress_page(rs, block, offset)) {
return 1;
}
@@ -2776,6 +2863,10 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
return -1;
}
+ if (confidential_guest()) {
+ cgs_mh_init();
+ }
+
/* migration has already setup the bitmap, reuse it. */
if (!migration_in_colo_state()) {
if (ram_init_all(rsp) != 0) {
--
2.20.1
- [RFC PATCH 07/26] cpu: Add boolean aux field to CPUState, (continued)
- [RFC PATCH 07/26] cpu: Add boolean aux field to CPUState, Dov Murik, 2021/03/02
- [RFC PATCH 23/26] target/i386: Re-sync kvm-clock after confidential guest migration, Dov Murik, 2021/03/02
- [RFC PATCH 03/26] machine: Add auxcpus=N suboption to -smp, Dov Murik, 2021/03/02
- [RFC PATCH 09/26] softmmu: Don't sync aux vcpus in pre_loadvm, Dov Murik, 2021/03/02
- [RFC PATCH 19/26] migration: Don't sync vcpus when migrating confidential guests, Dov Murik, 2021/03/02
- [RFC PATCH 08/26] hw/i386: Set CPUState.aux=true for auxiliary vcpus, Dov Murik, 2021/03/02
- [RFC PATCH 14/26] migration: Introduce gpa_inside_migration_helper_shared_area, Dov Murik, 2021/03/02
- [RFC PATCH 18/26] migration: Stop non-aux vcpus before copying the last pages, Dov Murik, 2021/03/02
- [RFC PATCH 25/26] target/i386: SEV: Allow migration unless there are no aux vcpus, Dov Murik, 2021/03/02
- [RFC PATCH 24/26] migration: Add start-migrate-incoming QMP command, Dov Murik, 2021/03/02
- [RFC PATCH 15/26] migration: Save confidential guest RAM using migration helper,
Dov Murik <=
- [RFC PATCH 26/26] docs: Add confidential guest live migration documentation, Dov Murik, 2021/03/02
- [RFC PATCH 20/26] migration: When starting target, don't sync auxiliary vcpus, Dov Murik, 2021/03/02
- [RFC PATCH 05/26] hw/i386: Mark auxiliary vcpus in possible_cpus, Dov Murik, 2021/03/02
- [RFC PATCH 10/26] softmmu: Add cpu_synchronize_without_aux_post_init, Dov Murik, 2021/03/02
- [RFC PATCH 17/26] migration: Stop VM after loading confidential RAM, Dov Murik, 2021/03/02
- [RFC PATCH 22/26] hw/isa/lpc_ich9: Allow updating an already-running VM, Dov Murik, 2021/03/02
- [RFC PATCH 21/26] migration: Call migration handler cleanup routines, Dov Murik, 2021/03/02
- Re: [RFC PATCH 00/26] Confidential guest live migration, no-reply, 2021/03/02
- Re: [RFC PATCH 00/26] Confidential guest live migration, Paolo Bonzini, 2021/03/04