During machine creation we encrypted the guest bios image, the LAUNCH_MEASURE command can be used to retrieve the measurement of the encrypted memory region. Emit the SEV_MEASUREMENT event so that libvirt can grab the measurement value as soon as we are done with creating the encrypted machine. Cc: Daniel P. Berrange <berrange@xxxxxxxxxx> Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx> Cc: kvm@xxxxxxxxxxxxxxx Signed-off-by: Brijesh Singh <brijesh.singh@xxxxxxx> --- accel/kvm/sev.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sysemu/sev.h | 1 + 2 files changed, 59 insertions(+) diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c index 83fc950bd3ac..c0eea371fa06 100644 --- a/accel/kvm/sev.c +++ b/accel/kvm/sev.c @@ -18,6 +18,7 @@ #include "sysemu/kvm.h" #include "sysemu/sev.h" #include "sysemu/sysemu.h" +#include "qapi-event.h" #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */ #define DEFAULT_SEV_DEVICE "/dev/sev" @@ -32,6 +33,7 @@ #endif static int sev_fd; +static SEVState *sev_state; #define SEV_FW_MAX_ERROR 0x17 @@ -399,6 +401,59 @@ err: return ret; } +static void +sev_launch_get_measure(Notifier *notifier, void *unused) +{ + int ret, error; + guchar *data; + SEVState *s = sev_state; + struct kvm_sev_launch_measure *measurement; + + measurement = g_malloc0(sizeof(*measurement)); + if (!measurement) { + return; + } + + /* query the measurement blob length */ + ret = sev_ioctl(KVM_SEV_LAUNCH_MEASURE, measurement, &error); + if (!measurement->len) { + error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", + __func__, ret, error, fw_error_to_str(errno)); + goto free_measurement; + } + + s->cur_state = SEV_STATE_SECRET; + + data = g_malloc(measurement->len); + if (s->measurement) { + goto free_data; + } + + measurement->uaddr = (unsigned long)data; + + /* get the measurement blob */ + ret = sev_ioctl(KVM_SEV_LAUNCH_MEASURE, measurement, &error); + if (ret) { + error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", + __func__, ret, error, fw_error_to_str(errno)); + goto free_data; + } + + s->measurement = g_base64_encode(data, measurement->len); + + DPRINTF("SEV: MEASUREMENT: %s\n", s->measurement); + qapi_event_send_sev_measurement(s->measurement, &error_abort); + +free_data: + g_free(data); +free_measurement: + g_free(measurement); +} + +static Notifier sev_machine_done_notify = { + .notify = sev_launch_get_measure, +}; + void * sev_guest_init(const char *id) { @@ -441,6 +496,9 @@ sev_guest_init(const char *id) } ram_block_notifier_add(&sev_ram_notifier); + qemu_add_machine_init_done_notifier(&sev_machine_done_notify); + + sev_state = s; return s; err: diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h index b1ea3f805290..3af945935b60 100644 --- a/include/sysemu/sev.h +++ b/include/sysemu/sev.h @@ -64,6 +64,7 @@ enum { struct SEVState { QSevGuestInfo *sev_info; int cur_state; + gchar *measurement; }; typedef struct SEVState SEVState; -- 2.9.5