The SEV LAUNCH_FINISH command is used for finalizing the guest launch process. The commad returned a measurement value that can be handed to the guest owner to validate the guest before vmrun.
For more information see [1], section 6.3 [1] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Spec.pdf The following KVM RFC patches defines and implements this command http://marc.info/?l=kvm&m=147190852423972&w=2 http://marc.info/?l=kvm&m=147190856623987&w=2 Signed-off-by: Brijesh Singh <brijesh.si...@amd.com> --- include/sysemu/sev.h | 17 +++++++++++++- sev.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h index b58a9d7..ab03c5d 100644 --- a/include/sysemu/sev.h +++ b/include/sysemu/sev.h @@ -39,5 +39,20 @@ int kvm_sev_guest_start(void); */ int kvm_sev_guest_update(uint8_t *address, uint32_t len); -#endif +/** + * kvm_sev_guest_finish - finialize launching guest into SEV mode. + */ +int kvm_sev_guest_finish(void); +/** + * kvm_sev_guest_get_measurement - get measurement from launch finish command. + * + * @measurement: measurement values returned from the SEV. Its 32-byte value + * and buffer must be allocated by caller. + * + * Returns: 0 on success and @measurement will contain the value, or + * 1 on failure. + */ +int kvm_sev_guest_measurement(uint8_t *measurement); + +#endif diff --git a/sev.c b/sev.c index a451dc0..055ed83 100644 --- a/sev.c +++ b/sev.c @@ -48,6 +48,7 @@ enum { SEV_LAUNCH_START = 0x1, + SEV_LAUNCH_FINISH, }; struct SEVInfo { @@ -326,6 +327,32 @@ static int sev_launch_update(uint8_t *addr, uint32_t len) return 0; } +static int sev_launch_finish(void) +{ + int i, ret; + SEVInfo *s = sev_info; + struct kvm_sev_issue_cmd input; + struct kvm_sev_launch_finish *finish = s->launch_finish; + + input.cmd = KVM_SEV_LAUNCH_FINISH; + input.opaque = (__u64)finish; + ret = kvm_vm_ioctl(kvm_state, KVM_SEV_ISSUE_CMD, &input); + if (ret) { + fprintf(stderr, "SEV: launch_finish failed ret=%d(%#010x)\n", + ret, input.ret_code); + exit(EXIT_FAILURE); + } + + DPRINTF("SEV: LAUNCH finish measurement=0x"); + for (i = 0; i < 32; i++) { + DPRINTF("%02x", finish->measurement[i]); + } + DPRINTF("\n"); + + s->state = SEV_LAUNCH_FINISH; + return 0; +} + int kvm_sev_guest_start(void) { SEVInfo *s = sev_info; @@ -371,3 +398,37 @@ int kvm_sev_guest_update(uint8_t *addr, uint32_t len) return 1; } + +int kvm_sev_guest_finish(void) +{ + SEVInfo *s = sev_info; + + if (!s) { + return 1; + } + + if (s->state == SEV_LAUNCH_START) { + return sev_launch_finish(); + } + + return 1; +} + +int kvm_sev_guest_measurement(uint8_t *out) +{ + SEVInfo *s = sev_info; + struct kvm_sev_launch_finish *finish = s->launch_finish; + + if (!s) { + return 1; + } + + if (s->type == UNENCRYPTED_GUEST && + s->state == SEV_LAUNCH_FINISH) { + memcpy(out, finish->measurement, 32); + } else { + return 1; + } + + return 0; +}