sev/i386: Add initial support for SEV-ES
[qemu/ar7.git] / target / i386 / sev.c
blobdc0e53019b5f0cda687f6454e5cbcfaf0366865d
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 "sysemu/kvm.h"
26 #include "sev_i386.h"
27 #include "sysemu/sysemu.h"
28 #include "sysemu/runstate.h"
29 #include "trace.h"
30 #include "migration/blocker.h"
31 #include "qom/object.h"
32 #include "exec/address-spaces.h"
33 #include "monitor/monitor.h"
34 #include "exec/confidential-guest-support.h"
36 #define TYPE_SEV_GUEST "sev-guest"
37 OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
40 /**
41 * SevGuestState:
43 * The SevGuestState object is used for creating and managing a SEV
44 * guest.
46 * # $QEMU \
47 * -object sev-guest,id=sev0 \
48 * -machine ...,memory-encryption=sev0
50 struct SevGuestState {
51 ConfidentialGuestSupport parent_obj;
53 /* configuration parameters */
54 char *sev_device;
55 uint32_t policy;
56 char *dh_cert_file;
57 char *session_file;
58 uint32_t cbitpos;
59 uint32_t reduced_phys_bits;
61 /* runtime state */
62 uint32_t handle;
63 uint8_t api_major;
64 uint8_t api_minor;
65 uint8_t build_id;
66 uint64_t me_mask;
67 int sev_fd;
68 SevState state;
69 gchar *measurement;
72 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
73 #define DEFAULT_SEV_DEVICE "/dev/sev"
75 static SevGuestState *sev_guest;
76 static Error *sev_mig_blocker;
78 static const char *const sev_fw_errlist[] = {
79 "",
80 "Platform state is invalid",
81 "Guest state is invalid",
82 "Platform configuration is invalid",
83 "Buffer too small",
84 "Platform is already owned",
85 "Certificate is invalid",
86 "Policy is not allowed",
87 "Guest is not active",
88 "Invalid address",
89 "Bad signature",
90 "Bad measurement",
91 "Asid is already owned",
92 "Invalid ASID",
93 "WBINVD is required",
94 "DF_FLUSH is required",
95 "Guest handle is invalid",
96 "Invalid command",
97 "Guest is active",
98 "Hardware error",
99 "Hardware unsafe",
100 "Feature not supported",
101 "Invalid parameter"
104 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
106 static int
107 sev_ioctl(int fd, int cmd, void *data, int *error)
109 int r;
110 struct kvm_sev_cmd input;
112 memset(&input, 0x0, sizeof(input));
114 input.id = cmd;
115 input.sev_fd = fd;
116 input.data = (__u64)(unsigned long)data;
118 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
120 if (error) {
121 *error = input.error;
124 return r;
127 static int
128 sev_platform_ioctl(int fd, int cmd, void *data, int *error)
130 int r;
131 struct sev_issue_cmd arg;
133 arg.cmd = cmd;
134 arg.data = (unsigned long)data;
135 r = ioctl(fd, SEV_ISSUE_CMD, &arg);
136 if (error) {
137 *error = arg.error;
140 return r;
143 static const char *
144 fw_error_to_str(int code)
146 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
147 return "unknown error";
150 return sev_fw_errlist[code];
153 static bool
154 sev_check_state(const SevGuestState *sev, SevState state)
156 assert(sev);
157 return sev->state == state ? true : false;
160 static void
161 sev_set_guest_state(SevGuestState *sev, SevState new_state)
163 assert(new_state < SEV_STATE__MAX);
164 assert(sev);
166 trace_kvm_sev_change_state(SevState_str(sev->state),
167 SevState_str(new_state));
168 sev->state = new_state;
171 static void
172 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
174 int r;
175 struct kvm_enc_region range;
176 ram_addr_t offset;
177 MemoryRegion *mr;
180 * The RAM device presents a memory region that should be treated
181 * as IO region and should not be pinned.
183 mr = memory_region_from_host(host, &offset);
184 if (mr && memory_region_is_ram_device(mr)) {
185 return;
188 range.addr = (__u64)(unsigned long)host;
189 range.size = size;
191 trace_kvm_memcrypt_register_region(host, size);
192 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
193 if (r) {
194 error_report("%s: failed to register region (%p+%#zx) error '%s'",
195 __func__, host, size, strerror(errno));
196 exit(1);
200 static void
201 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
203 int r;
204 struct kvm_enc_region range;
205 ram_addr_t offset;
206 MemoryRegion *mr;
209 * The RAM device presents a memory region that should be treated
210 * as IO region and should not have been pinned.
212 mr = memory_region_from_host(host, &offset);
213 if (mr && memory_region_is_ram_device(mr)) {
214 return;
217 range.addr = (__u64)(unsigned long)host;
218 range.size = size;
220 trace_kvm_memcrypt_unregister_region(host, size);
221 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
222 if (r) {
223 error_report("%s: failed to unregister region (%p+%#zx)",
224 __func__, host, size);
228 static struct RAMBlockNotifier sev_ram_notifier = {
229 .ram_block_added = sev_ram_block_added,
230 .ram_block_removed = sev_ram_block_removed,
233 static void
234 sev_guest_finalize(Object *obj)
238 static char *
239 sev_guest_get_session_file(Object *obj, Error **errp)
241 SevGuestState *s = SEV_GUEST(obj);
243 return s->session_file ? g_strdup(s->session_file) : NULL;
246 static void
247 sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
249 SevGuestState *s = SEV_GUEST(obj);
251 s->session_file = g_strdup(value);
254 static char *
255 sev_guest_get_dh_cert_file(Object *obj, Error **errp)
257 SevGuestState *s = SEV_GUEST(obj);
259 return g_strdup(s->dh_cert_file);
262 static void
263 sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
265 SevGuestState *s = SEV_GUEST(obj);
267 s->dh_cert_file = g_strdup(value);
270 static char *
271 sev_guest_get_sev_device(Object *obj, Error **errp)
273 SevGuestState *sev = SEV_GUEST(obj);
275 return g_strdup(sev->sev_device);
278 static void
279 sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
281 SevGuestState *sev = SEV_GUEST(obj);
283 sev->sev_device = g_strdup(value);
286 static void
287 sev_guest_class_init(ObjectClass *oc, void *data)
289 object_class_property_add_str(oc, "sev-device",
290 sev_guest_get_sev_device,
291 sev_guest_set_sev_device);
292 object_class_property_set_description(oc, "sev-device",
293 "SEV device to use");
294 object_class_property_add_str(oc, "dh-cert-file",
295 sev_guest_get_dh_cert_file,
296 sev_guest_set_dh_cert_file);
297 object_class_property_set_description(oc, "dh-cert-file",
298 "guest owners DH certificate (encoded with base64)");
299 object_class_property_add_str(oc, "session-file",
300 sev_guest_get_session_file,
301 sev_guest_set_session_file);
302 object_class_property_set_description(oc, "session-file",
303 "guest owners session parameters (encoded with base64)");
306 static void
307 sev_guest_instance_init(Object *obj)
309 SevGuestState *sev = SEV_GUEST(obj);
311 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
312 sev->policy = DEFAULT_GUEST_POLICY;
313 object_property_add_uint32_ptr(obj, "policy", &sev->policy,
314 OBJ_PROP_FLAG_READWRITE);
315 object_property_add_uint32_ptr(obj, "handle", &sev->handle,
316 OBJ_PROP_FLAG_READWRITE);
317 object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
318 OBJ_PROP_FLAG_READWRITE);
319 object_property_add_uint32_ptr(obj, "reduced-phys-bits",
320 &sev->reduced_phys_bits,
321 OBJ_PROP_FLAG_READWRITE);
324 /* sev guest info */
325 static const TypeInfo sev_guest_info = {
326 .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT,
327 .name = TYPE_SEV_GUEST,
328 .instance_size = sizeof(SevGuestState),
329 .instance_finalize = sev_guest_finalize,
330 .class_init = sev_guest_class_init,
331 .instance_init = sev_guest_instance_init,
332 .interfaces = (InterfaceInfo[]) {
333 { TYPE_USER_CREATABLE },
338 bool
339 sev_enabled(void)
341 return !!sev_guest;
344 bool
345 sev_es_enabled(void)
347 return false;
350 uint64_t
351 sev_get_me_mask(void)
353 return sev_guest ? sev_guest->me_mask : ~0;
356 uint32_t
357 sev_get_cbit_position(void)
359 return sev_guest ? sev_guest->cbitpos : 0;
362 uint32_t
363 sev_get_reduced_phys_bits(void)
365 return sev_guest ? sev_guest->reduced_phys_bits : 0;
368 SevInfo *
369 sev_get_info(void)
371 SevInfo *info;
373 info = g_new0(SevInfo, 1);
374 info->enabled = sev_enabled();
376 if (info->enabled) {
377 info->api_major = sev_guest->api_major;
378 info->api_minor = sev_guest->api_minor;
379 info->build_id = sev_guest->build_id;
380 info->policy = sev_guest->policy;
381 info->state = sev_guest->state;
382 info->handle = sev_guest->handle;
385 return info;
388 static int
389 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
390 size_t *cert_chain_len, Error **errp)
392 guchar *pdh_data = NULL;
393 guchar *cert_chain_data = NULL;
394 struct sev_user_data_pdh_cert_export export = {};
395 int err, r;
397 /* query the certificate length */
398 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
399 if (r < 0) {
400 if (err != SEV_RET_INVALID_LEN) {
401 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
402 r, err, fw_error_to_str(err));
403 return 1;
407 pdh_data = g_new(guchar, export.pdh_cert_len);
408 cert_chain_data = g_new(guchar, export.cert_chain_len);
409 export.pdh_cert_address = (unsigned long)pdh_data;
410 export.cert_chain_address = (unsigned long)cert_chain_data;
412 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
413 if (r < 0) {
414 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
415 r, err, fw_error_to_str(err));
416 goto e_free;
419 *pdh = pdh_data;
420 *pdh_len = export.pdh_cert_len;
421 *cert_chain = cert_chain_data;
422 *cert_chain_len = export.cert_chain_len;
423 return 0;
425 e_free:
426 g_free(pdh_data);
427 g_free(cert_chain_data);
428 return 1;
431 SevCapability *
432 sev_get_capabilities(Error **errp)
434 SevCapability *cap = NULL;
435 guchar *pdh_data = NULL;
436 guchar *cert_chain_data = NULL;
437 size_t pdh_len = 0, cert_chain_len = 0;
438 uint32_t ebx;
439 int fd;
441 if (!kvm_enabled()) {
442 error_setg(errp, "KVM not enabled");
443 return NULL;
445 if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) {
446 error_setg(errp, "SEV is not enabled in KVM");
447 return NULL;
450 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
451 if (fd < 0) {
452 error_setg_errno(errp, errno, "Failed to open %s",
453 DEFAULT_SEV_DEVICE);
454 return NULL;
457 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
458 &cert_chain_data, &cert_chain_len, errp)) {
459 goto out;
462 cap = g_new0(SevCapability, 1);
463 cap->pdh = g_base64_encode(pdh_data, pdh_len);
464 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
466 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
467 cap->cbitpos = ebx & 0x3f;
470 * When SEV feature is enabled, we loose one bit in guest physical
471 * addressing.
473 cap->reduced_phys_bits = 1;
475 out:
476 g_free(pdh_data);
477 g_free(cert_chain_data);
478 close(fd);
479 return cap;
482 static int
483 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
485 gsize sz;
486 gchar *base64;
487 GError *error = NULL;
489 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
490 error_report("failed to read '%s' (%s)", filename, error->message);
491 g_error_free(error);
492 return -1;
495 *data = g_base64_decode(base64, len);
496 return 0;
499 static int
500 sev_launch_start(SevGuestState *sev)
502 gsize sz;
503 int ret = 1;
504 int fw_error, rc;
505 struct kvm_sev_launch_start *start;
506 guchar *session = NULL, *dh_cert = NULL;
508 start = g_new0(struct kvm_sev_launch_start, 1);
510 start->handle = sev->handle;
511 start->policy = sev->policy;
512 if (sev->session_file) {
513 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
514 goto out;
516 start->session_uaddr = (unsigned long)session;
517 start->session_len = sz;
520 if (sev->dh_cert_file) {
521 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
522 goto out;
524 start->dh_uaddr = (unsigned long)dh_cert;
525 start->dh_len = sz;
528 trace_kvm_sev_launch_start(start->policy, session, dh_cert);
529 rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
530 if (rc < 0) {
531 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
532 __func__, ret, fw_error, fw_error_to_str(fw_error));
533 goto out;
536 sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
537 sev->handle = start->handle;
538 ret = 0;
540 out:
541 g_free(start);
542 g_free(session);
543 g_free(dh_cert);
544 return ret;
547 static int
548 sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
550 int ret, fw_error;
551 struct kvm_sev_launch_update_data update;
553 if (!addr || !len) {
554 return 1;
557 update.uaddr = (__u64)(unsigned long)addr;
558 update.len = len;
559 trace_kvm_sev_launch_update_data(addr, len);
560 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
561 &update, &fw_error);
562 if (ret) {
563 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
564 __func__, ret, fw_error, fw_error_to_str(fw_error));
567 return ret;
570 static int
571 sev_launch_update_vmsa(SevGuestState *sev)
573 int ret, fw_error;
575 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL, &fw_error);
576 if (ret) {
577 error_report("%s: LAUNCH_UPDATE_VMSA ret=%d fw_error=%d '%s'",
578 __func__, ret, fw_error, fw_error_to_str(fw_error));
581 return ret;
584 static void
585 sev_launch_get_measure(Notifier *notifier, void *unused)
587 SevGuestState *sev = sev_guest;
588 int ret, error;
589 guchar *data;
590 struct kvm_sev_launch_measure *measurement;
592 if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
593 return;
596 if (sev_es_enabled()) {
597 /* measure all the VM save areas before getting launch_measure */
598 ret = sev_launch_update_vmsa(sev);
599 if (ret) {
600 exit(1);
604 measurement = g_new0(struct kvm_sev_launch_measure, 1);
606 /* query the measurement blob length */
607 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
608 measurement, &error);
609 if (!measurement->len) {
610 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
611 __func__, ret, error, fw_error_to_str(errno));
612 goto free_measurement;
615 data = g_new0(guchar, measurement->len);
616 measurement->uaddr = (unsigned long)data;
618 /* get the measurement blob */
619 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
620 measurement, &error);
621 if (ret) {
622 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
623 __func__, ret, error, fw_error_to_str(errno));
624 goto free_data;
627 sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
629 /* encode the measurement value and emit the event */
630 sev->measurement = g_base64_encode(data, measurement->len);
631 trace_kvm_sev_launch_measurement(sev->measurement);
633 free_data:
634 g_free(data);
635 free_measurement:
636 g_free(measurement);
639 char *
640 sev_get_launch_measurement(void)
642 if (sev_guest &&
643 sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
644 return g_strdup(sev_guest->measurement);
647 return NULL;
650 static Notifier sev_machine_done_notify = {
651 .notify = sev_launch_get_measure,
654 static void
655 sev_launch_finish(SevGuestState *sev)
657 int ret, error;
658 Error *local_err = NULL;
660 trace_kvm_sev_launch_finish();
661 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
662 if (ret) {
663 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
664 __func__, ret, error, fw_error_to_str(error));
665 exit(1);
668 sev_set_guest_state(sev, SEV_STATE_RUNNING);
670 /* add migration blocker */
671 error_setg(&sev_mig_blocker,
672 "SEV: Migration is not implemented");
673 ret = migrate_add_blocker(sev_mig_blocker, &local_err);
674 if (local_err) {
675 error_report_err(local_err);
676 error_free(sev_mig_blocker);
677 exit(1);
681 static void
682 sev_vm_state_change(void *opaque, int running, RunState state)
684 SevGuestState *sev = opaque;
686 if (running) {
687 if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
688 sev_launch_finish(sev);
693 int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
695 SevGuestState *sev
696 = (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST);
697 char *devname;
698 int ret, fw_error, cmd;
699 uint32_t ebx;
700 uint32_t host_cbitpos;
701 struct sev_user_data_status status = {};
703 if (!sev) {
704 return 0;
707 ret = ram_block_discard_disable(true);
708 if (ret) {
709 error_report("%s: cannot disable RAM discard", __func__);
710 return -1;
713 sev_guest = sev;
714 sev->state = SEV_STATE_UNINIT;
716 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
717 host_cbitpos = ebx & 0x3f;
719 if (host_cbitpos != sev->cbitpos) {
720 error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'",
721 __func__, host_cbitpos, sev->cbitpos);
722 goto err;
725 if (sev->reduced_phys_bits < 1) {
726 error_setg(errp, "%s: reduced_phys_bits check failed, it should be >=1,"
727 " requested '%d'", __func__, sev->reduced_phys_bits);
728 goto err;
731 sev->me_mask = ~(1UL << sev->cbitpos);
733 devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
734 sev->sev_fd = open(devname, O_RDWR);
735 if (sev->sev_fd < 0) {
736 error_setg(errp, "%s: Failed to open %s '%s'", __func__,
737 devname, strerror(errno));
738 g_free(devname);
739 goto err;
741 g_free(devname);
743 ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status,
744 &fw_error);
745 if (ret) {
746 error_setg(errp, "%s: failed to get platform status ret=%d "
747 "fw_error='%d: %s'", __func__, ret, fw_error,
748 fw_error_to_str(fw_error));
749 goto err;
751 sev->build_id = status.build;
752 sev->api_major = status.api_major;
753 sev->api_minor = status.api_minor;
755 if (sev_es_enabled()) {
756 if (!(status.flags & SEV_STATUS_FLAGS_CONFIG_ES)) {
757 error_report("%s: guest policy requires SEV-ES, but "
758 "host SEV-ES support unavailable",
759 __func__);
760 goto err;
762 cmd = KVM_SEV_ES_INIT;
763 } else {
764 cmd = KVM_SEV_INIT;
767 trace_kvm_sev_init();
768 ret = sev_ioctl(sev->sev_fd, cmd, NULL, &fw_error);
769 if (ret) {
770 error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'",
771 __func__, ret, fw_error, fw_error_to_str(fw_error));
772 goto err;
775 ret = sev_launch_start(sev);
776 if (ret) {
777 error_setg(errp, "%s: failed to create encryption context", __func__);
778 goto err;
781 ram_block_notifier_add(&sev_ram_notifier);
782 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
783 qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
785 cgs->ready = true;
787 return 0;
788 err:
789 sev_guest = NULL;
790 ram_block_discard_disable(false);
791 return -1;
795 sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
797 if (!sev_guest) {
798 return 0;
801 /* if SEV is in update state then encrypt the data else do nothing */
802 if (sev_check_state(sev_guest, SEV_STATE_LAUNCH_UPDATE)) {
803 int ret = sev_launch_update_data(sev_guest, ptr, len);
804 if (ret < 0) {
805 error_setg(errp, "failed to encrypt pflash rom");
806 return ret;
810 return 0;
813 int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
814 uint64_t gpa, Error **errp)
816 struct kvm_sev_launch_secret input;
817 g_autofree guchar *data = NULL, *hdr = NULL;
818 int error, ret = 1;
819 void *hva;
820 gsize hdr_sz = 0, data_sz = 0;
821 MemoryRegion *mr = NULL;
823 if (!sev_guest) {
824 error_setg(errp, "SEV: SEV not enabled.");
825 return 1;
828 /* secret can be injected only in this state */
829 if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
830 error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
831 sev_guest->state);
832 return 1;
835 hdr = g_base64_decode(packet_hdr, &hdr_sz);
836 if (!hdr || !hdr_sz) {
837 error_setg(errp, "SEV: Failed to decode sequence header");
838 return 1;
841 data = g_base64_decode(secret, &data_sz);
842 if (!data || !data_sz) {
843 error_setg(errp, "SEV: Failed to decode data");
844 return 1;
847 hva = gpa2hva(&mr, gpa, data_sz, errp);
848 if (!hva) {
849 error_prepend(errp, "SEV: Failed to calculate guest address: ");
850 return 1;
853 input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
854 input.hdr_len = hdr_sz;
856 input.trans_uaddr = (uint64_t)(unsigned long)data;
857 input.trans_len = data_sz;
859 input.guest_uaddr = (uint64_t)(unsigned long)hva;
860 input.guest_len = data_sz;
862 trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
863 input.trans_uaddr, input.trans_len);
865 ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
866 &input, &error);
867 if (ret) {
868 error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
869 ret, error, fw_error_to_str(error));
870 return ret;
873 return 0;
876 static void
877 sev_register_types(void)
879 type_register_static(&sev_guest_info);
882 type_init(sev_register_types);