qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 00/26] Confidential guest live migration
@ 2021-03-02 20:47 Dov Murik
  2021-03-02 20:47 ` [RFC PATCH 01/26] linux-headers: Add definitions of KVM page encryption bitmap ioctls Dov Murik
                   ` (27 more replies)
  0 siblings, 28 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, James Bottomley,
	Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik, Hubertus Franke,
	Tobin Feldman-Fitzthum

This is an RFC series for fast migration of confidential guests using an
in-guest migration helper that lives in OVMF.  QEMU VM live migration
needs to read source VM's RAM and write it in the target VM; this
mechanism doesn't work when the guest memory is encrypted or QEMU is
prevented from reading it in another way.  In order to support live
migration in such scenarios, we introduce an in-guest migration helper
which can securely extract RAM content from the guest in order to send
it to the target.  The migration helper is implemented as part of the
VM's firmware in OVMF.

We've implemented and tested this on AMD SEV, but expect most of the
processes can be used with other technologies that prevent direct access
of hypervisor to the guest's memory.  Specifically, we don't use SEV's
PSP migration commands (SEV_SEND_START, SEV_RECEIVE_START, etc) at all.

Corresponding RFC patches for OVMF have been posted by my colleague
Tobin Feldman-Fitzthum on edk2-devel.  Those include the crux of the
migration helper: a mailbox protocol over a shared memory page which
allows communication between QEMU and the migration helper.  In the
source VM this is used to read a page and encrypt it for transport; in
the target it is used to decrypt the incoming page and storing the
content in the correct address in the guest memory.  All encryption and
decryption operations occur inside the trusted context in the VM, and
therefore the VM's memory plaintext content is never accessible to the
hosts participating in the migration.

In order to allow OVMF to run the migration helper in parallel to the
guest OS, we introduce the notion of auxiliary vcpus, which are usable
for OVMF but are hidden from the guest OS.  These might have other
future uses for in-guest operations/agents.

In the target VM we need the migration handler running to receive
incoming RAM pages; to achieve that, we boot the VM into OVMF with a
special fw_cfg value that causes OVMF to not boot the guest OS; we then
allow QEMU to receive an incoming migration by issuing a new
start-migrate-incoming QMP command.

The confidential RAM migration requires checking whether a given guest
RAM page is encrypted or not.  This is currently achieved using AMD's
patches which track the encryption status of guest pages in KVM, using
hypercalls from OVMF and guest Linux to report changes of such status.
The QEMU side of these patches is included as the first two patches in
this series.  The concrete implementation of this page encryption tracking
is currently in flux in the KVM mailing list, but the underlying
implementation doesn't affect our confidential RAM migration as long as
it can check whether a given guest address is encrypted.

List of patches in this series:

1-2: reposting AMD encrypted page bitmap support.
3-11: introduce the notion of auxiliary vcpus.
12-21: introduce the migration specifics.
22-23: fix devices issues when loading state into a live VM
24: introduce the start-migrate-incoming QMP command to switch the
target into accepting the incoming migration.
25: remove SEV migration blocker
26: add documentation


Brijesh Singh (1):
  kvm: add support to sync the page encryption state bitmap

Dov Murik (21):
  linux-headers: Add definitions of KVM page encryption bitmap ioctls
  machine: Add auxcpus=N suboption to -smp
  hw/boards: Add aux flag to CPUArchId
  hw/i386: Mark auxiliary vcpus in possible_cpus
  cpu: Add boolean aux field to CPUState
  hw/i386: Set CPUState.aux=true for auxiliary vcpus
  softmmu: Don't sync aux vcpus in pre_loadvm
  softmmu: Add cpu_synchronize_without_aux_post_init
  migration: Add helpers to save confidential RAM
  migration: Add helpers to load confidential RAM
  migration: Introduce gpa_inside_migration_helper_shared_area
  migration: Save confidential guest RAM using migration helper
  migration: Load confidential guest RAM using migration helper
  migration: Stop VM after loading confidential RAM
  migration: Don't sync vcpus when migrating confidential guests
  migration: When starting target, don't sync auxiliary vcpus
  hw/isa/lpc_ich9: Allow updating an already-running VM
  target/i386: Re-sync kvm-clock after confidential guest migration
  migration: Add start-migrate-incoming QMP command
  target/i386: SEV: Allow migration unless there are no aux vcpus
  docs: Add confidential guest live migration documentation

Tobin Feldman-Fitzthum (4):
  hw/acpi: Don't include auxiliary vcpus in ACPI tables
  softmmu: Add pause_all_vcpus_except_aux
  migration: Stop non-aux vcpus before copying the last pages
  migration: Call migration handler cleanup routines

 docs/confidential-guest-live-migration.rst | 142 ++++++++++++
 docs/confidential-guest-support.txt        |   5 +
 docs/index.rst                             |   1 +
 qapi/migration.json                        |  26 +++
 include/exec/ram_addr.h                    | 197 ++++++++++++++++
 include/exec/ramblock.h                    |   3 +
 include/exec/ramlist.h                     |   3 +-
 include/hw/boards.h                        |   3 +
 include/hw/core/cpu.h                      |   2 +
 include/hw/i386/x86.h                      |   2 +-
 include/sysemu/cpus.h                      |   2 +
 linux-headers/linux/kvm.h                  |  13 ++
 migration/confidential-ram.h               |  23 ++
 accel/kvm/kvm-all.c                        |  43 ++++
 hw/acpi/cpu.c                              |  10 +
 hw/core/cpu.c                              |   1 +
 hw/core/machine.c                          |   7 +
 hw/i386/acpi-build.c                       |   5 +
 hw/i386/acpi-common.c                      |   5 +
 hw/i386/pc.c                               |   7 +
 hw/i386/x86.c                              |  10 +-
 hw/isa/lpc_ich9.c                          |   3 +-
 migration/confidential-ram.c               | 258 +++++++++++++++++++++
 migration/migration.c                      |  18 +-
 migration/ram.c                            | 135 ++++++++++-
 migration/savevm.c                         |  13 +-
 softmmu/cpus.c                             |  68 +++++-
 softmmu/runstate.c                         |   1 +
 softmmu/vl.c                               |   3 +
 target/i386/machine.c                      |   9 +
 target/i386/sev.c                          |  25 +-
 migration/meson.build                      |   6 +-
 migration/trace-events                     |   4 +
 33 files changed, 1027 insertions(+), 26 deletions(-)
 create mode 100644 docs/confidential-guest-live-migration.rst
 create mode 100644 migration/confidential-ram.h
 create mode 100644 migration/confidential-ram.c


base-commit: 00d8ba9e0d62ea1c7459c25aeabf9c8bb7659462
-- 
2.20.1



^ permalink raw reply	[flat|nested] 30+ messages in thread

* [RFC PATCH 01/26] linux-headers: Add definitions of KVM page encryption bitmap ioctls
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
@ 2021-03-02 20:47 ` Dov Murik
  2021-03-02 20:47 ` [RFC PATCH 02/26] kvm: add support to sync the page encryption state bitmap Dov Murik
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Cornelia Huck, Brijesh Singh,
	open list:Overall KVM CPUs, Michael S. Tsirkin, James Bottomley,
	Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik, Hubertus Franke,
	Tobin Feldman-Fitzthum, Paolo Bonzini

Add support for two ioctls KVM_GET_PAGE_ENC_BITMAP and
KVM_SET_PAGE_ENC_BITMAP used to record the encryption state of each
guest page.

This patch will be replaced by a new implementation based on shared
regions list, or by user-space handling of the regions list.  However,
these changes do not affect the use of the page encryption indication in
confidential guest migration flow.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 linux-headers/linux/kvm.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 020b62a619..836c3776c0 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -532,6 +532,16 @@ struct kvm_dirty_log {
 	};
 };
 
