hw/timer/sse-timer: Model the SSE Subsystem System Timer
[qemu/ar7.git] / target / i386 / sev.c
blob0f414df02f39ddf93153958a8560a74a16ab0823
1 /*
2 * QEMU SEV support
4 * Copyright Advanced Micro Devices 2016-2018
6 * Author:
7 * Brijesh Singh <brijesh.singh@amd.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
16 #include <linux/kvm.h>
17 #include <linux/psp-sev.h>
19 #include <sys/ioctl.h>
21 #include "qapi/error.h"
22 #include "qom/object_interfaces.h"
23 #include "qemu/base64.h"
24 #include "qemu/module.h"
25 #include "qemu/uuid.h"
26 #include "sysemu/kvm.h"
27 #include "sev_i386.h"
28 #include "sysemu/sysemu.h"
29 #include "sysemu/runstate.h"
30 #include "trace.h"
31 #include "migration/blocker.h"
32 #include "qom/object.h"
33 #include "exec/address-spaces.h"
34 #include "monitor/monitor.h"
35 #include "exec/confidential-guest-support.h"
36 #include "hw/i386/pc.h"
38 #define TYPE_SEV_GUEST "sev-guest"
39 OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
42 /**
43 * SevGuestState:
45 * The SevGuestState object is used for creating and managing a SEV
46 * guest.
48 * # $QEMU \
49 * -object sev-guest,id=sev0 \
50 * -machine ...,memory-encryption=sev0
52 struct SevGuestState {
53 ConfidentialGuestSupport parent_obj;
55 /* configuration parameters */
56 char *sev_device;
57 uint32_t policy;
58 char *dh_cert_file;
59 char *session_file;
60 uint32_t cbitpos;
61 uint32_t reduced_phys_bits;
63 /* runtime state */
64 uint32_t handle;
65 uint8_t api_major;
66 uint8_t api_minor;
67 uint8_t build_id;
68 uint64_t me_mask;
69 int sev_fd;
70 SevState state;
71 gchar *measurement;
73 uint32_t reset_cs;
74 uint32_t reset_ip;
75 bool reset_data_valid;
78 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
79 #define DEFAULT_SEV_DEVICE "/dev/sev"
81 #define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
82 typedef struct __attribute__((__packed__)) SevInfoBlock {
83 /* SEV-ES Reset Vector Address */
84 uint32_t reset_addr;
85 } SevInfoBlock;
87 static SevGuestState *sev_guest;
88 static Error *sev_mig_blocker;
90 static const char *const sev_fw_errlist[] = {
91 "",
92 "Platform state is invalid",
93 "Guest state is invalid",
94 "Platform configuration is invalid",
95 "Buffer too small",
96 "Platform is already owned",
97 "Certificate is invalid",
98 "Policy is not allowed",
99 "Guest is not active",
100 "Invalid address",
101 "Bad signature",
102 "Bad measurement",
103 "Asid is already owned",
104 "Invalid ASID",
105 "WBINVD is required",
106 "DF_FLUSH is required",
107 "Guest handle is invalid",
108 "Invalid command",
109 "Guest is active",
110 "Hardware error",
111 "Hardware unsafe",
112 "Feature not supported",
113 "Invalid parameter"
116 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
118 static int
119 sev_ioctl(int fd, int cmd, void *data, int *error)
121 int r;
122 struct kvm_sev_cmd input;
124 memset(&input, 0x0, sizeof(input));
126 input.id = cmd;
127 input.sev_fd = fd;
128 input.data = (__u64)(unsigned long)data;
130 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
132 if (error) {
133 *error = input.error;
136 return r;
139 static int
140 sev_platform_ioctl(int fd, int cmd, void *data, int *error)
142 int r;
143 struct sev_issue_cmd arg;
145 arg.cmd = cmd;
146 arg.data = (unsigned long)data;
147 r = ioctl(fd, SEV_ISSUE_CMD, &arg);
148 if (error) {
149 *error = arg.error;
152 return r;
155 static const char *
156 fw_error_to_str(int code)
158 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
159 return "unknown error";
162 return sev_fw_errlist[code];
165 static bool
166 sev_check_state(const SevGuestState *sev, SevState state)
168 assert(sev);
169 return sev->state == state ? true : false;
172 static void
173 sev_set_guest_state(SevGuestState *sev, SevState new_state)
175 assert(new_state < SEV_STATE__MAX);
176 assert(sev);
178 trace_kvm_sev_change_state(SevState_str(sev->state),
179 SevState_str(new_state));
180 sev->state = new_state;
183 static void
184 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
186 int r;
187 struct kvm_enc_region range;
188 ram_addr_t offset;
189 MemoryRegion *mr;
192 * The RAM device presents a memory region that should be treated
193 * as IO region and should not be pinned.
195 mr = memory_region_from_host(host, &offset);
196 if (mr && memory_region_is_ram_device(mr)) {
197 return;
200 range.addr = (__u64)(unsigned long)host;
201 range.size = size;
203 trace_kvm_memcrypt_register_region(host, size);
204 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
205 if (r) {
206 error_report("%s: failed to register region (%p+%#zx) error '%s'",
207 __func__, host, size, strerror(errno));
208 exit(1);
212 static void
213 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
215 int r;
216 struct kvm_enc_region range;
217 ram_addr_t offset;
218 MemoryRegion *mr;
221 * The RAM device presents a memory region that should be treated
222 * as IO region and should not have been pinned.
224 mr = memory_region_from_host(host, &offset);
225 if (mr && memory_region_is_ram_device(mr)) {
226 return;
229 range.addr = (__u64)(unsigned long)host;
230 range.size = size;
232 trace_kvm_memcrypt_unregister_region(host, size);
233 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
234 if (r) {
235 error_report("%s: failed to unregister region (%p+%#zx)",
236 __func__, host, size);
240 static struct RAMBlockNotifier sev_ram_notifier = {
241 .ram_block_added = sev_ram_block_added,
242 .ram_block_removed = sev_ram_block_removed,
245 static void
246 sev_guest_finalize(Object *obj)
250 static char *
251 sev_guest_get_session_file(Object *obj, Error **errp)
253 SevGuestState *s = SEV_GUEST(obj);
255 return s->session_file ? g_strdup(s->session_file) : NULL;
258 static void
259 sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
261 SevGuestState *s = SEV_GUEST(obj);
263 s->session_file = g_strdup(value);
266 static char *
267 sev_guest_get_dh_cert_file(Object *obj, Error **errp)
269 SevGuestState *s = SEV_GUEST(obj);
271 return g_strdup(s->dh_cert_file);
274 static void
275 sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
277 SevGuestState *s = SEV_GUEST(obj);
279 s->dh_cert_file = g_strdup(value);
282 static char *
283 sev_guest_get_sev_device(Object *obj, Error **errp)
285 SevGuestState *sev = SEV_GUEST(obj);
287 return g_strdup(sev->sev_device);
290 static void
291 sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
293 SevGuestState *sev = SEV_GUEST(obj);
295 sev->sev_device = g_strdup(value);
298 static void
299 sev_guest_class_init(ObjectClass *oc, void *data)
301 object_class_property_add_str(oc, "sev-device",
302 sev_guest_get_sev_device,
303 sev_guest_set_sev_device);
304 object_class_property_set_description(oc, "sev-device",
305 "SEV device to use");
306 object_class_property_add_str(oc, "dh-cert-file",
307 sev_guest_get_dh_cert_file,
308 sev_guest_set_dh_cert_file);
309 object_class_property_set_description(oc, "dh-cert-file",
310 "guest owners DH certificate (encoded with base64)");
311 object_class_property_add_str(oc, "session-file",
312 sev_guest_get_session_file,
313 sev_guest_set_session_file);
314 object_class_property_set_description(oc, "session-file",
315 "guest owners session parameters (encoded with base64)");
318 static void
319 sev_guest_instance_init(Object *obj)
321 SevGuestState *sev = SEV_GUEST(obj);
323 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
324 sev->policy = DEFAULT_GUEST_POLICY;
325 object_property_add_uint32_ptr(obj, "policy", &sev->policy,
326 OBJ_PROP_FLAG_READWRITE);
327 object_property_add_uint32_ptr(obj, "handle", &sev->handle,
328 OBJ_PROP_FLAG_READWRITE);
329 object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
330 OBJ_PROP_FLAG_READWRITE);
331 object_property_add_uint32_ptr(obj, "reduced-phys-bits",
332 &sev->reduced_phys_bits,
333 OBJ_PROP_FLAG_READWRITE);
336 /* sev guest info */
337 static const TypeInfo sev_guest_info = {
338 .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT,
339 .name = TYPE_SEV_GUEST,
340 .instance_size = sizeof(SevGuestState),
341 .instance_finalize = sev_guest_finalize,
342 .class_init = sev_guest_class_init,
343 .instance_init = sev_guest_instance_init,
344 .interfaces = (InterfaceInfo[]) {
345 { TYPE_USER_CREATABLE },
350 bool
351 sev_enabled(void)
353 return !!sev_guest;
356 bool
357 sev_es_enabled(void)
359 return sev_enabled() && (sev_guest->policy & SEV_POLICY_ES);
362 uint64_t
363 sev_get_me_mask(void)
365 return sev_guest ? sev_guest->me_mask : ~0;
368 uint32_t
369 sev_get_cbit_position(void)
371 return sev_guest ? sev_guest->cbitpos : 0;
374 uint32_t
375 sev_get_reduced_phys_bits(void)
377 return sev_guest ? sev_guest->reduced_phys_bits : 0;
380 SevInfo *
381 sev_get_info(void)
383 SevInfo *info;
385 info = g_new0(SevInfo, 1);
386 info->enabled = sev_enabled();
388 if (info->enabled) {
389 info->api_major = sev_guest->api_major;
390 info->api_minor = sev_guest->api_minor;
391 info->build_id = sev_guest->build_id;
392 info->policy = sev_guest->policy;
393 info->state = sev_guest->state;
394 info->handle = sev_guest->handle;
397 return info;
400 static int
401 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
402 size_t *cert_chain_len, Error **errp)
404 guchar *pdh_data = NULL;
405 guchar *cert_chain_data = NULL;
406 struct sev_user_data_pdh_cert_export export = {};
407 int err, r;
409 /* query the certificate length */
410 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
411 if (r < 0) {
412 if (err != SEV_RET_INVALID_LEN) {
413 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
414 r, err, fw_error_to_str(err));
415 return 1;
419 pdh_data = g_new(guchar, export.pdh_cert_len);
420 cert_chain_data = g_new(guchar, export.cert_chain_len);
421 export.pdh_cert_address = (unsigned long)pdh_data;
422 export.cert_chain_address = (unsigned long)cert_chain_data;
424 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
425 if (r < 0) {
426 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
427 r, err, fw_error_to_str(err));
428 goto e_free;
431 *pdh = pdh_data;
432 *pdh_len = export.pdh_cert_len;
433 *cert_chain = cert_chain_data;
434 *cert_chain_len = export.cert_chain_len;
435 return 0;
437 e_free:
438 g_free(pdh_data);
439 g_free(cert_chain_data);
440 return 1;
443 SevCapability *
444 sev_get_capabilities(Error **errp)
446 SevCapability *cap = NULL;
447 guchar *pdh_data = NULL;
448 guchar *cert_chain_data = NULL;
449 size_t pdh_len = 0, cert_chain_len = 0;
450 uint32_t ebx;
451 int fd;
453 if (!kvm_enabled()) {
454 error_setg(errp, "KVM not enabled");
455 return NULL;
457 if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) {
458 error_setg(errp, "SEV is not enabled in KVM");
459 return NULL;
462 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
463 if (fd < 0) {
464 error_setg_errno(errp, errno, "Failed to open %s",
465 DEFAULT_SEV_DEVICE);
466 return NULL;
469 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
470 &cert_chain_data, &cert_chain_len, errp)) {
471 goto out;
474 cap = g_new0(SevCapability, 1);
475 cap->pdh = g_base64_encode(pdh_data, pdh_len);
476 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
478 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
479 cap->cbitpos = ebx & 0x3f;
482 * When SEV feature is enabled, we loose one bit in guest physical
483 * addressing.
485 cap->reduced_phys_bits = 1;
487 out:
488 g_free(pdh_data);
489 g_free(cert_chain_data);
490 close(fd);
491 return cap;
494 static int
495 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
497 gsize sz;
498 gchar *base64;
499 GError *error = NULL;
501 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
502 error_report("failed to read '%s' (%s)", filename, error->message);
503 g_error_free(error);
504 return -1;
507 *data = g_base64_decode(base64, len);
508 return 0;
511 static int
512 sev_launch_start(SevGuestState *sev)
514 gsize sz;
515 int ret = 1;
516 int fw_error, rc;
517 struct kvm_sev_launch_start *start;
518 guchar *session = NULL, *dh_cert = NULL;
520 start = g_new0(struct kvm_sev_launch_start, 1);
522 start->handle = sev->handle;
523 start->policy = sev->policy;
524 if (sev->session_file) {
525 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
526 goto out;
528 start->session_uaddr = (unsigned long)session;
529 start->session_len = sz;
532 if (sev->dh_cert_file) {
533 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
534 goto out;
536 start->dh_uaddr = (unsigned long)dh_cert;
537 start->dh_len = sz;
540 trace_kvm_sev_launch_start(start->policy, session, dh_cert);
541 rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
542 if (rc < 0) {
543 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
544 __func__, ret, fw_error, fw_error_to_str(fw_error));
545 goto out;
548 sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
549 sev->handle = start->handle;
550 ret = 0;
552 out:
553 g_free(start);
554 g_free(session);
555 g_free(dh_cert);
556 return ret;
559 static int
560 sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
562 int ret, fw_error;
563 struct kvm_sev_launch_update_data update;
565 if (!addr || !len) {
566 return 1;
569 update.uaddr = (__u64)(unsigned long)addr;
570 update.len = len;
571 trace_kvm_sev_launch_update_data(addr, len);
572 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
573 &update, &fw_error);
574 if (ret) {
575 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
576 __func__, ret, fw_error, fw_error_to_str(fw_error));
579 return ret;
582 static int
583 sev_launch_update_vmsa(SevGuestState *sev)
585 int ret, fw_error;
587 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL, &fw_error);
588 if (ret) {
589 error_report("%s: LAUNCH_UPDATE_VMSA ret=%d fw_error=%d '%s'",
590 __func__, ret, fw_error, fw_error_to_str(fw_error));
593 return ret;
596 static void
597 sev_launch_get_measure(Notifier *notifier, void *unused)
599 SevGuestState *sev = sev_guest;
600 int ret, error;
601 guchar *data;
602 struct kvm_sev_launch_measure *measurement;
604 if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
605 return;
608 if (sev_es_enabled()) {
609 /* measure all the VM save areas before getting launch_measure */
610 ret = sev_launch_update_vmsa(sev);
611 if (ret) {
612 exit(1);
616 measurement = g_new0(struct kvm_sev_launch_measure, 1);
618 /* query the measurement blob length */
619 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
620 measurement, &error);
621 if (!measurement->len) {
622 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
623 __func__, ret, error, fw_error_to_str(errno));
624 goto free_measurement;
627 data = g_new0(guchar, measurement->len);
628 measurement->uaddr = (unsigned long)data;
630 /* get the measurement blob */
631 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
632 measurement, &error);
633 if (ret) {
634 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
635 __func__, ret, error, fw_error_to_str(errno));
636 goto free_data;
639 sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
641 /* encode the measurement value and emit the event */
642 sev->measurement = g_base64_encode(data, measurement->len);
643 trace_kvm_sev_launch_measurement(sev->measurement);
645 free_data:
646 g_free(data);
647 free_measurement:
648 g_free(measurement);
651 char *
652 sev_get_launch_measurement(void)
654 if (sev_guest &&
655 sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
656 return g_strdup(sev_guest->measurement);
659 return NULL;
662 static Notifier sev_machine_done_notify = {
663 .notify = sev_launch_get_measure,
666 static void
667 sev_launch_finish(SevGuestState *sev)
669 int ret, error;
670 Error *local_err = NULL;
672 trace_kvm_sev_launch_finish();
673 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
674 if (ret) {
675 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
676 __func__, ret, error, fw_error_to_str(error));
677 exit(1);
680 sev_set_guest_state(sev, SEV_STATE_RUNNING);
682 /* add migration blocker */
683 error_setg(&sev_mig_blocker,
684 "SEV: Migration is not implemented");
685 ret = migrate_add_blocker(sev_mig_blocker, &local_err);
686 if (local_err) {
687 error_report_err(local_err);
688 error_free(sev_mig_blocker);
689 exit(1);
693 static void
694 sev_vm_state_change(void *opaque, int running, RunState state)
696 SevGuestState *sev = opaque;
698 if (running) {
699 if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
700 sev_launch_finish(sev);
705 int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
707 SevGuestState *sev
708 = (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST);
709 char *devname;
710 int ret, fw_error, cmd;
711 uint32_t ebx;
712 uint32_t host_cbitpos;
713 struct sev_user_data_status status = {};
715 if (!sev) {
716 return 0;
719 ret = ram_block_discard_disable(true);
720 if (ret) {
721 error_report("%s: cannot disable RAM discard", __func__);
722 return -1;
725 sev_guest = sev;
726 sev->state = SEV_STATE_UNINIT;
728 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
729 host_cbitpos = ebx & 0x3f;
731 if (host_cbitpos != sev->cbitpos) {
732 error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'",
733 __func__, host_cbitpos, sev->cbitpos);
734 goto err;
737 if (sev->reduced_phys_bits < 1) {
738 error_setg(errp, "%s: reduced_phys_bits check failed, it should be >=1,"
739 " requested '%d'", __func__, sev->reduced_phys_bits);
740 goto err;
743 sev->me_mask = ~(1UL << sev->cbitpos);
745 devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
746 sev->sev_fd = open(devname, O_RDWR);
747 if (sev->sev_fd < 0) {
748 error_setg(errp, "%s: Failed to open %s '%s'", __func__,
749 devname, strerror(errno));
750 g_free(devname);
751 goto err;
753 g_free(devname);
755 ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status,
756 &fw_error);
757 if (ret) {
758 error_setg(errp, "%s: failed to get platform status ret=%d "
759 "fw_error='%d: %s'", __func__, ret, fw_error,
760 fw_error_to_str(fw_error));
761 goto err;
763 sev->build_id = status.build;
764 sev->api_major = status.api_major;
765 sev->api_minor = status.api_minor;
767 if (sev_es_enabled()) {
768 if (!kvm_kernel_irqchip_allowed()) {
769 error_report("%s: SEV-ES guests require in-kernel irqchip support",
770 __func__);
771 goto err;
774 if (!(status.flags & SEV_STATUS_FLAGS_CONFIG_ES)) {
775 error_report("%s: guest policy requires SEV-ES, but "
776 "host SEV-ES support unavailable",
777 __func__);
778 goto err;
780 cmd = KVM_SEV_ES_INIT;
781 } else {
782 cmd = KVM_SEV_INIT;
785 trace_kvm_sev_init();
786 ret = sev_ioctl(sev->sev_fd, cmd, NULL, &fw_error);
787 if (ret) {
788 error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'",
789 __func__, ret, fw_error, fw_error_to_str(fw_error));
790 goto err;
793 ret = sev_launch_start(sev);
794 if (ret) {
795 error_setg(errp, "%s: failed to create encryption context", __func__);
796 goto err;
799 ram_block_notifier_add(&sev_ram_notifier);
800 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
801 qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
803 cgs->ready = true;
805 return 0;
806 err:
807 sev_guest = NULL;
808 ram_block_discard_disable(false);
809 return -1;
813 sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
815 if (!sev_guest) {
816 return 0;
819 /* if SEV is in update state then encrypt the data else do nothing */
820 if (sev_check_state(sev_guest, SEV_STATE_LAUNCH_UPDATE)) {
821 int ret = sev_launch_update_data(sev_guest, ptr, len);
822 if (ret < 0) {
823 error_setg(errp, "failed to encrypt pflash rom");
824 return ret;
828 return 0;
831 int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
832 uint64_t gpa, Error **errp)
834 struct kvm_sev_launch_secret input;
835 g_autofree guchar *data = NULL, *hdr = NULL;
836 int error, ret = 1;
837 void *hva;
838 gsize hdr_sz = 0, data_sz = 0;
839 MemoryRegion *mr = NULL;
841 if (!sev_guest) {
842 error_setg(errp, "SEV: SEV not enabled.");
843 return 1;
846 /* secret can be injected only in this state */
847 if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
848 error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
849 sev_guest->state);
850 return 1;
853 hdr = g_base64_decode(packet_hdr, &hdr_sz);
854 if (!hdr || !hdr_sz) {
855 error_setg(errp, "SEV: Failed to decode sequence header");
856 return 1;
859 data = g_base64_decode(secret, &data_sz);
860 if (!data || !data_sz) {
861 error_setg(errp, "SEV: Failed to decode data");
862 return 1;
865 hva = gpa2hva(&mr, gpa, data_sz, errp);
866 if (!hva) {
867 error_prepend(errp, "SEV: Failed to calculate guest address: ");
868 return 1;
871 input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
872 input.hdr_len = hdr_sz;
874 input.trans_uaddr = (uint64_t)(unsigned long)data;
875 input.trans_len = data_sz;
877 input.guest_uaddr = (uint64_t)(unsigned long)hva;
878 input.guest_len = data_sz;
880 trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
881 input.trans_uaddr, input.trans_len);
883 ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
884 &input, &error);
885 if (ret) {
886 error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
887 ret, error, fw_error_to_str(error));
888 return ret;
891 return 0;
894 static int
895 sev_es_parse_reset_block(SevInfoBlock *info, uint32_t *addr)
897 if (!info->reset_addr) {
898 error_report("SEV-ES reset address is zero");
899 return 1;
902 *addr = info->reset_addr;
904 return 0;
907 static int
908 sev_es_find_reset_vector(void *flash_ptr, uint64_t flash_size,
909 uint32_t *addr)
911 QemuUUID info_guid, *guid;
912 SevInfoBlock *info;
913 uint8_t *data;
914 uint16_t *len;
917 * Initialize the address to zero. An address of zero with a successful
918 * return code indicates that SEV-ES is not active.
920 *addr = 0;
923 * Extract the AP reset vector for SEV-ES guests by locating the SEV GUID.
924 * The SEV GUID is located on its own (original implementation) or within
925 * the Firmware GUID Table (new implementation), either of which are
926 * located 32 bytes from the end of the flash.
928 * Check the Firmware GUID Table first.
930 if (pc_system_ovmf_table_find(SEV_INFO_BLOCK_GUID, &data, NULL)) {
931 return sev_es_parse_reset_block((SevInfoBlock *)data, addr);
935 * SEV info block not found in the Firmware GUID Table (or there isn't
936 * a Firmware GUID Table), fall back to the original implementation.
938 data = flash_ptr + flash_size - 0x20;
940 qemu_uuid_parse(SEV_INFO_BLOCK_GUID, &info_guid);
941 info_guid = qemu_uuid_bswap(info_guid); /* GUIDs are LE */
943 guid = (QemuUUID *)(data - sizeof(info_guid));
944 if (!qemu_uuid_is_equal(guid, &info_guid)) {
945 error_report("SEV information block/Firmware GUID Table block not found in pflash rom");
946 return 1;
949 len = (uint16_t *)((uint8_t *)guid - sizeof(*len));
950 info = (SevInfoBlock *)(data - le16_to_cpu(*len));
952 return sev_es_parse_reset_block(info, addr);
955 void sev_es_set_reset_vector(CPUState *cpu)
957 X86CPU *x86;
958 CPUX86State *env;
960 /* Only update if we have valid reset information */
961 if (!sev_guest || !sev_guest->reset_data_valid) {
962 return;
965 /* Do not update the BSP reset state */
966 if (cpu->cpu_index == 0) {
967 return;
970 x86 = X86_CPU(cpu);
971 env = &x86->env;
973 cpu_x86_load_seg_cache(env, R_CS, 0xf000, sev_guest->reset_cs, 0xffff,
974 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
975 DESC_R_MASK | DESC_A_MASK);
977 env->eip = sev_guest->reset_ip;
980 int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size)
982 CPUState *cpu;
983 uint32_t addr;
984 int ret;
986 if (!sev_es_enabled()) {
987 return 0;
990 addr = 0;
991 ret = sev_es_find_reset_vector(flash_ptr, flash_size,
992 &addr);
993 if (ret) {
994 return ret;
997 if (addr) {
998 sev_guest->reset_cs = addr & 0xffff0000;
999 sev_guest->reset_ip = addr & 0x0000ffff;
1000 sev_guest->reset_data_valid = true;
1002 CPU_FOREACH(cpu) {
1003 sev_es_set_reset_vector(cpu);
1007 return 0;
1010 static void
1011 sev_register_types(void)
1013 type_register_static(&sev_guest_info);
1016 type_init(sev_register_types);