diff options
-rw-r--r-- | target/i386/cpu.c | 1 | ||||
-rw-r--r-- | target/i386/sev-stub.c | 6 | ||||
-rw-r--r-- | target/i386/sev.c | 44 | ||||
-rw-r--r-- | target/i386/sev_i386.h | 1 |
4 files changed, 50 insertions, 2 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 9c3d2d6..20c3a5a 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5984,6 +5984,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, break; case 0x8000001F: *eax = sev_enabled() ? 0x2 : 0; + *eax |= sev_es_enabled() ? 0x8 : 0; *ebx = sev_get_cbit_position(); *ebx |= sev_get_reduced_phys_bits() << 6; *ecx = 0; diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c index 1ac1fd5..edf6c51 100644 --- a/target/i386/sev-stub.c +++ b/target/i386/sev-stub.c @@ -49,6 +49,7 @@ SevCapability *sev_get_capabilities(Error **errp) error_setg(errp, "SEV is not available in this QEMU"); return NULL; } + int sev_inject_launch_secret(const char *hdr, const char *secret, uint64_t gpa, Error **errp) { @@ -59,3 +60,8 @@ int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp) { return 0; } + +bool sev_es_enabled(void) +{ + return false; +} diff --git a/target/i386/sev.c b/target/i386/sev.c index 11c9a3c..dc0e530 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -341,6 +341,12 @@ sev_enabled(void) return !!sev_guest; } +bool +sev_es_enabled(void) +{ + return false; +} + uint64_t sev_get_me_mask(void) { @@ -561,6 +567,20 @@ sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len) return ret; } +static int +sev_launch_update_vmsa(SevGuestState *sev) +{ + int ret, fw_error; + + ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL, &fw_error); + if (ret) { + error_report("%s: LAUNCH_UPDATE_VMSA ret=%d fw_error=%d '%s'", + __func__, ret, fw_error, fw_error_to_str(fw_error)); + } + + return ret; +} + static void sev_launch_get_measure(Notifier *notifier, void *unused) { @@ -573,6 +593,14 @@ sev_launch_get_measure(Notifier *notifier, void *unused) return; } + if (sev_es_enabled()) { + /* measure all the VM save areas before getting launch_measure */ + ret = sev_launch_update_vmsa(sev); + if (ret) { + exit(1); + } + } + measurement = g_new0(struct kvm_sev_launch_measure, 1); /* query the measurement blob length */ @@ -667,7 +695,7 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) SevGuestState *sev = (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST); char *devname; - int ret, fw_error; + int ret, fw_error, cmd; uint32_t ebx; uint32_t host_cbitpos; struct sev_user_data_status status = {}; @@ -724,8 +752,20 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) sev->api_major = status.api_major; sev->api_minor = status.api_minor; + if (sev_es_enabled()) { + if (!(status.flags & SEV_STATUS_FLAGS_CONFIG_ES)) { + error_report("%s: guest policy requires SEV-ES, but " + "host SEV-ES support unavailable", + __func__); + goto err; + } + cmd = KVM_SEV_ES_INIT; + } else { + cmd = KVM_SEV_INIT; + } + trace_kvm_sev_init(); - ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT, NULL, &fw_error); + ret = sev_ioctl(sev->sev_fd, cmd, NULL, &fw_error); if (ret) { error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'", __func__, ret, fw_error, fw_error_to_str(fw_error)); diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h index bd9f00a..ae221d4 100644 --- a/target/i386/sev_i386.h +++ b/target/i386/sev_i386.h @@ -28,6 +28,7 @@ #define SEV_POLICY_DOMAIN 0x10 #define SEV_POLICY_SEV 0x20 +extern bool sev_es_enabled(void); extern uint64_t sev_get_me_mask(void); extern SevInfo *sev_get_info(void); extern uint32_t sev_get_cbit_position(void); |