+/* for KVM_GET_PAGE_ENC_BITMAP */
+struct kvm_page_enc_bitmap {
+	__u64 start_gfn;
+	__u64 num_pages;
+	union {
+		void *enc_bitmap; /* one bit per page */
+		__u64 padding2;
+	};
+};
+
 /* for KVM_CLEAR_DIRTY_LOG */
 struct kvm_clear_dirty_log {
 	__u32 slot;
@@ -1557,6 +1567,9 @@ struct kvm_pv_cmd {
 /* Available with KVM_CAP_S390_PROTECTED */
 #define KVM_S390_PV_COMMAND		_IOWR(KVMIO, 0xc5, struct kvm_pv_cmd)
 
+#define KVM_GET_PAGE_ENC_BITMAP	_IOW(KVMIO, 0xc6, struct kvm_page_enc_bitmap)
+#define KVM_SET_PAGE_ENC_BITMAP	_IOW(KVMIO, 0xc7, struct kvm_page_enc_bitmap)
+
 /* Available with KVM_CAP_X86_MSR_FILTER */
 #define KVM_X86_SET_MSR_FILTER	_IOW(KVMIO,  0xc6, struct kvm_msr_filter)
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 02/26] kvm: add support to sync the page encryption state bitmap
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
  2021-03-02 20:47 ` [RFC PATCH 01/26] linux-headers: Add definitions of KVM page encryption bitmap ioctls Dov Murik
@ 2021-03-02 20:47 ` Dov Murik
  2021-03-02 20:47 ` [RFC PATCH 03/26] machine: Add auxcpus=N suboption to -smp Dov Murik
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh,
	open list:Overall KVM CPUs, Juan Quintela, James Bottomley,
	Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Dr. David Alan Gilbert, Hubertus Franke, Tobin Feldman-Fitzthum,
	Paolo Bonzini

From: Brijesh Singh <brijesh.singh@amd.com>

The SEV VMs have concept of private and shared memory. The private memory
is encrypted with guest-specific key, while shared memory may be encrypted
with hyperivosr key. The KVM_GET_PAGE_ENC_BITMAP can be used to get a
bitmap indicating whether the guest page is private or shared. A private
page must be transmitted using the SEV migration commands.

Add a cpu_physical_memory_sync_encrypted_bitmap() which can be used to get
the page encryption bitmap for a given memory region.

The page encryption bitmap is not exactly same as dirty bitmap. The page
encryption bitmap is a purely a matter of state about the page is encrypted
or not. To avoid some confusion we clone few functions for clarity.

[Dov changes: replace memcrypt-related checkers with confidential guest
support in migration/ram.c and accel/kvm; rename atomic_* to qatomic_*
in include/exec/ram_addr.h]

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 include/exec/ram_addr.h | 197 ++++++++++++++++++++++++++++++++++++++++
 include/exec/ramblock.h |   3 +
 include/exec/ramlist.h  |   3 +-
 accel/kvm/kvm-all.c     |  43 +++++++++
 migration/ram.c         |  17 ++++
 5 files changed, 262 insertions(+), 1 deletion(-)

diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 3cb9791df3..aac5b5e393 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -284,6 +284,60 @@ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
     set_bit_atomic(offset, blocks->blocks[idx]);
 }
 
+static inline void cpu_physical_memory_set_encrypted_range(ram_addr_t start,
+                                                           ram_addr_t length,
+                                                           unsigned long val)
+{
+    unsigned long page;
+    unsigned long * const *src;
+
+    page = start >> TARGET_PAGE_BITS;
+
+    rcu_read_lock();
+
+    src = qatomic_rcu_read(
+            &ram_list.dirty_memory[DIRTY_MEMORY_ENCRYPTED])->blocks;
+
+    if (length) {
+        unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE;
+        unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE;
+        int m = (start) & (BITS_PER_LONG - 1);
+        int n = MIN(length, BITS_PER_LONG - m);
+        unsigned long old_val = qatomic_read(&src[idx][BIT_WORD(offset)]);
+        unsigned long mask;
+
+        mask = (~0UL >> n);
+        mask = mask << m;
+
+        old_val &= ~mask;
+        val &= mask;
+
+        qatomic_xchg(&src[idx][BIT_WORD(offset)], old_val | val);
+        page += n;
+        length -= n;
+    }
+
+    /* remaining bits */
+    if (length) {
+        unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE;
+        unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE;
+        int m = (start) & (BITS_PER_LONG - 1);
+        int n = MIN(length, BITS_PER_LONG - m);
+        unsigned long old_val = qatomic_read(&src[idx][BIT_WORD(offset)]);
+        unsigned long mask;
+
+        mask = (~0UL >> n);
+        mask = mask << m;
+
+        old_val &= ~mask;
+        val &= mask;
+
+        qatomic_xchg(&src[idx][BIT_WORD(offset)], old_val | val);
+    }
+
+    rcu_read_unlock();
+}
+
 static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
                                                        ram_addr_t length,
                                                        uint8_t mask)
@@ -335,6 +389,62 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
 }
 
 #if !defined(_WIN32)
+static inline void cpu_physical_memory_set_encrypted_lebitmap(
+                                                        unsigned long *bitmap,
+                                                        ram_addr_t start,
+                                                        ram_addr_t pages)
+{
+    unsigned long i;
+    unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE;
+    unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
+
+    /* start address is aligned at the start of a word? */
+    if ((((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) &&
+        (hpratio == 1)) {
+        unsigned long **blocks[DIRTY_MEMORY_NUM];
+        unsigned long idx;
+        unsigned long offset;
+        long k;
+        long nr = BITS_TO_LONGS(pages);
+
+        idx = (start >> TARGET_PAGE_BITS) / DIRTY_MEMORY_BLOCK_SIZE;
+        offset = BIT_WORD((start >> TARGET_PAGE_BITS) %
+                          DIRTY_MEMORY_BLOCK_SIZE);
+
+        rcu_read_lock();
+
+        for (i = 0; i < DIRTY_MEMORY_NUM; i++) {
+            blocks[i] = qatomic_rcu_read(&ram_list.dirty_memory[i])->blocks;
+        }
+
+        for (k = 0; k < nr; k++) {
+            if (bitmap[k]) {
+                unsigned long temp = leul_to_cpu(bitmap[k]);
+
+                qatomic_xchg(&blocks[DIRTY_MEMORY_ENCRYPTED][idx][offset], temp);
+            }
+
+            if (++offset >= BITS_TO_LONGS(DIRTY_MEMORY_BLOCK_SIZE)) {
+                offset = 0;
+                idx++;
+            }
+        }
+
+        rcu_read_unlock();
+    } else {
+        i = 0;
+        while (pages > 0) {
+            unsigned long len = MIN(pages, BITS_PER_LONG);
+
+            cpu_physical_memory_set_encrypted_range(start, len,
+                            leul_to_cpu(bitmap[i]));
+            start += len;
+            i++;
+            pages -= len;
+        }
+    }
+}
+
 static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
                                                           ram_addr_t start,
                                                           ram_addr_t pages)
@@ -438,6 +548,8 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
     cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_MIGRATION);
     cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_VGA);
     cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_CODE);
+    cpu_physical_memory_test_and_clear_dirty(start, length,
+                                             DIRTY_MEMORY_ENCRYPTED);
 }
 
 
@@ -513,5 +625,90 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb,
 
     return num_dirty;
 }
+
+static inline bool cpu_physical_memory_test_encrypted(ram_addr_t start,
+                                                      ram_addr_t length)
+{
+    unsigned long end, page;
+    bool enc = false;
+    unsigned long * const *src;
+
+    if (length == 0) {
+        return enc;
+    }
+
+    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
+    page = start >> TARGET_PAGE_BITS;
+
+    rcu_read_lock();
+
+    src = qatomic_rcu_read(
+            &ram_list.dirty_memory[DIRTY_MEMORY_ENCRYPTED])->blocks;
+
+    while (page < end) {
+        unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE;
+        unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE;
+        unsigned long num = MIN(end - page, DIRTY_MEMORY_BLOCK_SIZE - offset);
+
+        enc |= qatomic_read(&src[idx][BIT_WORD(offset)]);
+        page += num;
+    }
+
+    rcu_read_unlock();
+
+    return enc;
+}
+
+static inline
+void cpu_physical_memory_sync_encrypted_bitmap(RAMBlock *rb,
+                                               ram_addr_t start,
+                                               ram_addr_t length)
+{
+    ram_addr_t addr;
+    unsigned long word = BIT_WORD((start + rb->offset) >> TARGET_PAGE_BITS);
+    unsigned long *dest = rb->encbmap;
+
+    /* start address and length is aligned at the start of a word? */
+    if (((word * BITS_PER_LONG) << TARGET_PAGE_BITS) ==
+         (start + rb->offset) &&
+        !(length & ((BITS_PER_LONG << TARGET_PAGE_BITS) - 1))) {
+        int k;
+        int nr = BITS_TO_LONGS(length >> TARGET_PAGE_BITS);
+        unsigned long * const *src;
+        unsigned long idx = (word * BITS_PER_LONG) / DIRTY_MEMORY_BLOCK_SIZE;
+        unsigned long offset = BIT_WORD((word * BITS_PER_LONG) %
+                                        DIRTY_MEMORY_BLOCK_SIZE);
+        unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
+
+        rcu_read_lock();
+
+        src = qatomic_rcu_read(
+                &ram_list.dirty_memory[DIRTY_MEMORY_ENCRYPTED])->blocks;
+
+        for (k = page; k < page + nr; k++) {
+            unsigned long bits = qatomic_read(&src[idx][offset]);
+            dest[k] = bits;
+
+            if (++offset >= BITS_TO_LONGS(DIRTY_MEMORY_BLOCK_SIZE)) {
+                offset = 0;
+                idx++;
+            }
+        }
+
+        rcu_read_unlock();
+    } else {
+        ram_addr_t offset = rb->offset;
+
+        for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
+            long k = (start + addr) >> TARGET_PAGE_BITS;
+            if (cpu_physical_memory_test_encrypted(start + addr + offset,
+                                                   TARGET_PAGE_SIZE)) {
+                set_bit(k, dest);
+            } else {
+                clear_bit(k, dest);
+            }
+        }
+    }
+}
 #endif
 #endif
diff --git a/include/exec/ramblock.h b/include/exec/ramblock.h
index 07d50864d8..bcd7720826 100644
--- a/include/exec/ramblock.h
+++ b/include/exec/ramblock.h
@@ -59,6 +59,9 @@ struct RAMBlock {
      */
     unsigned long *clear_bmap;
     uint8_t clear_bmap_shift;
+
+    /* bitmap of page encryption state for an encrypted guest */
+    unsigned long *encbmap;
 };
 #endif
 #endif
diff --git a/include/exec/ramlist.h b/include/exec/ramlist.h
index 26704aa3b0..2422e5ce86 100644
--- a/include/exec/ramlist.h
+++ b/include/exec/ramlist.h
@@ -11,7 +11,8 @@ typedef struct RAMBlockNotifier RAMBlockNotifier;
 #define DIRTY_MEMORY_VGA       0
 #define DIRTY_MEMORY_CODE      1
 #define DIRTY_MEMORY_MIGRATION 2
-#define DIRTY_MEMORY_NUM       3        /* num of dirty bits */
+#define DIRTY_MEMORY_ENCRYPTED 3
+#define DIRTY_MEMORY_NUM       4        /* num of dirty bits */
 
 /* The dirty memory bitmap is split into fixed-size blocks to allow growth
  * under RCU.  The bitmap for a block can be accessed as follows:
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 84c943fcdb..13350c1b9b 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -604,6 +604,43 @@ static void kvm_memslot_init_dirty_bitmap(KVMSlot *mem)
     mem->dirty_bmap = g_malloc0(bitmap_size);
 }
 
+/* sync page_enc bitmap */
+static int kvm_sync_page_enc_bitmap(KVMMemoryListener *kml,
+                                    MemoryRegionSection *section,
+                                    KVMSlot *mem)
+{
+    unsigned long size;
+    KVMState *s = kvm_state;
+    struct kvm_page_enc_bitmap e = {};
+    ram_addr_t pages = int128_get64(section->size) / getpagesize();
+    ram_addr_t start = section->offset_within_region +
+                       memory_region_get_ram_addr(section->mr);
+
+    size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS), 64) / 8;
+    e.enc_bitmap = g_malloc0(size);
+    e.start_gfn = mem->start_addr >> TARGET_PAGE_BITS;
+    e.num_pages = pages;
+    if (kvm_vm_ioctl(s, KVM_GET_PAGE_ENC_BITMAP, &e) == -1) {
+        DPRINTF("KVM_GET_PAGE_ENC_BITMAP ioctl failed %d\n", errno);
+        g_free(e.enc_bitmap);
+        return 1;
+    }
+
+    cpu_physical_memory_set_encrypted_lebitmap(e.enc_bitmap,
+                                               start, pages);
+
+    g_free(e.enc_bitmap);
+
+    return 0;
+}
+
+static inline bool confidential_guest(void)
+{
+    MachineState *ms = MACHINE(qdev_get_machine());
+
+    return ms->cgs;
+}
+
 /**
  * kvm_physical_sync_dirty_bitmap - Sync dirty bitmap from kernel space
  *
@@ -659,6 +696,12 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
         slot_offset += slot_size;
         start_addr += slot_size;
         size -= slot_size;
+
+        if (confidential_guest() &&
+            kvm_sync_page_enc_bitmap(kml, section, mem)) {
+            g_free(d.dirty_bitmap);
+            return -1;
+        }
     }
 out:
     return ret;
diff --git a/migration/ram.c b/migration/ram.c
index 72143da0ac..997f90cc5b 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -61,6 +61,7 @@
 #if defined(__linux__)
 #include "qemu/userfaultfd.h"
 #endif /* defined(__linux__) */
+#include "hw/boards.h"
 
 /***********************************************************/
 /* ram save/restore */
@@ -81,6 +82,13 @@
 /* 0x80 is reserved in migration.h start with 0x100 next */
 #define RAM_SAVE_FLAG_COMPRESS_PAGE    0x100
 
+static inline bool memcrypt_enabled(void)
+{
+    MachineState *ms = MACHINE(qdev_get_machine());
+
+    return ms->cgs;
+}
+
 static inline bool is_zero_range(uint8_t *p, uint64_t size)
 {
     return buffer_is_zero(p, size);
@@ -865,6 +873,9 @@ static void ramblock_sync_dirty_bitmap(RAMState *rs, RAMBlock *rb)
 
     rs->migration_dirty_pages += new_dirty_pages;
     rs->num_dirty_pages_period += new_dirty_pages;
+    if (memcrypt_enabled()) {
+        cpu_physical_memory_sync_encrypted_bitmap(rb, 0, rb->used_length);
+    }
 }
 
 /**
@@ -2174,6 +2185,8 @@ static void ram_save_cleanup(void *opaque)
         block->clear_bmap = NULL;
         g_free(block->bmap);
         block->bmap = NULL;
+        g_free(block->encbmap);
+        block->encbmap = NULL;
     }
 
     xbzrle_cleanup();
@@ -2615,6 +2628,10 @@ static void ram_list_init_bitmaps(void)
             bitmap_set(block->bmap, 0, pages);
             block->clear_bmap_shift = shift;
             block->clear_bmap = bitmap_new(clear_bmap_size(pages, shift));
+            if (memcrypt_enabled()) {
+                block->encbmap = bitmap_new(pages);
+                bitmap_set(block->encbmap, 0, pages);
+            }
         }
     }
 }
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 03/26] machine: Add auxcpus=N suboption to -smp
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
  2021-03-02 20:47 ` [RFC PATCH 01/26] linux-headers: Add definitions of KVM page encryption bitmap ioctls Dov Murik
  2021-03-02 20:47 ` [RFC PATCH 02/26] kvm: add support to sync the page encryption state bitmap Dov Murik
@ 2021-03-02 20:47 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 04/26] hw/boards: Add aux flag to CPUArchId Dov Murik
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	Michael S. Tsirkin, Richard Henderson, James Bottomley,
	Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik, Hubertus Franke,
	Tobin Feldman-Fitzthum, Paolo Bonzini

Add a notion of auxiliary vcpus to CpuTopology, which will allow to
designate a few vcpus (normally 1) to helper tasks not related to main
guest VM execution.

Example usage for starting a 4-vcpu guest, of which 1 vcpu is marked as
auxiliary:

    qemu-system-x86_64 -smp 4,auxcpus=1 ...

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 include/hw/boards.h | 1 +
 hw/core/machine.c   | 7 +++++++
 hw/i386/pc.c        | 7 +++++++
 softmmu/vl.c        | 3 +++
 4 files changed, 18 insertions(+)

diff --git a/include/hw/boards.h b/include/hw/boards.h
index a46dfe5d1a..7ee5c73510 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -246,6 +246,7 @@ typedef struct CpuTopology {
     unsigned int threads;
     unsigned int sockets;
     unsigned int max_cpus;
+    unsigned int aux_cpus;
 } CpuTopology;
 
 /**
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 970046f438..08ea2cedea 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -722,6 +722,7 @@ static void smp_parse(MachineState *ms, QemuOpts *opts)
         unsigned sockets = qemu_opt_get_number(opts, "sockets", 0);
         unsigned cores   = qemu_opt_get_number(opts, "cores", 0);
         unsigned threads = qemu_opt_get_number(opts, "threads", 0);
+        unsigned aux_cpus = qemu_opt_get_number(opts, "auxcpus", 0);
 
         /* compute missing values, prefer sockets over cores over threads */
         if (cpus == 0 || sockets == 0) {
@@ -767,10 +768,16 @@ static void smp_parse(MachineState *ms, QemuOpts *opts)
             exit(1);
         }
 
+        if (aux_cpus >= ms->smp.max_cpus) {
+            error_report("auxcpus must be lower than max_cpus");
+            exit(1);
+        }
+
         ms->smp.cpus = cpus;
         ms->smp.cores = cores;
         ms->smp.threads = threads;
         ms->smp.sockets = sockets;
+        ms->smp.aux_cpus = aux_cpus;
     }
 
     if (ms->smp.cpus > 1) {
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 8aa85dec54..95d3769842 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -718,6 +718,7 @@ void pc_smp_parse(MachineState *ms, QemuOpts *opts)
         unsigned dies = qemu_opt_get_number(opts, "dies", 1);
         unsigned cores   = qemu_opt_get_number(opts, "cores", 0);
         unsigned threads = qemu_opt_get_number(opts, "threads", 0);
+        unsigned aux_cpus = qemu_opt_get_number(opts, "auxcpus", 0);
 
         /* compute missing values, prefer sockets over cores over threads */
         if (cpus == 0 || sockets == 0) {
@@ -763,10 +764,16 @@ void pc_smp_parse(MachineState *ms, QemuOpts *opts)
             exit(1);
         }
 
+        if (aux_cpus >= ms->smp.max_cpus) {
+            error_report("auxcpus must be lower than max_cpus");
+            exit(1);
+        }
+
         ms->smp.cpus = cpus;
         ms->smp.cores = cores;
         ms->smp.threads = threads;
         ms->smp.sockets = sockets;
+        ms->smp.aux_cpus = aux_cpus;
         x86ms->smp_dies = dies;
     }
 
diff --git a/softmmu/vl.c b/softmmu/vl.c
index b219ce1f35..96f0ff8111 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -720,6 +720,9 @@ static QemuOptsList qemu_smp_opts = {
         }, {
             .name = "maxcpus",
             .type = QEMU_OPT_NUMBER,
+        }, {
+            .name = "auxcpus",
+            .type = QEMU_OPT_NUMBER,
         },
         { /*End of list */ }
     },
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 04/26] hw/boards: Add aux flag to CPUArchId
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (2 preceding siblings ...)
  2021-03-02 20:47 ` [RFC PATCH 03/26] machine: Add auxcpus=N suboption to -smp Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 05/26] hw/i386: Mark auxiliary vcpus in possible_cpus Dov Murik
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Hubertus Franke, Tobin Feldman-Fitzthum

