From: Tobin Feldman-Fitzthum <to...@ibm.com> In addition to using QMP to provide the guest memory address that the launch secret blob will be injected into, the secret address can also be specified in the guest ROM. This patch adds sev_find_secret_gpa, which scans the ROM page by page to find a launch secret table identified by a GUID. If the table is found, the address it contains will be used in place of any address specified via QMP.
Signed-off-by: Tobin Feldman-Fitzthum <to...@linux.vnet.ibm.com> --- target/i386/sev.c | 34 ++++++++++++++++++++++++++++++++-- target/i386/sev_i386.h | 16 ++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index 774e47d9d1..4adc56d7e3 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -706,6 +706,8 @@ sev_guest_init(const char *id) s->api_major = status.api_major; s->api_minor = status.api_minor; + s->secret_gpa = 0; + trace_kvm_sev_init(); ret = sev_ioctl(s->sev_fd, KVM_SEV_INIT, NULL, &fw_error); if (ret) { @@ -731,6 +733,28 @@ err: return NULL; } +static void +sev_find_secret_gpa(uint8_t *ptr, uint64_t len) +{ + uint64_t offset; + + SevROMSecretTable *secret_table; + QemuUUID secret_table_guid; + + qemu_uuid_parse(SEV_ROM_SECRET_GUID,&secret_table_guid); + secret_table_guid = qemu_uuid_bswap(secret_table_guid); + + offset = len - 0x1000; + while(offset > 0) { + secret_table = (SevROMSecretTable *)(ptr + offset); + if(qemu_uuid_is_equal(&secret_table_guid, (QemuUUID *) secret_table)){ + sev_state->secret_gpa = (long unsigned int) secret_table->base; + break; + } + offset -= 0x1000; + } +} + int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) { @@ -738,6 +762,9 @@ sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) /* if SEV is in update state then encrypt the data else do nothing */ if (sev_check_state(SEV_STATE_LAUNCH_UPDATE)) { + if(!sev_state->secret_gpa) { + sev_find_secret_gpa(ptr, len); + } return sev_launch_update_data(ptr, len); } @@ -776,8 +803,8 @@ int sev_inject_launch_secret(const char *packet_hdr, /* secret can be inject only in this state */ if (!sev_check_state(SEV_STATE_LAUNCH_SECRET)) { - error_report("Not in correct state. %x",sev_state->state); - return 1; + error_report("Not in correct state. %x",sev_state->state); + return 1; } hdr = g_base64_decode(packet_hdr, &hdr_sz); @@ -792,6 +819,9 @@ int sev_inject_launch_secret(const char *packet_hdr, goto err; } + if(sev_state->secret_gpa) + gpa = sev_state->secret_gpa; + hva = gpa2hva(gpa, data_sz); if (!hva) { goto err; diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h index 8ada9d385d..b1f9ab93bb 100644 --- a/target/i386/sev_i386.h +++ b/target/i386/sev_i386.h @@ -19,6 +19,7 @@ #include "sysemu/kvm.h" #include "sysemu/sev.h" #include "qemu/error-report.h" +#include "qemu/uuid.h" #include "qapi/qapi-types-misc-target.h" #define SEV_POLICY_NODBG 0x1 @@ -28,6 +29,8 @@ #define SEV_POLICY_DOMAIN 0x10 #define SEV_POLICY_SEV 0x20 +#define SEV_ROM_SECRET_GUID "adf956ad-e98c-484c-ae11-b51c7d336447" + #define TYPE_QSEV_GUEST_INFO "sev-guest" #define QSEV_GUEST_INFO(obj) \ OBJECT_CHECK(QSevGuestInfo, (obj), TYPE_QSEV_GUEST_INFO) @@ -42,6 +45,18 @@ extern SevCapability *sev_get_capabilities(void); typedef struct QSevGuestInfo QSevGuestInfo; typedef struct QSevGuestInfoClass QSevGuestInfoClass; +typedef struct SevROMSecretTable SevROMSecretTable; + +/** + * If guest physical address for the launch secret is + * provided in the ROM, it should be in the following + * page-aligned structure. + */ +struct SevROMSecretTable { + QemuUUID guid; + unsigned int base; + unsigned int size; +}; /** * QSevGuestInfo: @@ -78,6 +93,7 @@ struct SEVState { uint32_t cbitpos; uint32_t reduced_phys_bits; uint32_t handle; + uint64_t secret_gpa; int sev_fd; SevState state; gchar *measurement; -- 2.20.1 (Apple Git-117)