453 lines
14 KiB
Diff
453 lines
14 KiB
Diff
|
|
From 13bd2629b78f528b0b4684a643f59d30b7274aa8 Mon Sep 17 00:00:00 2001
|
||
|
|
From: jiangxin <jiangxin@hygon.cn>
|
||
|
|
Date: Fri, 17 Jun 2022 09:37:56 +0800
|
||
|
|
Subject: [PATCH] target/i386: csv: Add support to migrate the outgoing page
|
||
|
|
for CSV3 guest
|
||
|
|
|
||
|
|
The csv3_send_encrypt_data() provides the method to encrypt the
|
||
|
|
guest's private pages during migration. The routine is similar to
|
||
|
|
CSV2's. Usually, it starts with a SEND_START command to create the
|
||
|
|
migration context. Then SEND_ENCRYPT_DATA command is performed to
|
||
|
|
encrypt guest pages. After migration is completed, a SEND_FINISH
|
||
|
|
command is performed to the firmware.
|
||
|
|
|
||
|
|
Signed-off-by: Jiang Xin <jiangxin@hygon.cn>
|
||
|
|
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||
|
|
---
|
||
|
|
migration/ram.c | 87 +++++++++++++++++++
|
||
|
|
target/i386/csv.c | 182 +++++++++++++++++++++++++++++++++++++++
|
||
|
|
target/i386/csv.h | 22 +++++
|
||
|
|
target/i386/sev.c | 14 ++-
|
||
|
|
target/i386/sev.h | 1 +
|
||
|
|
target/i386/trace-events | 1 +
|
||
|
|
6 files changed, 306 insertions(+), 1 deletion(-)
|
||
|
|
|
||
|
|
diff --git a/migration/ram.c b/migration/ram.c
|
||
|
|
index 1377b9eb37..1f9348fd06 100644
|
||
|
|
--- a/migration/ram.c
|
||
|
|
+++ b/migration/ram.c
|
||
|
|
@@ -2480,6 +2480,90 @@ ram_save_encrypted_pages_in_batch(RAMState *rs, PageSearchStatus *pss)
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
+/**
|
||
|
|
+ * ram_save_csv3_pages - send the given csv3 VM pages to the stream
|
||
|
|
+ */
|
||
|
|
+static int ram_save_csv3_pages(RAMState *rs, PageSearchStatus *pss)
|
||
|
|
+{
|
||
|
|
+ bool page_dirty;
|
||
|
|
+ int ret;
|
||
|
|
+ int tmppages, pages = 0;
|
||
|
|
+ uint8_t *p;
|
||
|
|
+ uint32_t host_len = 0;
|
||
|
|
+ uint64_t bytes_xmit = 0;
|
||
|
|
+ RAMBlock *block = pss->block;
|
||
|
|
+ ram_addr_t offset = 0;
|
||
|
|
+ hwaddr paddr = RAM_ADDR_INVALID;
|
||
|
|
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||
|
|
+ ConfidentialGuestSupportClass *cgs_class =
|
||
|
|
+ (ConfidentialGuestSupportClass *) object_get_class(OBJECT(ms->cgs));
|
||
|
|
+ struct ConfidentialGuestMemoryEncryptionOps *ops =
|
||
|
|
+ cgs_class->memory_encryption_ops;
|
||
|
|
+
|
||
|
|
+ if (!kvm_csv3_enabled())
|
||
|
|
+ return 0;
|
||
|
|
+
|
||
|
|
+ do {
|
||
|
|
+ page_dirty = migration_bitmap_clear_dirty(rs, block, pss->page);
|
||
|
|
+
|
||
|
|
+ /* Check the pages is dirty and if it is send it */
|
||
|
|
+ if (page_dirty) {
|
||
|
|
+ ret = kvm_physical_memory_addr_from_host(kvm_state,
|
||
|
|
+ block->host + (pss->page << TARGET_PAGE_BITS), &paddr);
|
||
|
|
+ /* Process ROM or MMIO */
|
||
|
|
+ if (paddr == RAM_ADDR_INVALID ||
|
||
|
|
+ memory_region_is_rom(block->mr)) {
|
||
|
|
+ tmppages = migration_ops->ram_save_target_page(rs, pss);
|
||
|
|
+ } else {
|
||
|
|
+ /* Caculate the offset and host virtual address of the page */
|
||
|
|
+ offset = pss->page << TARGET_PAGE_BITS;
|
||
|
|
+ p = block->host + offset;
|
||
|
|
+
|
||
|
|
+ if (ops->queue_outgoing_page(p, TARGET_PAGE_SIZE, offset))
|
||
|
|
+ return -1;
|
||
|
|
+
|
||
|
|
+ tmppages = 1;
|
||
|
|
+ host_len += TARGET_PAGE_SIZE;
|
||
|
|
+
|
||
|
|
+ stat64_add(&mig_stats.normal_pages, 1);
|
||
|
|
+ }
|
||
|
|
+ } else {
|
||
|
|
+ tmppages = 0;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (tmppages >= 0) {
|
||
|
|
+ pages += tmppages;
|
||
|
|
+ } else {
|
||
|
|
+ return tmppages;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ pss_find_next_dirty(pss);
|
||
|
|
+ } while (offset_in_ramblock(block,
|
||
|
|
+ ((ram_addr_t)pss->page) << TARGET_PAGE_BITS) &&
|
||
|
|
+ host_len < CSV3_OUTGOING_PAGE_WINDOW_SIZE);
|
||
|
|
+
|
||
|
|
+ /* Check if there are any queued pages */
|
||
|
|
+ if (host_len != 0) {
|
||
|
|
+ /* Always set offset as 0 for csv3. */
|
||
|
|
+ ram_transferred_add(save_page_header(pss, pss->pss_channel,
|
||
|
|
+ block, 0 | RAM_SAVE_FLAG_ENCRYPTED_DATA));
|
||
|
|
+
|
||
|
|
+ qemu_put_be32(pss->pss_channel, RAM_SAVE_ENCRYPTED_PAGE);
|
||
|
|
+ ram_transferred_add(4);
|
||
|
|
+ /* Process the queued pages in batch */
|
||
|
|
+ ret = ops->save_queued_outgoing_pages(pss->pss_channel, &bytes_xmit);
|
||
|
|
+ if (ret) {
|
||
|
|
+ return -1;
|
||
|
|
+ }
|
||
|
|
+ ram_transferred_add(bytes_xmit);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ /* The offset we leave with is the last one we looked at */
|
||
|
|
+ pss->page--;
|
||
|
|
+
|
||
|
|
+ return pages;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/**
|
||
|
|
* ram_save_host_page: save a whole host page
|
||
|
|
*
|
||
|
|
@@ -2515,6 +2599,9 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss)
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
+ if (kvm_csv3_enabled())
|
||
|
|
+ return ram_save_csv3_pages(rs, pss);
|
||
|
|
+
|
||
|
|
#ifdef CONFIG_HYGON_CSV_MIG_ACCEL
|
||
|
|
/*
|
||
|
|
* If command_batch function is enabled and memory encryption is enabled
|
||
|
|
diff --git a/target/i386/csv.c b/target/i386/csv.c
|
||
|
|
index e4706efa27..22e709a95c 100644
|
||
|
|
--- a/target/i386/csv.c
|
||
|
|
+++ b/target/i386/csv.c
|
||
|
|
@@ -16,8 +16,13 @@
|
||
|
|
#include "qapi/error.h"
|
||
|
|
#include "sysemu/kvm.h"
|
||
|
|
#include "exec/address-spaces.h"
|
||
|
|
+#include "migration/blocker.h"
|
||
|
|
+#include "migration/qemu-file.h"
|
||
|
|
+#include "migration/misc.h"
|
||
|
|
+#include "monitor/monitor.h"
|
||
|
|
|
||
|
|
#include <linux/kvm.h>
|
||
|
|
+#include <linux/psp-sev.h>
|
||
|
|
|
||
|
|
#ifdef CONFIG_NUMA
|
||
|
|
#include <numaif.h>
|
||
|
|
@@ -30,6 +35,19 @@
|
||
|
|
|
||
|
|
bool csv_kvm_cpu_reset_inhibit;
|
||
|
|
|
||
|
|
+struct ConfidentialGuestMemoryEncryptionOps csv3_memory_encryption_ops = {
|
||
|
|
+ .save_setup = sev_save_setup,
|
||
|
|
+ .save_outgoing_page = NULL,
|
||
|
|
+ .is_gfn_in_unshared_region = NULL,
|
||
|
|
+ .save_outgoing_shared_regions_list = sev_save_outgoing_shared_regions_list,
|
||
|
|
+ .load_incoming_shared_regions_list = sev_load_incoming_shared_regions_list,
|
||
|
|
+ .queue_outgoing_page = csv3_queue_outgoing_page,
|
||
|
|
+ .save_queued_outgoing_pages = csv3_save_queued_outgoing_pages,
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
+#define CSV3_OUTGOING_PAGE_NUM \
|
||
|
|
+ (CSV3_OUTGOING_PAGE_WINDOW_SIZE / TARGET_PAGE_SIZE)
|
||
|
|
+
|
||
|
|
Csv3GuestState csv3_guest = { 0 };
|
||
|
|
|
||
|
|
int
|
||
|
|
@@ -70,6 +88,7 @@ csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops)
|
||
|
|
csv3_guest.fw_error_to_str = ops->fw_error_to_str;
|
||
|
|
QTAILQ_INIT(&csv3_guest.dma_map_regions_list);
|
||
|
|
qemu_mutex_init(&csv3_guest.dma_map_regions_list_mutex);
|
||
|
|
+ csv3_guest.sev_send_start = ops->sev_send_start;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
@@ -301,3 +320,166 @@ end:
|
||
|
|
qemu_mutex_unlock(&s->dma_map_regions_list_mutex);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+static inline hwaddr csv3_hva_to_gfn(uint8_t *ptr)
|
||
|
|
+{
|
||
|
|
+ ram_addr_t offset = RAM_ADDR_INVALID;
|
||
|
|
+
|
||
|
|
+ kvm_physical_memory_addr_from_host(kvm_state, ptr, &offset);
|
||
|
|
+
|
||
|
|
+ return offset >> TARGET_PAGE_BITS;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+static int
|
||
|
|
+csv3_send_start(QEMUFile *f, uint64_t *bytes_sent)
|
||
|
|
+{
|
||
|
|
+ if (csv3_guest.sev_send_start)
|
||
|
|
+ return csv3_guest.sev_send_start(f, bytes_sent);
|
||
|
|
+ else
|
||
|
|
+ return -1;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+static int
|
||
|
|
+csv3_send_get_packet_len(int *fw_err)
|
||
|
|
+{
|
||
|
|
+ int ret;
|
||
|
|
+ struct kvm_csv3_send_encrypt_data update = {0};
|
||
|
|
+
|
||
|
|
+ update.hdr_len = 0;
|
||
|
|
+ update.trans_len = 0;
|
||
|
|
+ ret = csv3_ioctl(KVM_CSV3_SEND_ENCRYPT_DATA, &update, fw_err);
|
||
|
|
+ if (*fw_err != SEV_RET_INVALID_LEN) {
|
||
|
|
+ error_report("%s: failed to get session length ret=%d fw_error=%d '%s'",
|
||
|
|
+ __func__, ret, *fw_err, fw_error_to_str(*fw_err));
|
||
|
|
+ ret = 0;
|
||
|
|
+ goto err;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (update.hdr_len <= INT_MAX)
|
||
|
|
+ ret = update.hdr_len;
|
||
|
|
+ else
|
||
|
|
+ ret = 0;
|
||
|
|
+
|
||
|
|
+err:
|
||
|
|
+ return ret;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+static int
|
||
|
|
+csv3_send_encrypt_data(Csv3GuestState *s, QEMUFile *f,
|
||
|
|
+ uint8_t *ptr, uint32_t size, uint64_t *bytes_sent)
|
||
|
|
+{
|
||
|
|
+ int ret, fw_error = 0;
|
||
|
|
+ guchar *trans;
|
||
|
|
+ uint32_t guest_addr_entry_num;
|
||
|
|
+ uint32_t i;
|
||
|
|
+ struct kvm_csv3_send_encrypt_data update = { };
|
||
|
|
+
|
||
|
|
+ /*
|
||
|
|
+ * If this is first call then query the packet header bytes and allocate
|
||
|
|
+ * the packet buffer.
|
||
|
|
+ */
|
||
|
|
+ if (!s->send_packet_hdr) {
|
||
|
|
+ s->send_packet_hdr_len = csv3_send_get_packet_len(&fw_error);
|
||
|
|
+ if (s->send_packet_hdr_len < 1) {
|
||
|
|
+ error_report("%s: SEND_UPDATE fw_error=%d '%s'",
|
||
|
|
+ __func__, fw_error, fw_error_to_str(fw_error));
|
||
|
|
+ return 1;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ s->send_packet_hdr = g_new(gchar, s->send_packet_hdr_len);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (!s->guest_addr_len || !s->guest_addr_data) {
|
||
|
|
+ error_report("%s: invalid host address or size", __func__);
|
||
|
|
+ return 1;
|
||
|
|
+ } else {
|
||
|
|
+ guest_addr_entry_num = s->guest_addr_len / sizeof(struct guest_addr_entry);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ /* allocate transport buffer */
|
||
|
|
+ trans = g_new(guchar, guest_addr_entry_num * TARGET_PAGE_SIZE);
|
||
|
|
+
|
||
|
|
+ update.hdr_uaddr = (uintptr_t)s->send_packet_hdr;
|
||
|
|
+ update.hdr_len = s->send_packet_hdr_len;
|
||
|
|
+ update.guest_addr_data = (uintptr_t)s->guest_addr_data;
|
||
|
|
+ update.guest_addr_len = s->guest_addr_len;
|
||
|
|
+ update.trans_uaddr = (uintptr_t)trans;
|
||
|
|
+ update.trans_len = guest_addr_entry_num * TARGET_PAGE_SIZE;
|
||
|
|
+
|
||
|
|
+ trace_kvm_csv3_send_encrypt_data(trans, update.trans_len);
|
||
|
|
+
|
||
|
|
+ ret = csv3_ioctl(KVM_CSV3_SEND_ENCRYPT_DATA, &update, &fw_error);
|
||
|
|
+ if (ret) {
|
||
|
|
+ error_report("%s: SEND_ENCRYPT_DATA ret=%d fw_error=%d '%s'",
|
||
|
|
+ __func__, ret, fw_error, fw_error_to_str(fw_error));
|
||
|
|
+ goto err;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ for (i = 0; i < guest_addr_entry_num; i++) {
|
||
|
|
+ if (s->guest_addr_data[i].share)
|
||
|
|
+ memcpy(trans + i * TARGET_PAGE_SIZE, (guchar *)s->guest_hva_data[i].hva,
|
||
|
|
+ TARGET_PAGE_SIZE);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ qemu_put_be32(f, update.hdr_len);
|
||
|
|
+ qemu_put_buffer(f, (uint8_t *)update.hdr_uaddr, update.hdr_len);
|
||
|
|
+ *bytes_sent += 4 + update.hdr_len;
|
||
|
|
+
|
||
|
|
+ qemu_put_be32(f, update.guest_addr_len);
|
||
|
|
+ qemu_put_buffer(f, (uint8_t *)update.guest_addr_data, update.guest_addr_len);
|
||
|
|
+ *bytes_sent += 4 + update.guest_addr_len;
|
||
|
|
+
|
||
|
|
+ qemu_put_be32(f, update.trans_len);
|
||
|
|
+ qemu_put_buffer(f, (uint8_t *)update.trans_uaddr, update.trans_len);
|
||
|
|
+ *bytes_sent += (4 + update.trans_len);
|
||
|
|
+
|
||
|
|
+err:
|
||
|
|
+ s->guest_addr_len = 0;
|
||
|
|
+ g_free(trans);
|
||
|
|
+ return ret;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+int
|
||
|
|
+csv3_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr)
|
||
|
|
+{
|
||
|
|
+ Csv3GuestState *s = &csv3_guest;
|
||
|
|
+ uint32_t i = 0;
|
||
|
|
+
|
||
|
|
+ if (!s->guest_addr_data) {
|
||
|
|
+ s->guest_hva_data = g_new0(struct guest_hva_entry, CSV3_OUTGOING_PAGE_NUM);
|
||
|
|
+ s->guest_addr_data = g_new0(struct guest_addr_entry, CSV3_OUTGOING_PAGE_NUM);
|
||
|
|
+ s->guest_addr_len = 0;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (s->guest_addr_len >= sizeof(struct guest_addr_entry) * CSV3_OUTGOING_PAGE_NUM) {
|
||
|
|
+ error_report("Failed to queue outgoing page");
|
||
|
|
+ return 1;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ i = s->guest_addr_len / sizeof(struct guest_addr_entry);
|
||
|
|
+ s->guest_hva_data[i].hva = (uintptr_t)ptr;
|
||
|
|
+ s->guest_addr_data[i].share = 0;
|
||
|
|
+ s->guest_addr_data[i].reserved = 0;
|
||
|
|
+ s->guest_addr_data[i].gfn = csv3_hva_to_gfn(ptr);
|
||
|
|
+ s->guest_addr_len += sizeof(struct guest_addr_entry);
|
||
|
|
+
|
||
|
|
+ return 0;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+int
|
||
|
|
+csv3_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent)
|
||
|
|
+{
|
||
|
|
+ Csv3GuestState *s = &csv3_guest;
|
||
|
|
+
|
||
|
|
+ /*
|
||
|
|
+ * If this is a first buffer then create outgoing encryption context
|
||
|
|
+ * and write our PDH, policy and session data.
|
||
|
|
+ */
|
||
|
|
+ if (!csv3_check_state(SEV_STATE_SEND_UPDATE) &&
|
||
|
|
+ csv3_send_start(f, bytes_sent)) {
|
||
|
|
+ error_report("Failed to create outgoing context");
|
||
|
|
+ return 1;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return csv3_send_encrypt_data(s, f, NULL, 0, bytes_sent);
|
||
|
|
+}
|
||
|
|
diff --git a/target/i386/csv.h b/target/i386/csv.h
|
||
|
|
index 12733341b3..12c1b22659 100644
|
||
|
|
--- a/target/i386/csv.h
|
||
|
|
+++ b/target/i386/csv.h
|
||
|
|
@@ -81,6 +81,18 @@ struct dma_map_region {
|
||
|
|
QTAILQ_ENTRY(dma_map_region) list;
|
||
|
|
};
|
||
|
|
|
||
|
|
+#define CSV3_OUTGOING_PAGE_WINDOW_SIZE (512 * TARGET_PAGE_SIZE)
|
||
|
|
+
|
||
|
|
+struct guest_addr_entry {
|
||
|
|
+ uint64_t share: 1;
|
||
|
|
+ uint64_t reserved: 11;
|
||
|
|
+ uint64_t gfn: 52;
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
+struct guest_hva_entry {
|
||
|
|
+ uint64_t hva;
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
struct Csv3GuestState {
|
||
|
|
uint32_t policy;
|
||
|
|
int sev_fd;
|
||
|
|
@@ -89,11 +101,19 @@ struct Csv3GuestState {
|
||
|
|
const char *(*fw_error_to_str)(int code);
|
||
|
|
QTAILQ_HEAD(, dma_map_region) dma_map_regions_list;
|
||
|
|
QemuMutex dma_map_regions_list_mutex;
|
||
|
|
+ gchar *send_packet_hdr;
|
||
|
|
+ size_t send_packet_hdr_len;
|
||
|
|
+ struct guest_hva_entry *guest_hva_data;
|
||
|
|
+ struct guest_addr_entry *guest_addr_data;
|
||
|
|
+ size_t guest_addr_len;
|
||
|
|
+
|
||
|
|
+ int (*sev_send_start)(QEMUFile *f, uint64_t *bytes_sent);
|
||
|
|
};
|
||
|
|
|
||
|
|
typedef struct Csv3GuestState Csv3GuestState;
|
||
|
|
|
||
|
|
extern struct Csv3GuestState csv3_guest;
|
||
|
|
+extern struct ConfidentialGuestMemoryEncryptionOps csv3_memory_encryption_ops;
|
||
|
|
extern int csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops);
|
||
|
|
extern int csv3_launch_encrypt_vmcb(void);
|
||
|
|
|
||
|
|
@@ -101,5 +121,7 @@ int csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp);
|
||
|
|
|
||
|
|
int csv3_shared_region_dma_map(uint64_t start, uint64_t end);
|
||
|
|
void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end);
|
||
|
|
+int csv3_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr);
|
||
|
|
+int csv3_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent);
|
||
|
|
|
||
|
|
#endif
|
||
|
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||
|
|
index 0012a5efb0..5a96b0b452 100644
|
||
|
|
--- a/target/i386/sev.c
|
||
|
|
+++ b/target/i386/sev.c
|
||
|
|
@@ -1270,7 +1270,11 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||
|
|
qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
|
||
|
|
migration_add_notifier(&sev_migration_state, sev_migration_state_notifier);
|
||
|
|
|
||
|
|
- cgs_class->memory_encryption_ops = &sev_memory_encryption_ops;
|
||
|
|
+ if (csv3_enabled()) {
|
||
|
|
+ cgs_class->memory_encryption_ops = &csv3_memory_encryption_ops;
|
||
|
|
+ } else {
|
||
|
|
+ cgs_class->memory_encryption_ops = &sev_memory_encryption_ops;
|
||
|
|
+ }
|
||
|
|
QTAILQ_INIT(&sev->shared_regions_list);
|
||
|
|
|
||
|
|
/* Determine whether support MSR_AMD64_SEV_ES_GHCB */
|
||
|
|
@@ -2654,9 +2658,17 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
+static int _sev_send_start(QEMUFile *f, uint64_t *bytes_sent)
|
||
|
|
+{
|
||
|
|
+ SevGuestState *s = sev_guest;
|
||
|
|
+
|
||
|
|
+ return sev_send_start(s, f, bytes_sent);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
struct sev_ops sev_ops = {
|
||
|
|
.sev_ioctl = sev_ioctl,
|
||
|
|
.fw_error_to_str = fw_error_to_str,
|
||
|
|
+ .sev_send_start = _sev_send_start,
|
||
|
|
};
|
||
|
|
|
||
|
|
static void
|
||
|
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||
|
|
index e91431e0f7..8ccef22a95 100644
|
||
|
|
--- a/target/i386/sev.h
|
||
|
|
+++ b/target/i386/sev.h
|
||
|
|
@@ -83,6 +83,7 @@ extern bool sev_kvm_has_msr_ghcb;
|
||
|
|
struct sev_ops {
|
||
|
|
int (*sev_ioctl)(int fd, int cmd, void *data, int *error);
|
||
|
|
const char *(*fw_error_to_str)(int code);
|
||
|
|
+ int (*sev_send_start)(QEMUFile *f, uint64_t *bytes_sent);
|
||
|
|
};
|
||
|
|
|
||
|
|
extern struct sev_ops sev_ops;
|
||
|
|
diff --git a/target/i386/trace-events b/target/i386/trace-events
|
||
|
|
index 34c205ffda..a4a58b12a1 100644
|
||
|
|
--- a/target/i386/trace-events
|
||
|
|
+++ b/target/i386/trace-events
|
||
|
|
@@ -22,3 +22,4 @@ kvm_sev_receive_update_vmsa(uint32_t cpu_id, uint32_t cpu_index, void *src, int
|
||
|
|
|
||
|
|
# csv.c
|
||
|
|
kvm_csv3_launch_encrypt_data(uint64_t gpa, void *addr, uint64_t len) "gpa 0x%" PRIx64 "addr %p len 0x%" PRIx64
|
||
|
|
+kvm_csv3_send_encrypt_data(void *dst, int len) "trans %p len %d"
|
||
|
|
--
|
||
|
|
2.41.0.windows.1
|
||
|
|
|