The aux flag indicates whether a vcpu is auxiliary.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 include/hw/boards.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/hw/boards.h b/include/hw/boards.h
index 7ee5c73510..4458b359c3 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -51,6 +51,7 @@ MemoryRegion *machine_consume_memdev(MachineState *machine,
  * @type - QOM class name of possible @cpu object
  * @props - CPU object properties, initialized by board
  * #vcpus_count - number of threads provided by @cpu object
+ * @aux - is this CPU auxiliary
  */
 typedef struct CPUArchId {
     uint64_t arch_id;
@@ -58,6 +59,7 @@ typedef struct CPUArchId {
     CpuInstanceProperties props;
     Object *cpu;
     const char *type;
+    bool aux;
 } CPUArchId;
 
 /**
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 05/26] hw/i386: Mark auxiliary vcpus in possible_cpus
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (3 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 04/26] hw/boards: Add aux flag to CPUArchId Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 06/26] hw/acpi: Don't include auxiliary vcpus in ACPI tables Dov Murik
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	Michael S. Tsirkin, Richard Henderson, James Bottomley,
	Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik, Hubertus Franke,
	Tobin Feldman-Fitzthum, Paolo Bonzini

Mark the last aux_cpus vcpus in the machine state's possible_cpus as
auxiliary.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 hw/i386/x86.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 6329f90ef9..be23fad650 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -448,6 +448,7 @@ const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
 {
     X86MachineState *x86ms = X86_MACHINE(ms);
     unsigned int max_cpus = ms->smp.max_cpus;
+    unsigned int aux_cpus_start_at = max_cpus - ms->smp.aux_cpus;
     X86CPUTopoInfo topo_info;
     int i;
 
@@ -475,6 +476,7 @@ const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
             x86_cpu_apic_id_from_index(x86ms, i);
         x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id,
                                  &topo_info, &topo_ids);
+        ms->possible_cpus->cpus[i].aux = i >= aux_cpus_start_at;
         ms->possible_cpus->cpus[i].props.has_socket_id = true;
         ms->possible_cpus->cpus[i].props.socket_id = topo_ids.pkg_id;
         if (x86ms->smp_dies > 1) {
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 06/26] hw/acpi: Don't include auxiliary vcpus in ACPI tables
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (4 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 05/26] hw/i386: Mark auxiliary vcpus in possible_cpus Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 07/26] cpu: Add boolean aux field to CPUState Dov Murik
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	Michael S. Tsirkin, Richard Henderson, James Bottomley,
	Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik, Hubertus Franke,
	Tobin Feldman-Fitzthum, Paolo Bonzini, Igor Mammedov

From: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>

By excluding auxiliary vcpus from the ACPI tables, we hide them from the
guest OS.  This in turn allows OVMF to execute code on the auxiliary
vcpus in parallel to the OS.

Signed-off-by: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>
Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 hw/acpi/cpu.c         | 10 ++++++++++
 hw/i386/acpi-build.c  |  5 +++++
 hw/i386/acpi-common.c |  5 +++++
 3 files changed, 20 insertions(+)

diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index e2317be546..d3f0a48da9 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -436,6 +436,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
 
         method = aml_method(CPU_NOTIFY_METHOD, 2, AML_NOTSERIALIZED);
         for (i = 0; i < arch_ids->len; i++) {
+            if (arch_ids->cpus[i].aux) {
+                /* don't build objects for auxiliary CPUs */
+                continue;
+            }
+
             Aml *cpu = aml_name(CPU_NAME_FMT, i);
             Aml *uid = aml_arg(0);
             Aml *event = aml_arg(1);
@@ -651,6 +656,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
 
         /* build Processor object for each processor */
         for (i = 0; i < arch_ids->len; i++) {
+            if (arch_ids->cpus[i].aux) {
+                /* don't build objects for auxiliary CPUs */
+                continue;
+            }
+
             Aml *dev;
             Aml *uid = aml_int(i);
             GArray *madt_buf = g_array_new(0, 1, 1);
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index b9190b924a..8cc7e2af3a 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1708,6 +1708,11 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
     srat->reserved1 = cpu_to_le32(1);
 
     for (i = 0; i < apic_ids->len; i++) {
+        if (apic_ids->cpus[i].aux) {
+            /* don't build objects for auxiliary CPUs */
+            continue;
+        }
+
         int node_id = apic_ids->cpus[i].props.node_id;
         uint32_t apic_id = apic_ids->cpus[i].arch_id;
 
diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 1f5947fcf9..7c73f3900b 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -91,6 +91,11 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
     madt->flags = cpu_to_le32(1);
 
     for (i = 0; i < apic_ids->len; i++) {
+        if (apic_ids->cpus[i].aux) {
+            /* don't build objects for auxiliary CPUs */
+            continue;
+        }
+
         adevc->madt_cpu(adev, i, apic_ids, table_data);
         if (apic_ids->cpus[i].arch_id > 254) {
             x2apic_mode = true;
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 07/26] cpu: Add boolean aux field to CPUState
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (5 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 06/26] hw/acpi: Don't include auxiliary vcpus in ACPI tables Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 08/26] hw/i386: Set CPUState.aux=true for auxiliary vcpus Dov Murik
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Hubertus Franke, Tobin Feldman-Fitzthum

The aux field indicates auxiliary CPUs.  This will allow QEMU to act
differently on auxilirary CPUs, for example pausing the VM while keeping
the auxiliary CPUs running.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 include/hw/core/cpu.h | 2 ++
 hw/core/cpu.c         | 1 +
 2 files changed, 3 insertions(+)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index c005d3dc2d..cdbb6462a3 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -430,6 +430,8 @@ struct CPUState {
 
     int hvf_fd;
 
+    bool aux;
+
     /* track IOMMUs whose translations we've cached in the TCG TLB */
     GArray *iommu_notifiers;
 };
diff --git a/hw/core/cpu.c b/hw/core/cpu.c
index 00330ba07d..2100cb7f1a 100644
--- a/hw/core/cpu.c
+++ b/hw/core/cpu.c
@@ -387,6 +387,7 @@ static Property cpu_common_props[] = {
                      MemoryRegion *),
 #endif
     DEFINE_PROP_BOOL("start-powered-off", CPUState, start_powered_off, false),
+    DEFINE_PROP_BOOL("aux", CPUState, aux, false),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 08/26] hw/i386: Set CPUState.aux=true for auxiliary vcpus
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (6 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 07/26] cpu: Add boolean aux field to CPUState Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 09/26] softmmu: Don't sync aux vcpus in pre_loadvm Dov Murik
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	Michael S. Tsirkin, Richard Henderson, James Bottomley,
	Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik, Hubertus Franke,
	Tobin Feldman-Fitzthum, Paolo Bonzini

On x86 machines, when initializing the CPUState structs, set the aux
flag to true for auxiliary vcpus.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 include/hw/i386/x86.h | 2 +-
 hw/i386/x86.c         | 8 ++++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index 56080bd1fb..f9ec6af9b7 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -85,7 +85,7 @@ void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms);
 uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
                                     unsigned int cpu_index);
 
-void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp);
+void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, bool aux, Error **errp);
 void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
 CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms,
                                              unsigned cpu_index);
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index be23fad650..bc17b53180 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -101,13 +101,16 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
 }
 
 
-void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, Error **errp)
+void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, bool aux, Error **errp)
 {
     Object *cpu = object_new(MACHINE(x86ms)->cpu_type);
 
     if (!object_property_set_uint(cpu, "apic-id", apic_id, errp)) {
         goto out;
     }
+    if (!object_property_set_bool(cpu, "aux", aux, errp)) {
+        goto out;
+    }
     qdev_realize(DEVICE(cpu), NULL, errp);
 
 out:
@@ -135,7 +138,8 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version)
                                                       ms->smp.max_cpus - 1) + 1;
     possible_cpus = mc->possible_cpu_arch_ids(ms);
     for (i = 0; i < ms->smp.cpus; i++) {
-        x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, &error_fatal);
+        x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id,
+                    possible_cpus->cpus[i].aux, &error_fatal);
     }
 }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 09/26] softmmu: Don't sync aux vcpus in pre_loadvm
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (7 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 08/26] hw/i386: Set CPUState.aux=true for auxiliary vcpus Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 10/26] softmmu: Add cpu_synchronize_without_aux_post_init Dov Murik
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Richard Henderson,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Hubertus Franke, Tobin Feldman-Fitzthum, Paolo Bonzini

When preparing to load state into a migration target VM, don't sync the
auxiliary vcpus to allow the migration helper to keep running there (it
is used during the migration).

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 softmmu/cpus.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/softmmu/cpus.c b/softmmu/cpus.c
index a7ee431187..878cf2a421 100644
--- a/softmmu/cpus.c
+++ b/softmmu/cpus.c
@@ -162,7 +162,9 @@ void cpu_synchronize_all_pre_loadvm(void)
     CPUState *cpu;
 
     CPU_FOREACH(cpu) {
-        cpu_synchronize_pre_loadvm(cpu);
+        if (!cpu->aux) {
+            cpu_synchronize_pre_loadvm(cpu);
+        }
     }
 }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 10/26] softmmu: Add cpu_synchronize_without_aux_post_init
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (8 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 09/26] softmmu: Don't sync aux vcpus in pre_loadvm Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 11/26] softmmu: Add pause_all_vcpus_except_aux Dov Murik
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Richard Henderson,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Hubertus Franke, Tobin Feldman-Fitzthum, Paolo Bonzini

This will be used during migration on the target.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 include/sysemu/cpus.h |  1 +
 softmmu/cpus.c        | 11 +++++++++++
 2 files changed, 12 insertions(+)

diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
index 868f1192de..dc24e38254 100644
--- a/include/sysemu/cpus.h
+++ b/include/sysemu/cpus.h
@@ -46,6 +46,7 @@ bool cpus_are_resettable(void);
 void cpu_synchronize_all_states(void);
 void cpu_synchronize_all_post_reset(void);
 void cpu_synchronize_all_post_init(void);
+void cpu_synchronize_without_aux_post_init(void);
 void cpu_synchronize_all_pre_loadvm(void);
 
 #ifndef CONFIG_USER_ONLY
diff --git a/softmmu/cpus.c b/softmmu/cpus.c
index 878cf2a421..68fa4639a7 100644
--- a/softmmu/cpus.c
+++ b/softmmu/cpus.c
@@ -157,6 +157,17 @@ void cpu_synchronize_all_post_init(void)
     }
 }
 
+void cpu_synchronize_without_aux_post_init(void)
+{
+    CPUState *cpu;
+
+    CPU_FOREACH(cpu) {
+        if (!cpu->aux) {
+            cpu_synchronize_post_init(cpu);
+        }
+    }
+}
+
 void cpu_synchronize_all_pre_loadvm(void)
 {
     CPUState *cpu;
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 11/26] softmmu: Add pause_all_vcpus_except_aux
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (9 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 10/26] softmmu: Add cpu_synchronize_without_aux_post_init Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 12/26] migration: Add helpers to save confidential RAM Dov Murik
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Richard Henderson,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Hubertus Franke, Tobin Feldman-Fitzthum, Paolo Bonzini

From: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>

Introduce a function to pause all CPUs except the auxiliary CPUs.  This
will be used during migration when a migration handler is running on the
auxiliary CPU.

Co-Author: Dov Murik <dovmurik@linux.vnet.ibm.com>
Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
Signed-off-by: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>
---
 include/sysemu/cpus.h |  1 +
 softmmu/cpus.c        | 53 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
index dc24e38254..e668570053 100644
--- a/include/sysemu/cpus.h
+++ b/include/sysemu/cpus.h
@@ -34,6 +34,7 @@ bool qemu_in_vcpu_thread(void);
 void qemu_init_cpu_loop(void);
 void resume_all_vcpus(void);
 void pause_all_vcpus(void);
+void pause_all_vcpus_except_aux(void);
 void cpu_stop_current(void);
 
 extern int icount_align_option;
diff --git a/softmmu/cpus.c b/softmmu/cpus.c
index 68fa4639a7..3028b5d0d4 100644
--- a/softmmu/cpus.c
+++ b/softmmu/cpus.c
@@ -550,6 +550,19 @@ static bool all_vcpus_paused(void)
     return true;
 }
 
+static bool all_vcpus_except_aux_paused(void)
+{
+    CPUState *cpu;
+
+    CPU_FOREACH(cpu) {
+        if (!cpu->aux && !cpu->stopped) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 void pause_all_vcpus(void)
 {
     CPUState *cpu;
@@ -564,15 +577,51 @@ void pause_all_vcpus(void)
         }
     }
 
+    /*
+     * Drop the replay_lock so any vCPU threads woken up can finish their
+     * replay tasks
+     */
+    replay_mutex_unlock();
+
+    while (!all_vcpus_paused()) {
+        qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
+        CPU_FOREACH(cpu) {
+            qemu_cpu_kick(cpu);
+        }
+    }
+
+    qemu_mutex_unlock_iothread();
+    replay_mutex_lock();
+    qemu_mutex_lock_iothread();
+}
+
+void pause_all_vcpus_except_aux(void)
+{
+    CPUState *cpu;
+
+    qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false);
+    CPU_FOREACH(cpu) {
+        if (!cpu->aux) {
+            if (qemu_cpu_is_self(cpu)) {
+                qemu_cpu_stop(cpu, true);
+            } else {
+                cpu->stop = true;
+                qemu_cpu_kick(cpu);
+            }
+        }
+    }
+
     /* We need to drop the replay_lock so any vCPU threads woken up
      * can finish their replay tasks
      */
     replay_mutex_unlock();
 
