Encrypted VMs have concept of private and shared memory. The private memory is encrypted with the guest-specific key, while shared memory may be encrypted with hyperivosr key. The guest OS uses a hypercall to notify the page encryption state to the hypervisor. The hypervisor maintain a bitmap of page encryption state. This bitmap should be migrated to ensure that target machine can function correctly.
Signed-off-by: Brijesh Singh <brijesh.si...@amd.com> --- accel/kvm/kvm-all.c | 37 +++++++++++++++++++++++++++++++++++++ accel/kvm/sev-stub.c | 11 +++++++++++ accel/stubs/kvm-stub.c | 10 ++++++++++ include/sysemu/kvm.h | 13 +++++++++++++ include/sysemu/sev.h | 3 +++ 5 files changed, 74 insertions(+) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 7f94dba6f9..442b1af36e 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -114,6 +114,9 @@ struct KVMState uint8_t *ptr, uint32_t sz, uint64_t *bytes_sent); int (*memcrypt_load_incoming_page)(void *ehandle, QEMUFile *f, uint8_t *ptr); + int (*memcrypt_load_incoming_page_enc_bitmap)(void *ehandle, QEMUFile *f); + int (*memcrypt_save_outgoing_page_enc_bitmap)(void *ehandle, QEMUFile *f, + uint64_t start, uint64_t length); }; KVMState *kvm_state; @@ -192,6 +195,40 @@ int kvm_memcrypt_load_incoming_page(QEMUFile *f, uint8_t *ptr) return 1; } +int kvm_memcrypt_load_incoming_page_enc_bitmap(QEMUFile *f) +{ + if (kvm_state->memcrypt_handle && + kvm_state->memcrypt_load_incoming_page_enc_bitmap) { + return kvm_state->memcrypt_load_incoming_page_enc_bitmap( + kvm_state->memcrypt_handle, f); + } + + return 1; +} + +int kvm_memcrypt_save_outgoing_page_enc_bitmap(QEMUFile *f) +{ + KVMMemoryListener *kml = &kvm_state->memory_listener; + KVMState *s = kvm_state; + int ret = 1, i; + + if (s->memcrypt_handle && + s->memcrypt_save_outgoing_page_enc_bitmap) { + + /* iterate through all the registered slots and send the bitmap */ + for (i = 0; i < s->nr_slots; i++) { + KVMSlot *mem = &kml->slots[i]; + ret = s->memcrypt_save_outgoing_page_enc_bitmap(s->memcrypt_handle, + f, mem->start_addr, mem->memory_size); + if (ret) { + return 1; + } + } + } + + return ret; +} + static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml) { KVMState *s = kvm_state; diff --git a/accel/kvm/sev-stub.c b/accel/kvm/sev-stub.c index c12a8e005e..7acd7211e6 100644 --- a/accel/kvm/sev-stub.c +++ b/accel/kvm/sev-stub.c @@ -35,3 +35,14 @@ int sev_load_incoming_page(void *handle, QEMUFile *f, uint8_t *ptr) { return 1; } + +int sev_load_incoming_page_enc_bitmap(void *handle, QEMUFile *f) +{ + return 1; +} + +int sev_save_outgoing_page_enc_bitmap(void *handle, QEMUFile *f, + uint64_t start, uint64_t length) +{ + return 1; +} diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index e14b879531..ae607787e7 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -125,6 +125,16 @@ int kvm_memcrypt_load_incoming_page(QEMUFile *f, uint8_t *ptr) return 1; } +int kvm_memcrypt_load_incoming_page_enc_bitmap(QEMUFile *f) +{ + return 1; +} + +int kvm_memcrypt_save_outgoing_page_enc_bitmap(QEMUFile *f) +{ + return 1; +} + #ifndef CONFIG_USER_ONLY int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index bb6bcc143c..8aa06b4462 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -260,6 +260,19 @@ int kvm_memcrypt_save_outgoing_page(QEMUFile *f, uint8_t *ptr, uint32_t size, */ int kvm_memcrypt_load_incoming_page(QEMUFile *f, uint8_t *ptr); +/** + * kvm_memcrypt_load_incoming_page_enc_bitmap: read the page encryption bitmap + * from the socket and pass it to the hypervisor. + */ +int kvm_memcrypt_load_incoming_page_enc_bitmap(QEMUFile *f); + +/** + * kvm_memcrypt_save_outgoing_page_enc_bitmap: write the page encryption bitmap + * on socket. + */ +int kvm_memcrypt_save_outgoing_page_enc_bitmap(QEMUFile *f); + + #ifdef NEED_CPU_H #include "cpu.h" diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h index 752a71b1c0..e08886ca33 100644 --- a/include/sysemu/sev.h +++ b/include/sysemu/sev.h @@ -21,4 +21,7 @@ int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len); int sev_save_outgoing_page(void *handle, QEMUFile *f, uint8_t *ptr, uint32_t size, uint64_t *bytes_sent); int sev_load_incoming_page(void *handle, QEMUFile *f, uint8_t *ptr); +int sev_load_incoming_page_enc_bitmap(void *handle, QEMUFile *f); +int sev_save_outgoing_page_enc_bitmap(void *handle, QEMUFile *f, + uint64_t start, uint64_t length); #endif -- 2.17.1