-    while (!all_vcpus_paused()) {
+    while (!all_vcpus_except_aux_paused()) {
         qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex);
         CPU_FOREACH(cpu) {
-            qemu_cpu_kick(cpu);
+            if (!cpu->aux) {
+                qemu_cpu_kick(cpu);
+            }
         }
     }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 12/26] migration: Add helpers to save confidential RAM
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (10 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 11/26] softmmu: Add pause_all_vcpus_except_aux Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 13/26] migration: Add helpers to load " Dov Murik
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Juan Quintela,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Dr. David Alan Gilbert, Hubertus Franke, Tobin Feldman-Fitzthum

QEMU cannot read the memory of memory-encrypted guests, which is
required for sending RAM to the migration target.  Instead, QEMU asks a
migration helper running on an auxiliary vcpu in the guest to extract
pages from memory; these pages are encrypted with a transfer key that is
known to the source and target guests, but not to both QEMUs.

The interaction with the guest migration helper is performed using two
shared (unencrypted) pages which both QEMU and guest can read from and
write to.  The details of the mailbox protocol are described in
migration/confidential-ram.c.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 migration/confidential-ram.h |  17 ++++
 migration/confidential-ram.c | 184 +++++++++++++++++++++++++++++++++++
 migration/meson.build        |   6 +-
 migration/trace-events       |   3 +
 4 files changed, 209 insertions(+), 1 deletion(-)
 create mode 100644 migration/confidential-ram.h
 create mode 100644 migration/confidential-ram.c

diff --git a/migration/confidential-ram.h b/migration/confidential-ram.h
new file mode 100644
index 0000000000..0d49718d31
--- /dev/null
+++ b/migration/confidential-ram.h
@@ -0,0 +1,17 @@
+/*
+ * QEMU migration for confidential guest's RAM
+ */
+
+#ifndef QEMU_CONFIDENTIAL_RAM_H
+#define QEMU_CONFIDENTIAL_RAM_H
+
+#include "exec/cpu-common.h"
+#include "qemu-file.h"
+
+void cgs_mh_init(void);
+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);
+
+#endif
diff --git a/migration/confidential-ram.c b/migration/confidential-ram.c
new file mode 100644
index 0000000000..65a588e7f6
--- /dev/null
+++ b/migration/confidential-ram.c
@@ -0,0 +1,184 @@
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu/rcu.h"
+#include "qemu/coroutine.h"
+#include "qemu/timer.h"
+#include "io/channel.h"
+#include "qapi/error.h"
+#include "exec/memory.h"
+#include "trace.h"
+#include "confidential-ram.h"
+
+enum cgs_mig_helper_cmd {
+    /* Initialize migration helper in guest */
+    CGS_MIG_HELPER_CMD_INIT = 0,
+
+    /*
+     * Fetch a page from gpa, encrypt it, and save result into the shared page
+     */
+    CGS_MIG_HELPER_CMD_ENCRYPT,
+
+    /* Read the shared page, decrypt it, and save result into gpa */
+    CGS_MIG_HELPER_CMD_DECRYPT,
+
+    /* Reset migration helper in guest */
+    CGS_MIG_HELPER_CMD_RESET,
+
+    CGS_MIG_HELPER_CMD_MAX
+};
+
+struct QEMU_PACKED CGSMigHelperCmdParams {
+    uint64_t cmd_type;
+    uint64_t gpa;
+    int32_t prefetch;
+    int32_t ret;
+    int32_t go;
+    int32_t done;
+};
+typedef struct CGSMigHelperCmdParams CGSMigHelperCmdParams;
+
+struct QEMU_PACKED CGSMigHelperPageHeader {
+    uint32_t len;
+    uint8_t data[0];
+};
+typedef struct CGSMigHelperPageHeader CGSMigHelperPageHeader;
+
+struct CGSMigHelperState {
+    CGSMigHelperCmdParams *cmd_params;
+    CGSMigHelperPageHeader *io_page_hdr;
+    uint8_t *io_page;
+    bool initialized;
+};
+typedef struct CGSMigHelperState CGSMigHelperState;
+
+static CGSMigHelperState cmhs = {0};
+
+#define MH_BUSYLOOP_TIMEOUT       100000000LL
+#define MH_REQUEST_TIMEOUT_MS     100
+#define MH_REQUEST_TIMEOUT_NS     (MH_REQUEST_TIMEOUT_MS * 1000 * 1000)
+
+/*
+ * The migration helper shared area is hard-coded at gpa 0x820000 with size of
+ * 2 pages (0x2000 bytes).  Instead of hard-coding, the address and size may be
+ * fetched from OVMF itself using a pc_system_ovmf_table_find call to query
+ * OVMF's GUIDed structure for a migration helper GUID.
+ */
+#define MH_SHARED_CMD_PARAMS_ADDR    0x820000
+#define MH_SHARED_IO_PAGE_HDR_ADDR   (MH_SHARED_CMD_PARAMS_ADDR + 0x800)
+#define MH_SHARED_IO_PAGE_ADDR       (MH_SHARED_CMD_PARAMS_ADDR + 0x1000)
+
+void cgs_mh_init(void)
+{
+    RCU_READ_LOCK_GUARD();
+    cmhs.cmd_params = qemu_map_ram_ptr(NULL, MH_SHARED_CMD_PARAMS_ADDR);
+    cmhs.io_page_hdr = qemu_map_ram_ptr(NULL, MH_SHARED_IO_PAGE_HDR_ADDR);
+    cmhs.io_page = qemu_map_ram_ptr(NULL, MH_SHARED_IO_PAGE_ADDR);
+}
+
+static int send_command_to_cgs_mig_helper(uint64_t cmd_type, uint64_t gpa)
+{
+    /*
+     * The cmd_params struct is on a page shared with the guest migration
+     * helper.  We use a volatile struct to force writes to memory so that the
+     * guest can see them.
+     */
+    volatile CGSMigHelperCmdParams *params = cmhs.cmd_params;
+    int64_t counter, request_timeout_at;
+
+    /*
+     * At this point io_page and io_page_hdr should be already filled according
+     * to the requested cmd_type.
+     */
+
+    params->cmd_type = cmd_type;
+    params->gpa = gpa;
+    params->prefetch = 0;
+    params->ret = -1;
+    params->done = 0;
+
+    /*
+     * Force writes of all command parameters before writing the 'go' flag.
+     * The guest migration handler waits for the go flag and then reads the
+     * command parameters.
+     */
+    smp_wmb();
+
+    /* Tell the migration helper to start working on this command */
+    params->go = 1;
+
+    /*
+     * Wait for the guest migration helper to process the command and mark the
+     * done flag
+     */
+    request_timeout_at = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) +
+                         MH_REQUEST_TIMEOUT_NS;
+    do {
+        counter = 0;
+        while (!params->done && (counter < MH_BUSYLOOP_TIMEOUT)) {
+            counter++;
+        }
+    } while (!params->done &&
+             qemu_clock_get_ns(QEMU_CLOCK_REALTIME) < request_timeout_at);
+
+    if (!params->done) {
+        error_report("Migration helper command %" PRIu64 " timed-out for "
+                     "gpa 0x%" PRIx64, cmd_type, gpa);
+        return -EIO;
+    }
+
+    return params->ret;
+}
+
+static void init_cgs_mig_helper_if_needed(void)
+{
+    int ret;
+
+    if (cmhs.initialized) {
+        return;
+    }
+
+    ret = send_command_to_cgs_mig_helper(CGS_MIG_HELPER_CMD_INIT, 0);
+    if (ret == 0) {
+        cmhs.initialized = true;
+    }
+}
+
+void cgs_mh_cleanup(void)
+{
+    send_command_to_cgs_mig_helper(CGS_MIG_HELPER_CMD_RESET, 0);
+}
+
+int cgs_mh_save_encrypted_page(QEMUFile *f, ram_addr_t src_gpa, uint32_t size,
+                               uint64_t *bytes_sent)
+{
+    int ret;
+
+    init_cgs_mig_helper_if_needed();
+
+    /* Ask the migration helper to encrypt the page at src_gpa */
+    trace_encrypted_ram_save_page(size, src_gpa);
+    ret = send_command_to_cgs_mig_helper(CGS_MIG_HELPER_CMD_ENCRYPT, src_gpa);
+    if (ret) {
+        error_report("Error cgs_mh_save_encrypted_page ret=%d", ret);
+        return -1;
+    }
+
+    /* Sanity check for response header */
+    if (cmhs.io_page_hdr->len > 1024) {
+        error_report("confidential-ram: migration helper response is too large "
+                     "(len=%u)", cmhs.io_page_hdr->len);
+        return -EINVAL;
+    }
+
+    qemu_put_be32(f, cmhs.io_page_hdr->len);
+    qemu_put_buffer(f, cmhs.io_page_hdr->data, cmhs.io_page_hdr->len);
+    *bytes_sent = 4 + cmhs.io_page_hdr->len;
+
+    qemu_put_be32(f, size);
+    qemu_put_buffer(f, cmhs.io_page, size);
+    *bytes_sent += 4 + size;
+
+    return ret;
+}
diff --git a/migration/meson.build b/migration/meson.build
index 9645f44005..95fe7bdd12 100644
--- a/migration/meson.build
+++ b/migration/meson.build
@@ -30,4 +30,8 @@ softmmu_ss.add(when: ['CONFIG_RDMA', rdma], if_true: files('rdma.c'))
 softmmu_ss.add(when: 'CONFIG_LIVE_BLOCK_MIGRATION', if_true: files('block.c'))
 softmmu_ss.add(when: zstd, if_true: files('multifd-zstd.c'))
 
-specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files('dirtyrate.c', 'ram.c'))
+specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files(
+  'dirtyrate.c',
+  'ram.c',
+  'confidential-ram.c',
+))
diff --git a/migration/trace-events b/migration/trace-events
index 668c562fed..929de4ca98 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -343,3 +343,6 @@ migration_block_save_pending(uint64_t pending) "Enter save live pending  %" PRIu
 # page_cache.c
 migration_pagecache_init(int64_t max_num_items) "Setting cache buckets to %" PRId64
 migration_pagecache_insert(void) "Error allocating page"
+
+# confidential-ram.c
+encrypted_ram_save_page(uint32_t size, uint64_t gpa) "size: %u, gpa: 0x%" PRIx64
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 13/26] migration: Add helpers to load confidential RAM
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (11 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 12/26] migration: Add helpers to save confidential RAM Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 14/26] migration: Introduce gpa_inside_migration_helper_shared_area Dov Murik
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Juan Quintela,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Dr. David Alan Gilbert, Hubertus Franke, Tobin Feldman-Fitzthum

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 --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
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 14/26] migration: Introduce gpa_inside_migration_helper_shared_area
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (12 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 13/26] migration: Add helpers to load " Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 15/26] migration: Save confidential guest RAM using migration helper Dov Murik
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Juan Quintela,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Dr. David Alan Gilbert, Hubertus Franke, Tobin Feldman-Fitzthum

The gpa_inside_migration_helper_shared_area will be used to skip
migrating RAM pages that are used by the migration helper at the target.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 migration/confidential-ram.h | 2 ++
 migration/confidential-ram.c | 6 ++++++
 2 files changed, 8 insertions(+)

diff --git a/migration/confidential-ram.h b/migration/confidential-ram.h
index ebe4073bce..9a1027bdaf 100644
--- a/migration/confidential-ram.h
+++ b/migration/confidential-ram.h
@@ -8,6 +8,8 @@
 #include "exec/cpu-common.h"
 #include "qemu-file.h"
 
+bool gpa_inside_migration_helper_shared_area(ram_addr_t gpa);
+
 void cgs_mh_init(void);
 void cgs_mh_cleanup(void);
 
diff --git a/migration/confidential-ram.c b/migration/confidential-ram.c
index fe317ee74b..0b821af774 100644
--- a/migration/confidential-ram.c
+++ b/migration/confidential-ram.c
@@ -68,6 +68,12 @@ static CGSMigHelperState cmhs = {0};
 #define MH_SHARED_CMD_PARAMS_ADDR    0x820000
 #define MH_SHARED_IO_PAGE_HDR_ADDR   (MH_SHARED_CMD_PARAMS_ADDR + 0x800)
 #define MH_SHARED_IO_PAGE_ADDR       (MH_SHARED_CMD_PARAMS_ADDR + 0x1000)
+#define MH_SHARED_LAST_BYTE          (MH_SHARED_CMD_PARAMS_ADDR + 0x1fff)
+
+bool gpa_inside_migration_helper_shared_area(ram_addr_t gpa)
+{
+    return gpa >= MH_SHARED_CMD_PARAMS_ADDR && gpa <= MH_SHARED_LAST_BYTE;
+}
 
 void cgs_mh_init(void)
 {
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 15/26] migration: Save confidential guest RAM using migration helper
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (13 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 14/26] migration: Introduce gpa_inside_migration_helper_shared_area Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 16/26] migration: Load " Dov Murik
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Juan Quintela,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Dr. David Alan Gilbert, Hubertus Franke, Tobin Feldman-Fitzthum

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



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 16/26] migration: Load confidential guest RAM using migration helper
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (14 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 15/26] migration: Save confidential guest RAM using migration helper Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 17/26] migration: Stop VM after loading confidential RAM Dov Murik
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Juan Quintela,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Dr. David Alan Gilbert, Hubertus Franke, Tobin Feldman-Fitzthum

When loading encrypted RAM pages of a confidential guest, ask the
in-guest migration helper to decrypt the incoming page and place it
correctly in the guest memory at the appropriate address.  This way the
page's plaintext content remains inaccessible to the host.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 migration/ram.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/migration/ram.c b/migration/ram.c
index 8e55ed49fd..82a1d13f5f 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -3519,6 +3519,10 @@ void colo_release_ram_cache(void)
  */
 static int ram_load_setup(QEMUFile *f, void *opaque)
 {
+    if (confidential_guest()) {
+        cgs_mh_init();
+    }
+
     if (compress_threads_load_setup(f)) {
         return -1;
     }
@@ -3812,6 +3816,8 @@ void colo_flush_ram_cache(void)
 static int ram_load_precopy(QEMUFile *f)
 {
     int flags = 0, ret = 0, invalid_flags = 0, len = 0, i = 0;
+    ram_addr_t gpa;
+
     /* ADVISE is earlier, it shows the source has the postcopy capability on */
     bool postcopy_advised = postcopy_is_advised();
     if (!migrate_use_compression()) {
@@ -3848,7 +3854,8 @@ static int ram_load_precopy(QEMUFile *f)
         }
 
         if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE |
-                     RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE)) {
+                     RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE |
+                     RAM_SAVE_FLAG_GUEST_ENCRYPTED_PAGE)) {
             RAMBlock *block = ram_block_from_stream(f, flags);
 
             host = host_from_ram_block_offset(block, addr);
@@ -3977,6 +3984,16 @@ static int ram_load_precopy(QEMUFile *f)
                 break;
             }
             break;
+
+        case RAM_SAVE_FLAG_GUEST_ENCRYPTED_PAGE:
+            if (!kvm_physical_memory_addr_from_host(kvm_state, host, &gpa)) {
+                error_report("%s: failed to get gpa for host %p", __func__, host);
+                ret = -EINVAL;
+                break;
+            }
+            ret = cgs_mh_load_encrypted_page(f, gpa);
+            break;
+
         case RAM_SAVE_FLAG_EOS:
             /* normal exit */
             multifd_recv_sync_main();
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 17/26] migration: Stop VM after loading confidential RAM
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (15 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 16/26] migration: Load " Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 18/26] migration: Stop non-aux vcpus before copying the last pages Dov Murik
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	Juan Quintela, Richard Henderson, James Bottomley, Jon Grimm,
	Tobin Feldman-Fitzthum, Dov Murik, Dr. David Alan Gilbert,
	Hubertus Franke, Tobin Feldman-Fitzthum, Paolo Bonzini

Register a dummy device state (EndOfConfidentialRAMState) with high
priority so it is the first device which is loaded in the target.  The
post_load handler of this device stops the VM, which makes things easier
when loading devices' states which expect the VM not to be running at
the same time.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 migration/confidential-ram.h |  2 ++
 migration/confidential-ram.c | 31 +++++++++++++++++++++++++++++++
 softmmu/runstate.c           |  1 +
 target/i386/sev.c            |  2 ++
 4 files changed, 36 insertions(+)

diff --git a/migration/confidential-ram.h b/migration/confidential-ram.h
index 9a1027bdaf..2822c5ee3d 100644
--- a/migration/confidential-ram.h
+++ b/migration/confidential-ram.h
@@ -18,4 +18,6 @@ int cgs_mh_save_encrypted_page(QEMUFile *f, ram_addr_t src_gpa, uint32_t size,
 
 int cgs_mh_load_encrypted_page(QEMUFile *f, ram_addr_t dest_gpa);
 
+void register_end_of_confidential_ram(void);
+
 #endif
diff --git a/migration/confidential-ram.c b/migration/confidential-ram.c
index 0b821af774..982cf9b874 100644
--- a/migration/confidential-ram.c
+++ b/migration/confidential-ram.c
@@ -8,6 +8,8 @@
 #include "io/channel.h"
 #include "qapi/error.h"
 #include "exec/memory.h"
+#include "migration/vmstate.h"
+#include "sysemu/runstate.h"
 #include "trace.h"
 #include "confidential-ram.h"
 
@@ -225,3 +227,32 @@ int cgs_mh_load_encrypted_page(QEMUFile *f, ram_addr_t dest_gpa)
     }
     return ret;
 }
+
+typedef struct {
+    bool dummy;
+} EndOfConfidentialRAMState;
+
+static EndOfConfidentialRAMState end_of_confidential_ram_state = { .dummy = false };
+
+static int end_of_confidential_ram_post_load(void *opaque, int version_id)
+{
+    vm_stop(RUN_STATE_INMIGRATE);
+    return 0;
+}
+
+static const VMStateDescription vmstate_end_of_confidential_ram = {
+    .name = "end-of-confidential-ram",
+    .priority = MIG_PRI_GICV3, /* TODO define new (higher) priority level */
+    .version_id = 1,
+    .post_load = end_of_confidential_ram_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_BOOL(dummy, EndOfConfidentialRAMState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+void register_end_of_confidential_ram(void)
+{
+    vmstate_register(NULL, 0, &vmstate_end_of_confidential_ram,
+                     &end_of_confidential_ram_state);
+}
diff --git a/softmmu/runstate.c b/softmmu/runstate.c
index 2874417b61..193413246d 100644
--- a/softmmu/runstate.c
+++ b/softmmu/runstate.c
@@ -131,6 +131,7 @@ static const RunStateTransition runstate_transitions_def[] = {
     { RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
     { RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
     { RUN_STATE_RUNNING, RUN_STATE_PAUSED },
+    { RUN_STATE_RUNNING, RUN_STATE_INMIGRATE },
     { RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
     { RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
     { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 0f414df02f..da2d0cc699 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -33,6 +33,7 @@
 #include "exec/address-spaces.h"
 #include "monitor/monitor.h"
 #include "exec/confidential-guest-support.h"
+#include "migration/confidential-ram.h"
 #include "hw/i386/pc.h"
 
 #define TYPE_SEV_GUEST "sev-guest"
@@ -1011,6 +1012,7 @@ static void
 sev_register_types(void)
 {
     type_register_static(&sev_guest_info);
+    register_end_of_confidential_ram();
 }
 
 type_init(sev_register_types);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 18/26] migration: Stop non-aux vcpus before copying the last pages
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (16 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 17/26] migration: Stop VM after loading confidential RAM Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 19/26] migration: Don't sync vcpus when migrating confidential guests Dov Murik
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Juan Quintela,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Dr. David Alan Gilbert, Hubertus Franke, Tobin Feldman-Fitzthum

From: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>

Co-Author: Dov Murik <dovmurik@linux.vnet.ibm.com>
Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
Signed-off-by: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>
---
 migration/migration.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/migration/migration.c b/migration/migration.c
index a5ddf43559..7ec25bd006 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -24,6 +24,7 @@
 #include "sysemu/runstate.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/cpu-throttle.h"
+#include "sysemu/cpus.h"
 #include "rdma.h"
 #include "ram.h"
 #include "migration/global_state.h"
@@ -3156,14 +3157,14 @@ static void migration_completion(MigrationState *s)
         qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
         s->vm_was_running = runstate_is_running();
         ret = global_state_store();
+        pause_all_vcpus_except_aux();
+        qemu_mutex_unlock_iothread();
 
         if (!ret) {
             bool inactivate = !migrate_colo_enabled();
-            ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
-            if (ret >= 0) {
-                ret = migration_maybe_pause(s, &current_active_state,
-                                            MIGRATION_STATUS_DEVICE);
-            }
+            ret = migration_maybe_pause(s, &current_active_state,
+                                        MIGRATION_STATUS_DEVICE);
+
             if (ret >= 0) {
                 qemu_file_set_rate_limit(s->to_dst_file, INT64_MAX);
                 ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
@@ -3173,7 +3174,7 @@ static void migration_completion(MigrationState *s)
                 s->block_inactive = true;
             }
         }
-        qemu_mutex_unlock_iothread();
+        runstate_set(RUN_STATE_FINISH_MIGRATE);
 
         if (ret < 0) {
             goto fail;
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 19/26] migration: Don't sync vcpus when migrating confidential guests
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (17 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 18/26] migration: Stop non-aux vcpus before copying the last pages Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 20/26] migration: When starting target, don't sync auxiliary vcpus Dov Murik
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Juan Quintela,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Dr. David Alan Gilbert, Hubertus Franke, Tobin Feldman-Fitzthum

When loading incoming VM state to the migration target, don't sync the
vcpus because it'll prevent the migration handler to keep running.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 migration/savevm.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/migration/savevm.c b/migration/savevm.c
index 52e2d72e4b..c5252612c3 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -2673,6 +2673,13 @@ out:
     return ret;
 }
 
+static inline bool confidential_guest(void)
+{
+    MachineState *ms = MACHINE(qdev_get_machine());
+
+    return ms->cgs;
+}
+
 int qemu_loadvm_state(QEMUFile *f)
 {
     MigrationIncomingState *mis = migration_incoming_get_current();
@@ -2693,7 +2700,9 @@ int qemu_loadvm_state(QEMUFile *f)
         return -EINVAL;
     }
 
-    cpu_synchronize_all_pre_loadvm();
+    if (!confidential_guest()) {
+        cpu_synchronize_all_pre_loadvm();
+    }
 
     ret = qemu_loadvm_state_main(f, mis);
     qemu_event_set(&mis->main_thread_load_event);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 20/26] migration: When starting target, don't sync auxiliary vcpus
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (18 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 19/26] migration: Don't sync vcpus when migrating confidential guests Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 21/26] migration: Call migration handler cleanup routines Dov Murik
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Juan Quintela,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Dr. David Alan Gilbert, Hubertus Franke, Tobin Feldman-Fitzthum

If auxiliary vcpus are defined, they are used for running the migration
helper inside the guest.  We want to keep them running and not sync
their state.

This behaves exactly like cpu_synchronize_all_post_init() when there are
no auxiliary vcpus.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 migration/savevm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/migration/savevm.c b/migration/savevm.c
index c5252612c3..c6af1f7bba 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -2754,7 +2754,7 @@ int qemu_loadvm_state(QEMUFile *f)
     }
 
     qemu_loadvm_state_cleanup();
-    cpu_synchronize_all_post_init();
+    cpu_synchronize_without_aux_post_init();
 
     return ret;
 }
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 21/26] migration: Call migration handler cleanup routines
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (19 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 20/26] migration: When starting target, don't sync auxiliary vcpus Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 22/26] hw/isa/lpc_ich9: Allow updating an already-running VM Dov Murik
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Juan Quintela,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Dr. David Alan Gilbert, Hubertus Franke, Tobin Feldman-Fitzthum

From: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>

Signed-off-by: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>
Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 migration/ram.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/migration/ram.c b/migration/ram.c
index 82a1d13f5f..ce551c1d2f 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -3054,6 +3054,10 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
         ram_control_after_iterate(f, RAM_CONTROL_FINISH);
     }
 
+    if (confidential_guest()) {
+        cgs_mh_cleanup();
+    }
+
     if (ret >= 0) {
         multifd_send_sync_main(rs->f);
         qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
@@ -3549,6 +3553,10 @@ static int ram_load_cleanup(void *opaque)
         rb->receivedmap = NULL;
     }
 
+    if (confidential_guest()) {
+        cgs_mh_cleanup();
+    }
+
     return 0;
 }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 22/26] hw/isa/lpc_ich9: Allow updating an already-running VM
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (20 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 21/26] migration: Call migration handler cleanup routines Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 23/26] target/i386: Re-sync kvm-clock after confidential guest migration Dov Murik
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Michael S. Tsirkin,
	James Bottomley, Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik,
	Hubertus Franke, Tobin Feldman-Fitzthum

The post_load function crashed when we were loading the device state in
to an already-running guest.  This was because an existing memory region
as not deleted in ich9_lpc_rcba_update.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 hw/isa/lpc_ich9.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index d3145bf014..1fc1af3491 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -529,9 +529,10 @@ ich9_lpc_pmcon_update(ICH9LPCState *lpc)
 static int ich9_lpc_post_load(void *opaque, int version_id)
 {
     ICH9LPCState *lpc = opaque;
+    uint32_t rcba_old = pci_get_long(lpc->d.config + ICH9_LPC_RCBA);
 
     ich9_lpc_pmbase_sci_update(lpc);
-    ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RCBA_EN */);
+    ich9_lpc_rcba_update(lpc, rcba_old);
     ich9_lpc_pmcon_update(lpc);
     return 0;
 }
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 23/26] target/i386: Re-sync kvm-clock after confidential guest migration
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (21 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 22/26] hw/isa/lpc_ich9: Allow updating an already-running VM Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 24/26] migration: Add start-migrate-incoming QMP command Dov Murik
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	Richard Henderson, James Bottomley, Jon Grimm,
	Tobin Feldman-Fitzthum, Dov Murik, Hubertus Franke,
	Tobin Feldman-Fitzthum, Paolo Bonzini

If confidential guest support is active, set TSC to 0 on the target when
loading the CPU state.  This causes the guest OS to re-sync with
kvm-clock.

Without this change, the guest clocks after migration are stuck (don't
advance), except the *_COARSE clocks which advance normally.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 target/i386/machine.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/target/i386/machine.c b/target/i386/machine.c
index 3768a753af..36c52ec02e 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -297,8 +297,17 @@ static int cpu_post_load(void *opaque, int version_id)
     X86CPU *cpu = opaque;
     CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
+    MachineState *ms = MACHINE(qdev_get_machine());
     int i;
 
+    /*
+     * When loading the state of a confidential guest, set TSC to zero at allow
+     * the guest OS to re-sync with kvmclock.
+     */
+    if (ms->cgs) {
+        env->tsc = 0;
+    }
+
     if (env->tsc_khz && env->user_tsc_khz &&
         env->tsc_khz != env->user_tsc_khz) {
         error_report("Mismatch between user-specified TSC frequency and "
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 24/26] migration: Add start-migrate-incoming QMP command
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (22 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 23/26] target/i386: Re-sync kvm-clock after confidential guest migration Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 25/26] target/i386: SEV: Allow migration unless there are no aux vcpus Dov Murik
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Juan Quintela,
	Markus Armbruster, James Bottomley, Jon Grimm,
	Tobin Feldman-Fitzthum, Dov Murik, Dr. David Alan Gilbert,
	Hubertus Franke, Tobin Feldman-Fitzthum

This command forces a running VM into a migrate-incoming state.  When
using guest-assisted migration (for confidential guests), the target
must be started so that its auxiliary vcpu is running the migration
helper; after it is ready we can start receiving the incoming migration
connection.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 qapi/migration.json   | 26 ++++++++++++++++++++++++++
 migration/migration.c |  5 +++++
 2 files changed, 31 insertions(+)

diff --git a/qapi/migration.json b/qapi/migration.json
index 6e5943fbb4..c7361e0038 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1569,6 +1569,32 @@
 ##
 { 'command': 'migrate-incoming', 'data': {'uri': 'str' } }
 
+##
+# @start-migrate-incoming:
+#
+# Force start an incoming migration even in a running VM.  This is used by the
+# target VM in guest-assisted migration of a confidential guest.
+#
+# @uri: The Uniform Resource Identifier identifying the source or
+#       address to listen on
+#
+# Returns: nothing on success
+#
+# Since: 6.0
+#
+# Notes:
+#
+# The uri format is the same as the -incoming command-line option.
+#
+# Example:
+#
+# -> { "execute": "start-migrate-incoming",
+#      "arguments": { "uri": "tcp::4446" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'start-migrate-incoming', 'data': {'uri': 'str' } }
+
 ##
 # @xen-save-devices-state:
 #
diff --git a/migration/migration.c b/migration/migration.c
index 7ec25bd006..4729b89bef 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -2098,6 +2098,11 @@ void qmp_migrate_incoming(const char *uri, Error **errp)
     once = false;
 }
 
+void qmp_start_migrate_incoming(const char *uri, Error **errp)
+{
+    qemu_start_incoming_migration(uri, errp);
+}
+
 void qmp_migrate_recover(const char *uri, Error **errp)
 {
     MigrationIncomingState *mis = migration_incoming_get_current();
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 25/26] target/i386: SEV: Allow migration unless there are no aux vcpus
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (23 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 24/26] migration: Add start-migrate-incoming QMP command Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 20:48 ` [RFC PATCH 26/26] docs: Add confidential guest live migration documentation Dov Murik
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, Eduardo Habkost,
	Richard Henderson, James Bottomley, Jon Grimm,
	Tobin Feldman-Fitzthum, Dov Murik, Hubertus Franke,
	Tobin Feldman-Fitzthum, Paolo Bonzini

Memory-encrypted guests require a migration helper running on an
auxiliary vcpu inside the guest in order to migrate RAM to the target.
When there are no auxiliary vcpus, block migration attempts.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 target/i386/sev.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/target/i386/sev.c b/target/i386/sev.c
index da2d0cc699..f22f9b29ea 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -32,6 +32,7 @@
 #include "qom/object.h"
 #include "exec/address-spaces.h"
 #include "monitor/monitor.h"
+#include "hw/boards.h"
 #include "exec/confidential-guest-support.h"
 #include "migration/confidential-ram.h"
 #include "hw/i386/pc.h"
@@ -669,6 +670,7 @@ sev_launch_finish(SevGuestState *sev)
 {
     int ret, error;
     Error *local_err = NULL;
+    MachineState *ms = MACHINE(qdev_get_machine());
 
     trace_kvm_sev_launch_finish();
     ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
@@ -680,14 +682,19 @@ sev_launch_finish(SevGuestState *sev)
 
     sev_set_guest_state(sev, SEV_STATE_RUNNING);
 
-    /* add migration blocker */
-    error_setg(&sev_mig_blocker,
-               "SEV: Migration is not implemented");
-    ret = migrate_add_blocker(sev_mig_blocker, &local_err);
-    if (local_err) {
-        error_report_err(local_err);
-        error_free(sev_mig_blocker);
-        exit(1);
+    /*
+     * SEV migration is not supported unless there's an auxiliary CPU running
+     * the guest-assisted migration helper.
+     */
+    if (ms->smp.aux_cpus == 0) {
+        error_setg(&sev_mig_blocker,
+                   "SEV: Migration is not implemented");
+        ret = migrate_add_blocker(sev_mig_blocker, &local_err);
+        if (local_err) {
+            error_report_err(local_err);
+            error_free(sev_mig_blocker);
+            exit(1);
+        }
     }
 }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [RFC PATCH 26/26] docs: Add confidential guest live migration documentation
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (24 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 25/26] target/i386: SEV: Allow migration unless there are no aux vcpus Dov Murik
@ 2021-03-02 20:48 ` Dov Murik
  2021-03-02 21:24 ` [RFC PATCH 00/26] Confidential guest live migration no-reply
  2021-03-04  9:10 ` Paolo Bonzini
  27 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-02 20:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, James Bottomley,
	Jon Grimm, Tobin Feldman-Fitzthum, Dov Murik, Hubertus Franke,
	Tobin Feldman-Fitzthum

The new page is linked from the main index, otherwise sphinx complains
that "document isn't included in any toctree"; I assume there would be a
better place for it in the documentation tree.

Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
 docs/confidential-guest-live-migration.rst | 142 +++++++++++++++++++++
 docs/confidential-guest-support.txt        |   5 +
 docs/index.rst                             |   1 +
 3 files changed, 148 insertions(+)
 create mode 100644 docs/confidential-guest-live-migration.rst

diff --git a/docs/confidential-guest-live-migration.rst b/docs/confidential-guest-live-migration.rst
new file mode 100644
index 0000000000..dc59df8f9c
--- /dev/null
+++ b/docs/confidential-guest-live-migration.rst
@@ -0,0 +1,142 @@
+=================================
+Confidential Guest Live Migration
+=================================
+
+When migrating regular QEMU guests, QEMU reads the guest's RAM and sends it
+over to the migration target host, where QEMU there writes it into the target
+guest's RAM and starts the VM.  This mechanism doesn't work when the guest
+memory is encrypted or QEMU is prevented from reading it in another way.
+
+In order to support live migration in such scenarios, QEMU relies on an
+in-guest migration helper which can securely extract RAM content from the
+guest in order to send it to the target.  The migration helper is implemented as
+part of the VM's firmware in OVMF.
+
+
+Migration flow
+==============
+
+Source VM
+---------
+
+The source VM is started with an extra auxiliary vcpu which is not listed in the
+ACPI tables.  OVMF uses this vcpu and starts a dedicated migration helper on it;
+the migration helper simply waits for commands from QEMU.  When migration starts
+using the ``migrate`` command, QEMU starts saving the state of the different
+devices.  When it reaches saving RAM pages, it'll check for each page whether it
+is encrypted or not; for encrypted pages, it'll send a command to the migration
+helper to extract the given page.  The migration helper receives this command,
+reads the page content, encrypts it with a transport key, and returns the
+newly-encrypted page to QEMU.  QEMU saves those pages to the outgoing migration
+stream using a new page flag ``RAM_SAVE_FLAG_GUEST_ENCRYPTED_PAGE``.
+
+When QEMU reaches the last stage of RAM migration, it stops the source VM to
+avoid dirtying the last pages of RAM.  However, the auxiliary vcpu must be kept
+running so the migration helper can still extract pages from the guest memory.
+
+Target VM
+---------
+
+Usually QEMU migration target VMs are started with the ``-incoming``
+command-line option which starts the VM paused.  However, in order to migrate
+confidential guests we must have the migration helper running inside the guest;
+in such a case, we start the target with a special ``-fw_cfg`` value that tells
+OVMF to enter a CPU dead loop on all vcpus except the auxiliary vcpu, which runs
+the migration helper.  After this short "boot" completes, QEMU can switch to the
+"migration incoming" mode; we do that with the new ``start-migrate-incoming``
+QMP command that makes the target VM listen for incoming migration connections.
+
+QEMU will load the state of VM devices as it arrives from the incoming migration
+stream.  When it encounters a RAM page with the
+``RAM_SAVE_FLAG_GUEST_ENCRYPTED_PAGE`` flag, it will send its
+transport-encrypted content and guest physical address to the migration helper.
+The migration helper running inside the guest will decrypt the page using the
+transport key and place the content in memory (again, that memory page is not
+accessible to host due to the confidential guest properties; for example, in SEV
+it is hardware-encrypted with a VM-specific key).
+
+
+Usage
+=====
+
+In order to start the source and target VMs with auxiliary CPUs, the auxcpus=
+option must be passed to ``-smp`` . For example::
+
+    # ${QEMU} -smp 5,auxcpus=1 ...
+
+This command starts a VM with 5 vcpus of which 4 are main vcpus (available for
+the guest OS) and 1 is auxliary vcpu.
+
+Moreover, in both the source and target we need to instruct OVMF to start the
+migration helper running in the auxiliary vcpu.  This is achieved using the
+following command-line option::
+
+    # ${QEMU} -fw_cfg name=opt/ovmf/PcdSevIsMigrationHelper,string=0 ...
+
+In the target VM we need to add another ``-fw_cfg`` entry to instruct OVMF to
+start only the migration helepr, which will wait for incoming pages (the target
+cannot be started with ``-incoming`` because that option completely pauses the
+VM, not allowing the migration helper to run). Because the migration helper must
+be running when the incoming RAM pages are received, starting the target VM with
+the ``-incoming`` option doesn't work (with that option, the VM doesn't start
+executing).  Instead, start the target VM without ``-incoming`` but with the
+following option::
+
+    # ${QEMU} -fw_cfg name=opt/ovmf/PcdSevIsMigrationTarget,string=1 ...
+
+After the VM boots into the migration helper, we instruct QEMU to listen for
+incoming migration connections by sending the following QMP command::
+
+    { "execute": "start-migrate-incoming",
+      "arguments": { "uri": "tcp:0.0.0.0:6666" } }
+
+Now that the target is ready, we instruct the source VM to start migrating its
+state using the regular ``migrate`` QMP command, supplying the target VMs
+listening address::
+
+    { "execute": "migrate",
+      "arguments": { "uri": "tcp:192.168.111.222:6666" } }
+
+
+Implementation details
+======================
+
+Migration helper <-> QEMU communication
+---------------------------------------
+
+The migration helper is running inside the guest (implemented as part of OVMF).
+QEMU communicates with it using a mailbox protocol over two shared (unencrypted)
+4K RAM pages.
+
+The first page contains a ``SevMigHelperCmdParams`` struct at offset 0x0
+(``cmd_params``) and a ``MigrationHelperHeader`` struct at offset 0x800
+(``io_hdr``).  The second page (``io_page``) is dedicated for encrypted page
+content.
+
+In order to save a confidential RAM page, QEMU will fill the ``cmd_params``
+struct to indicate the SEV_MIG_HELPER_CMD_ENCRYPT command and the requested gpa
+(guest physical address), and then set the ``go`` field to 1.  Meanwhile the
+migration helper waits for the ``go`` field to become non-zero; after it notices
+``go`` is 1 it'll read the gpa, read the content of the relevant page from the
+guest's memory, encrypt it with the transport key, and store the
+transport-encrypted page in the the ``io_page``.  Additional envelope data like
+encryption IV and other fields are stored in ``io_hdr``.  After the migration is
+done writing to ``io_page`` and ``io_hdr``, it sets the ``done`` field to 1.  At
+this point QEMU notices that the migration helper is done and can continue its
+part, which is saving the header and page to the outgoing migration stream.
+
+Similar process is used when loading a confidential RAM from the incoming
+migration stream.  QEMU reads the header and the encrypted page from the stream,
+and copies them into the shared areas ``io_hdr`` and ``io_page`` respectably.
+It then fills the ``cmd_params`` struct to indicate the
+SEV_MIG_HELPER_CMD_DECRYPT command and the gpa, and sets ``go`` to 1.  The
+migration helper will notice the command, will decrypt the page using the
+transport key and will place the decrypted content in the requetsed gpa, and set
+``done`` to 1 to allow QEMU to continue processing the next item in the incoming
+migration stream.
+
+Shared pages address discovery
+------------------------------
+In the current implementation the address of the two shared pages is hard-coded
+in both OVMF and QEMU.  We plan for OVMF to expose this address via its GUIDed
+table and let QEMU discover it using ``pc_system_ovmf_table_find()``.
diff --git a/docs/confidential-guest-support.txt b/docs/confidential-guest-support.txt
index 71d07ba57a..bed1601fbb 100644
--- a/docs/confidential-guest-support.txt
+++ b/docs/confidential-guest-support.txt
@@ -47,3 +47,8 @@ s390x Protected Virtualization (PV)
     docs/system/s390x/protvirt.rst
 
 Other mechanisms may be supported in future.
+
+Live migration support
+----------------------
+Details regarding confidential guest live migration are in:
+    docs/confidential-guest-live-migration.rst
diff --git a/docs/index.rst b/docs/index.rst
index 763e3d0426..6f797d050a 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -16,3 +16,4 @@ Welcome to QEMU's documentation!
    interop/index
    specs/index
    devel/index
+   confidential-guest-live-migration
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [RFC PATCH 00/26] Confidential guest live migration
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (25 preceding siblings ...)
  2021-03-02 20:48 ` [RFC PATCH 26/26] docs: Add confidential guest live migration documentation Dov Murik
@ 2021-03-02 21:24 ` no-reply
  2021-03-03  8:08   ` Dov Murik
  2021-03-04  9:10 ` Paolo Bonzini
  27 siblings, 1 reply; 30+ messages in thread
From: no-reply @ 2021-03-02 21:24 UTC (permalink / raw)
  To: dovmurik
  Cc: thomas.lendacky, ashish.kalra, brijesh.singh, jejb, jon.grimm,
	tobin, qemu-devel, frankeh, dovmurik, tobin

Patchew URL: https://patchew.org/QEMU/20210302204822.81901-1-dovmurik@linux.vnet.ibm.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20210302204822.81901-1-dovmurik@linux.vnet.ibm.com
Subject: [RFC PATCH 00/26] Confidential guest live migration

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]      patchew/20210302175524.1290840-1-berrange@redhat.com -> patchew/20210302175524.1290840-1-berrange@redhat.com
 * [new tag]         patchew/20210302204822.81901-1-dovmurik@linux.vnet.ibm.com -> patchew/20210302204822.81901-1-dovmurik@linux.vnet.ibm.com
Switched to a new branch 'test'
f283a35 docs: Add confidential guest live migration documentation
08f3c3b target/i386: SEV: Allow migration unless there are no aux vcpus
99d1efb migration: Add start-migrate-incoming QMP command
6ca0894 target/i386: Re-sync kvm-clock after confidential guest migration
47e02a0 hw/isa/lpc_ich9: Allow updating an already-running VM
af25d7b migration: Call migration handler cleanup routines
48db1fb migration: When starting target, don't sync auxiliary vcpus
5eb9336 migration: Don't sync vcpus when migrating confidential guests
af9b2fa migration: Stop non-aux vcpus before copying the last pages
2789368 migration: Stop VM after loading confidential RAM
4692252 migration: Load confidential guest RAM using migration helper
e041f58 migration: Save confidential guest RAM using migration helper
328a888 migration: Introduce gpa_inside_migration_helper_shared_area
b71be10 migration: Add helpers to load confidential RAM
32bdb2e migration: Add helpers to save confidential RAM
8d2fccb softmmu: Add pause_all_vcpus_except_aux
ed10484 softmmu: Add cpu_synchronize_without_aux_post_init
e68df04 softmmu: Don't sync aux vcpus in pre_loadvm
17bfe19 hw/i386: Set CPUState.aux=true for auxiliary vcpus
808eb76 cpu: Add boolean aux field to CPUState
34d94b2 hw/acpi: Don't include auxiliary vcpus in ACPI tables
2e9bc24 hw/i386: Mark auxiliary vcpus in possible_cpus
3d07b10 hw/boards: Add aux flag to CPUArchId
0e07c01 machine: Add auxcpus=N suboption to -smp
49124f3 kvm: add support to sync the page encryption state bitmap
47f202b linux-headers: Add definitions of KVM page encryption bitmap ioctls

=== OUTPUT BEGIN ===
1/26 Checking commit 47f202b0bc8c (linux-headers: Add definitions of KVM page encryption bitmap ioctls)
2/26 Checking commit 49124f3bf03f (kvm: add support to sync the page encryption state bitmap)
ERROR: use qemu_real_host_page_size instead of getpagesize()
#51: FILE: accel/kvm/kvm-all.c:615:
+    ram_addr_t pages = int128_get64(section->size) / getpagesize();

ERROR: use qemu_real_host_page_size instead of getpagesize()
#171: FILE: include/exec/ram_addr.h:398:
+    unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE;

WARNING: line over 80 characters
#197: FILE: include/exec/ram_addr.h:424:
+                qatomic_xchg(&blocks[DIRTY_MEMORY_ENCRYPTED][idx][offset], temp);

total: 2 errors, 1 warnings, 340 lines checked

Patch 2/26 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

3/26 Checking commit 0e07c0168e00 (machine: Add auxcpus=N suboption to -smp)
4/26 Checking commit 3d07b103b36f (hw/boards: Add aux flag to CPUArchId)
5/26 Checking commit 2e9bc24b9064 (hw/i386: Mark auxiliary vcpus in possible_cpus)
6/26 Checking commit 34d94b2baa07 (hw/acpi: Don't include auxiliary vcpus in ACPI tables)
7/26 Checking commit 808eb7693543 (cpu: Add boolean aux field to CPUState)
8/26 Checking commit 17bfe1902081 (hw/i386: Set CPUState.aux=true for auxiliary vcpus)
WARNING: line over 80 characters
#26: FILE: hw/i386/x86.c:104:
+void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, bool aux, Error **errp)

WARNING: line over 80 characters
#58: FILE: include/hw/i386/x86.h:88:
+void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, bool aux, Error **errp);

total: 0 errors, 2 warnings, 34 lines checked

Patch 8/26 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
9/26 Checking commit e68df046c12e (softmmu: Don't sync aux vcpus in pre_loadvm)
10/26 Checking commit ed104842e25d (softmmu: Add cpu_synchronize_without_aux_post_init)
11/26 Checking commit 8d2fccbd9cf9 (softmmu: Add pause_all_vcpus_except_aux)
WARNING: Block comments use a leading /* on a separate line
#88: FILE: softmmu/cpus.c:614:
+    /* We need to drop the replay_lock so any vCPU threads woken up

total: 0 errors, 1 warnings, 78 lines checked

Patch 11/26 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
12/26 Checking commit 32bdb2e1c795 (migration: Add helpers to save confidential RAM)
Use of uninitialized value $acpi_testexpected in string eq at ./scripts/checkpatch.pl line 1529.
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#28: 
new file mode 100644

total: 0 errors, 1 warnings, 216 lines checked

Patch 12/26 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
13/26 Checking commit b71be10a582a (migration: Add helpers to load confidential RAM)
14/26 Checking commit 328a888fe8fd (migration: Introduce gpa_inside_migration_helper_shared_area)
15/26 Checking commit e041f580a1da (migration: Save confidential guest RAM using migration helper)
16/26 Checking commit 4692252e1994 (migration: Load confidential guest RAM using migration helper)
WARNING: line over 80 characters
#59: FILE: migration/ram.c:3990:
+                error_report("%s: failed to get gpa for host %p", __func__, host);

total: 0 errors, 1 warnings, 43 lines checked

Patch 16/26 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
17/26 Checking commit 278936890c8d (migration: Stop VM after loading confidential RAM)
WARNING: line over 80 characters
#44: FILE: migration/confidential-ram.c:235:
+static EndOfConfidentialRAMState end_of_confidential_ram_state = { .dummy = false };

total: 0 errors, 1 warnings, 67 lines checked

Patch 17/26 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
18/26 Checking commit af9b2fa4e956 (migration: Stop non-aux vcpus before copying the last pages)
19/26 Checking commit 5eb933666eda (migration: Don't sync vcpus when migrating confidential guests)
20/26 Checking commit 48db1fbc2c51 (migration: When starting target, don't sync auxiliary vcpus)
21/26 Checking commit af25d7bee8ac (migration: Call migration handler cleanup routines)
22/26 Checking commit 47e02a0e2441 (hw/isa/lpc_ich9: Allow updating an already-running VM)
23/26 Checking commit 6ca089420af2 (target/i386: Re-sync kvm-clock after confidential guest migration)
24/26 Checking commit 99d1efb7f73c (migration: Add start-migrate-incoming QMP command)
25/26 Checking commit 08f3c3b68478 (target/i386: SEV: Allow migration unless there are no aux vcpus)
26/26 Checking commit f283a35951da (docs: Add confidential guest live migration documentation)
Use of uninitialized value $acpi_testexpected in string eq at ./scripts/checkpatch.pl line 1529.
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#20: 
new file mode 100644

total: 0 errors, 1 warnings, 154 lines checked

Patch 26/26 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20210302204822.81901-1-dovmurik@linux.vnet.ibm.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [RFC PATCH 00/26] Confidential guest live migration
  2021-03-02 21:24 ` [RFC PATCH 00/26] Confidential guest live migration no-reply
@ 2021-03-03  8:08   ` Dov Murik
  0 siblings, 0 replies; 30+ messages in thread
From: Dov Murik @ 2021-03-03  8:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: thomas.lendacky, ashish.kalra, brijesh.singh, jejb, jon.grimm,
	tobin, tobin, frankeh

The errors reported below on patch 02/26 are due to rebasing an older patch
from AMD.  I didn't want to make any changes to the code (except make it compile
and run correctly) because this feature (encrypted pages bitmap) is still
work-in-progress (in KVM and QEMU).

-Dov

On 02/03/2021 23:24, no-reply@patchew.org wrote:
> Patchew URL: https://patchew.org/QEMU/20210302204822.81901-1-dovmurik@linux.vnet.ibm.com/
> 
> 
> 
> Hi,
> 
> This series seems to have some coding style problems. See output below for
> more information:
> 
> Type: series
> Message-id: 20210302204822.81901-1-dovmurik@linux.vnet.ibm.com
> Subject: [RFC PATCH 00/26] Confidential guest live migration
> 
> === TEST SCRIPT BEGIN ===
> #!/bin/bash
> git rev-parse base > /dev/null || exit 0
> git config --local diff.renamelimit 0
> git config --local diff.renames True
> git config --local diff.algorithm histogram
> ./scripts/checkpatch.pl --mailback base..
> === TEST SCRIPT END ===
> 
> Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
> From https://github.com/patchew-project/qemu
>  - [tag update]      patchew/20210302175524.1290840-1-berrange@redhat.com -> patchew/20210302175524.1290840-1-berrange@redhat.com
>  * [new tag]         patchew/20210302204822.81901-1-dovmurik@linux.vnet.ibm.com -> patchew/20210302204822.81901-1-dovmurik@linux.vnet.ibm.com
> Switched to a new branch 'test'
> f283a35 docs: Add confidential guest live migration documentation
> 08f3c3b target/i386: SEV: Allow migration unless there are no aux vcpus
> 99d1efb migration: Add start-migrate-incoming QMP command
> 6ca0894 target/i386: Re-sync kvm-clock after confidential guest migration
> 47e02a0 hw/isa/lpc_ich9: Allow updating an already-running VM
> af25d7b migration: Call migration handler cleanup routines
> 48db1fb migration: When starting target, don't sync auxiliary vcpus
> 5eb9336 migration: Don't sync vcpus when migrating confidential guests
> af9b2fa migration: Stop non-aux vcpus before copying the last pages
> 2789368 migration: Stop VM after loading confidential RAM
> 4692252 migration: Load confidential guest RAM using migration helper
> e041f58 migration: Save confidential guest RAM using migration helper
> 328a888 migration: Introduce gpa_inside_migration_helper_shared_area
> b71be10 migration: Add helpers to load confidential RAM
> 32bdb2e migration: Add helpers to save confidential RAM
> 8d2fccb softmmu: Add pause_all_vcpus_except_aux
> ed10484 softmmu: Add cpu_synchronize_without_aux_post_init
> e68df04 softmmu: Don't sync aux vcpus in pre_loadvm
> 17bfe19 hw/i386: Set CPUState.aux=true for auxiliary vcpus
> 808eb76 cpu: Add boolean aux field to CPUState
> 34d94b2 hw/acpi: Don't include auxiliary vcpus in ACPI tables
> 2e9bc24 hw/i386: Mark auxiliary vcpus in possible_cpus
> 3d07b10 hw/boards: Add aux flag to CPUArchId
> 0e07c01 machine: Add auxcpus=N suboption to -smp
> 49124f3 kvm: add support to sync the page encryption state bitmap
> 47f202b linux-headers: Add definitions of KVM page encryption bitmap ioctls
> 
> === OUTPUT BEGIN ===
> 1/26 Checking commit 47f202b0bc8c (linux-headers: Add definitions of KVM page encryption bitmap ioctls)
> 2/26 Checking commit 49124f3bf03f (kvm: add support to sync the page encryption state bitmap)
> ERROR: use qemu_real_host_page_size instead of getpagesize()
> #51: FILE: accel/kvm/kvm-all.c:615:
> +    ram_addr_t pages = int128_get64(section->size) / getpagesize();
> 
> ERROR: use qemu_real_host_page_size instead of getpagesize()
> #171: FILE: include/exec/ram_addr.h:398:
> +    unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE;
> 
> WARNING: line over 80 characters
> #197: FILE: include/exec/ram_addr.h:424:
> +                qatomic_xchg(&blocks[DIRTY_MEMORY_ENCRYPTED][idx][offset], temp);
> 
> total: 2 errors, 1 warnings, 340 lines checked
> 
> Patch 2/26 has style problems, please review.  If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
> 
> 3/26 Checking commit 0e07c0168e00 (machine: Add auxcpus=N suboption to -smp)
> 4/26 Checking commit 3d07b103b36f (hw/boards: Add aux flag to CPUArchId)
> 5/26 Checking commit 2e9bc24b9064 (hw/i386: Mark auxiliary vcpus in possible_cpus)
> 6/26 Checking commit 34d94b2baa07 (hw/acpi: Don't include auxiliary vcpus in ACPI tables)
> 7/26 Checking commit 808eb7693543 (cpu: Add boolean aux field to CPUState)
> 8/26 Checking commit 17bfe1902081 (hw/i386: Set CPUState.aux=true for auxiliary vcpus)
> WARNING: line over 80 characters
> #26: FILE: hw/i386/x86.c:104:
> +void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, bool aux, Error **errp)
> 
> WARNING: line over 80 characters
> #58: FILE: include/hw/i386/x86.h:88:
> +void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, bool aux, Error **errp);
> 
> total: 0 errors, 2 warnings, 34 lines checked
> 
> Patch 8/26 has style problems, please review.  If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
> 9/26 Checking commit e68df046c12e (softmmu: Don't sync aux vcpus in pre_loadvm)
> 10/26 Checking commit ed104842e25d (softmmu: Add cpu_synchronize_without_aux_post_init)
> 11/26 Checking commit 8d2fccbd9cf9 (softmmu: Add pause_all_vcpus_except_aux)
> WARNING: Block comments use a leading /* on a separate line
> #88: FILE: softmmu/cpus.c:614:
> +    /* We need to drop the replay_lock so any vCPU threads woken up
> 
> total: 0 errors, 1 warnings, 78 lines checked
> 
> Patch 11/26 has style problems, please review.  If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
> 12/26 Checking commit 32bdb2e1c795 (migration: Add helpers to save confidential RAM)
> Use of uninitialized value $acpi_testexpected in string eq at ./scripts/checkpatch.pl line 1529.
> WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
> #28: 
> new file mode 100644
> 
> total: 0 errors, 1 warnings, 216 lines checked
> 
> Patch 12/26 has style problems, please review.  If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
> 13/26 Checking commit b71be10a582a (migration: Add helpers to load confidential RAM)
> 14/26 Checking commit 328a888fe8fd (migration: Introduce gpa_inside_migration_helper_shared_area)
> 15/26 Checking commit e041f580a1da (migration: Save confidential guest RAM using migration helper)
> 16/26 Checking commit 4692252e1994 (migration: Load confidential guest RAM using migration helper)
> WARNING: line over 80 characters
> #59: FILE: migration/ram.c:3990:
> +                error_report("%s: failed to get gpa for host %p", __func__, host);
> 
> total: 0 errors, 1 warnings, 43 lines checked
> 
> Patch 16/26 has style problems, please review.  If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
> 17/26 Checking commit 278936890c8d (migration: Stop VM after loading confidential RAM)
> WARNING: line over 80 characters
> #44: FILE: migration/confidential-ram.c:235:
> +static EndOfConfidentialRAMState end_of_confidential_ram_state = { .dummy = false };
> 
> total: 0 errors, 1 warnings, 67 lines checked
> 
> Patch 17/26 has style problems, please review.  If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
> 18/26 Checking commit af9b2fa4e956 (migration: Stop non-aux vcpus before copying the last pages)
> 19/26 Checking commit 5eb933666eda (migration: Don't sync vcpus when migrating confidential guests)
> 20/26 Checking commit 48db1fbc2c51 (migration: When starting target, don't sync auxiliary vcpus)
> 21/26 Checking commit af25d7bee8ac (migration: Call migration handler cleanup routines)
> 22/26 Checking commit 47e02a0e2441 (hw/isa/lpc_ich9: Allow updating an already-running VM)
> 23/26 Checking commit 6ca089420af2 (target/i386: Re-sync kvm-clock after confidential guest migration)
> 24/26 Checking commit 99d1efb7f73c (migration: Add start-migrate-incoming QMP command)
> 25/26 Checking commit 08f3c3b68478 (target/i386: SEV: Allow migration unless there are no aux vcpus)
> 26/26 Checking commit f283a35951da (docs: Add confidential guest live migration documentation)
> Use of uninitialized value $acpi_testexpected in string eq at ./scripts/checkpatch.pl line 1529.
> WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
> #20: 
> new file mode 100644
> 
> total: 0 errors, 1 warnings, 154 lines checked
> 
> Patch 26/26 has style problems, please review.  If any of these errors
> are false positives report them to the maintainer, see
> CHECKPATCH in MAINTAINERS.
> === OUTPUT END ===
> 
> Test command exited with code: 1
> 
> 
> The full log is available at
> http://patchew.org/logs/20210302204822.81901-1-dovmurik@linux.vnet.ibm.com/testing.checkpatch/?type=message.
> ---
> Email generated automatically by Patchew [https://patchew.org/].
> Please send your feedback to patchew-devel@redhat.com
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [RFC PATCH 00/26] Confidential guest live migration
  2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
                   ` (26 preceding siblings ...)
  2021-03-02 21:24 ` [RFC PATCH 00/26] Confidential guest live migration no-reply
@ 2021-03-04  9:10 ` Paolo Bonzini
  27 siblings, 0 replies; 30+ messages in thread
From: Paolo Bonzini @ 2021-03-04  9:10 UTC (permalink / raw)
  To: Dov Murik, qemu-devel
  Cc: Tom Lendacky, Ashish Kalra, Brijesh Singh, James Bottomley,
	Jon Grimm, Tobin Feldman-Fitzthum, Tobin Feldman-Fitzthum,
	Hubertus Franke

On 02/03/21 21:47, Dov Murik wrote:
> In order to allow OVMF to run the migration helper in parallel to the
> guest OS, we introduce the notion of auxiliary vcpus, which are usable
> for OVMF but are hidden from the guest OS.  These might have other
> future uses for in-guest operations/agents.

Hi Dov,

I think the helper approach to migration in general is great, but I'm 
not sure I agree with the concept of auxiliary vCPUs.  I would rather 
have a completely separate VM file descriptor that does not even go 
through the regular KVM run loop.  Patches were posted recently to the 
KVM mailing list to create secondary VMs sharing the encryption context 
(ASID) with a primary VM.

When starting the VM, the firmware would proceed with attestation as 
usual, detect it was running as a migration helper VM during the SEC 
phase, and divert execution to the migration helper instead of 
continuing with PEI.

The main advantage would be that the migration VM would not have to 
share the address space with the primary VM.  This would allow migrating 
encrypted RAM areas that are not visible to the primary VM, for example 
PCI BARs (those areas would be a problem for the kernel migration bitmap 
though; I'll remark on that separately on Ashish's KVM series).

The VM would not even have an interrupt controller, so that HLT exits to 
the host when it's done processing the mailbox.  This would make it much 
simpler to audit both the QEMU and the firmware sides.

Paolo

> In the target VM we need the migration handler running to receive
> incoming RAM pages; to achieve that, we boot the VM into OVMF with a
> special fw_cfg value that causes OVMF to not boot the guest OS; we then
> allow QEMU to receive an incoming migration by issuing a new
> start-migrate-incoming QMP command.
> 
> The confidential RAM migration requires checking whether a given guest
> RAM page is encrypted or not.  This is currently achieved using AMD's
> patches which track the encryption status of guest pages in KVM, using
> hypercalls from OVMF and guest Linux to report changes of such status.
> The QEMU side of these patches is included as the first two patches in
> this series.  The concrete implementation of this page encryption tracking
> is currently in flux in the KVM mailing list, but the underlying
> implementation doesn't affect our confidential RAM migration as long as
> it can check whether a given guest address is encrypted.
> 
> List of patches in this series:
> 
> 1-2: reposting AMD encrypted page bitmap support.
> 3-11: introduce the notion of auxiliary vcpus.
> 12-21: introduce the migration specifics.
> 22-23: fix devices issues when loading state into a live VM
> 24: introduce the start-migrate-incoming QMP command to switch the
> target into accepting the incoming migration.
> 25: remove SEV migration blocker
> 26: add documentation
> 
> 
> Brijesh Singh (1):
>    kvm: add support to sync the page encryption state bitmap
> 
> Dov Murik (21):
>    linux-headers: Add definitions of KVM page encryption bitmap ioctls
>    machine: Add auxcpus=N suboption to -smp
>    hw/boards: Add aux flag to CPUArchId
>    hw/i386: Mark auxiliary vcpus in possible_cpus
>    cpu: Add boolean aux field to CPUState
>    hw/i386: Set CPUState.aux=true for auxiliary vcpus
>    softmmu: Don't sync aux vcpus in pre_loadvm
>    softmmu: Add cpu_synchronize_without_aux_post_init
>    migration: Add helpers to save confidential RAM
>    migration: Add helpers to load confidential RAM
>    migration: Introduce gpa_inside_migration_helper_shared_area
>    migration: Save confidential guest RAM using migration helper
>    migration: Load confidential guest RAM using migration helper
>    migration: Stop VM after loading confidential RAM
>    migration: Don't sync vcpus when migrating confidential guests
>    migration: When starting target, don't sync auxiliary vcpus
>    hw/isa/lpc_ich9: Allow updating an already-running VM
>    target/i386: Re-sync kvm-clock after confidential guest migration
>    migration: Add start-migrate-incoming QMP command
>    target/i386: SEV: Allow migration unless there are no aux vcpus
>    docs: Add confidential guest live migration documentation
> 
> Tobin Feldman-Fitzthum (4):
>    hw/acpi: Don't include auxiliary vcpus in ACPI tables
>    softmmu: Add pause_all_vcpus_except_aux
>    migration: Stop non-aux vcpus before copying the last pages
>    migration: Call migration handler cleanup routines
> 
>   docs/confidential-guest-live-migration.rst | 142 ++++++++++++
>   docs/confidential-guest-support.txt        |   5 +
>   docs/index.rst                             |   1 +
>   qapi/migration.json                        |  26 +++
>   include/exec/ram_addr.h                    | 197 ++++++++++++++++
>   include/exec/ramblock.h                    |   3 +
>   include/exec/ramlist.h                     |   3 +-
>   include/hw/boards.h                        |   3 +
>   include/hw/core/cpu.h                      |   2 +
>   include/hw/i386/x86.h                      |   2 +-
>   include/sysemu/cpus.h                      |   2 +
>   linux-headers/linux/kvm.h                  |  13 ++
>   migration/confidential-ram.h               |  23 ++
>   accel/kvm/kvm-all.c                        |  43 ++++
>   hw/acpi/cpu.c                              |  10 +
>   hw/core/cpu.c                              |   1 +
>   hw/core/machine.c                          |   7 +
>   hw/i386/acpi-build.c                       |   5 +
>   hw/i386/acpi-common.c                      |   5 +
>   hw/i386/pc.c                               |   7 +
>   hw/i386/x86.c                              |  10 +-
>   hw/isa/lpc_ich9.c                          |   3 +-
>   migration/confidential-ram.c               | 258 +++++++++++++++++++++
>   migration/migration.c                      |  18 +-
>   migration/ram.c                            | 135 ++++++++++-
>   migration/savevm.c                         |  13 +-
>   softmmu/cpus.c                             |  68 +++++-
>   softmmu/runstate.c                         |   1 +
>   softmmu/vl.c                               |   3 +
>   target/i386/machine.c                      |   9 +
>   target/i386/sev.c                          |  25 +-
>   migration/meson.build                      |   6 +-
>   migration/trace-events                     |   4 +
>   33 files changed, 1027 insertions(+), 26 deletions(-)
>   create mode 100644 docs/confidential-guest-live-migration.rst
>   create mode 100644 migration/confidential-ram.h
>   create mode 100644 migration/confidential-ram.c
> 
> 
> base-commit: 00d8ba9e0d62ea1c7459c25aeabf9c8bb7659462
> 



^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2021-03-04  9:12 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-02 20:47 [RFC PATCH 00/26] Confidential guest live migration Dov Murik
2021-03-02 20:47 ` [RFC PATCH 01/26] linux-headers: Add definitions of KVM page encryption bitmap ioctls Dov Murik
2021-03-02 20:47 ` [RFC PATCH 02/26] kvm: add support to sync the page encryption state bitmap Dov Murik
2021-03-02 20:47 ` [RFC PATCH 03/26] machine: Add auxcpus=N suboption to -smp Dov Murik
2021-03-02 20:48 ` [RFC PATCH 04/26] hw/boards: Add aux flag to CPUArchId Dov Murik
2021-03-02 20:48 ` [RFC PATCH 05/26] hw/i386: Mark auxiliary vcpus in possible_cpus Dov Murik
2021-03-02 20:48 ` [RFC PATCH 06/26] hw/acpi: Don't include auxiliary vcpus in ACPI tables Dov Murik
2021-03-02 20:48 ` [RFC PATCH 07/26] cpu: Add boolean aux field to CPUState Dov Murik
2021-03-02 20:48 ` [RFC PATCH 08/26] hw/i386: Set CPUState.aux=true for auxiliary vcpus Dov Murik
2021-03-02 20:48 ` [RFC PATCH 09/26] softmmu: Don't sync aux vcpus in pre_loadvm Dov Murik
2021-03-02 20:48 ` [RFC PATCH 10/26] softmmu: Add cpu_synchronize_without_aux_post_init Dov Murik
2021-03-02 20:48 ` [RFC PATCH 11/26] softmmu: Add pause_all_vcpus_except_aux Dov Murik
2021-03-02 20:48 ` [RFC PATCH 12/26] migration: Add helpers to save confidential RAM Dov Murik
2021-03-02 20:48 ` [RFC PATCH 13/26] migration: Add helpers to load " Dov Murik
2021-03-02 20:48 ` [RFC PATCH 14/26] migration: Introduce gpa_inside_migration_helper_shared_area Dov Murik
2021-03-02 20:48 ` [RFC PATCH 15/26] migration: Save confidential guest RAM using migration helper Dov Murik
2021-03-02 20:48 ` [RFC PATCH 16/26] migration: Load " Dov Murik
2021-03-02 20:48 ` [RFC PATCH 17/26] migration: Stop VM after loading confidential RAM Dov Murik
2021-03-02 20:48 ` [RFC PATCH 18/26] migration: Stop non-aux vcpus before copying the last pages Dov Murik
2021-03-02 20:48 ` [RFC PATCH 19/26] migration: Don't sync vcpus when migrating confidential guests Dov Murik
2021-03-02 20:48 ` [RFC PATCH 20/26] migration: When starting target, don't sync auxiliary vcpus Dov Murik
2021-03-02 20:48 ` [RFC PATCH 21/26] migration: Call migration handler cleanup routines Dov Murik
2021-03-02 20:48 ` [RFC PATCH 22/26] hw/isa/lpc_ich9: Allow updating an already-running VM Dov Murik
2021-03-02 20:48 ` [RFC PATCH 23/26] target/i386: Re-sync kvm-clock after confidential guest migration Dov Murik
2021-03-02 20:48 ` [RFC PATCH 24/26] migration: Add start-migrate-incoming QMP command Dov Murik
2021-03-02 20:48 ` [RFC PATCH 25/26] target/i386: SEV: Allow migration unless there are no aux vcpus Dov Murik
2021-03-02 20:48 ` [RFC PATCH 26/26] docs: Add confidential guest live migration documentation Dov Murik
2021-03-02 21:24 ` [RFC PATCH 00/26] Confidential guest live migration no-reply
2021-03-03  8:08   ` Dov Murik
2021-03-04  9:10 ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).