target/mips: Replace gen_exception_end(EXCP_RI) by gen_rsvd_instruction
[qemu/ar7.git] / target / i386 / sev.c
blob154660681189f536de60a8a5552cf33986128451
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"
35 #define TYPE_SEV_GUEST "sev-guest"
36 OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
39 /**
40 * SevGuestState:
42 * The SevGuestState object is used for creating and managing a SEV
43 * guest.
45 * # $QEMU \
46 * -object sev-guest,id=sev0 \
47 * -machine ...,memory-encryption=sev0
49 struct SevGuestState {
50 Object parent_obj;
52 /* configuration parameters */
53 char *sev_device;
54 uint32_t policy;
55 char *dh_cert_file;
56 char *session_file;
57 uint32_t cbitpos;
58 uint32_t reduced_phys_bits;
60 /* runtime state */
61 uint32_t handle;
62 uint8_t api_major;
63 uint8_t api_minor;
64 uint8_t build_id;
65 uint64_t me_mask;
66 int sev_fd;
67 SevState state;
68 gchar *measurement;
71 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
72 #define DEFAULT_SEV_DEVICE "/dev/sev"
74 static SevGuestState *sev_guest;
75 static Error *sev_mig_blocker;
77 static const char *const sev_fw_errlist[] = {
78 "",
79 "Platform state is invalid",
80 "Guest state is invalid",
81 "Platform configuration is invalid",
82 "Buffer too small",
83 "Platform is already owned",
84 "Certificate is invalid",
85 "Policy is not allowed",
86 "Guest is not active",
87 "Invalid address",
88 "Bad signature",
89 "Bad measurement",
90 "Asid is already owned",
91 "Invalid ASID",
92 "WBINVD is required",
93 "DF_FLUSH is required",
94 "Guest handle is invalid",
95 "Invalid command",
96 "Guest is active",
97 "Hardware error",
98 "Hardware unsafe",
99 "Feature not supported",
100 "Invalid parameter"
103 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
105 static int
106 sev_ioctl(int fd, int cmd, void *data, int *error)
108 int r;
109 struct kvm_sev_cmd input;
111 memset(&input, 0x0, sizeof(input));
113 input.id = cmd;
114 input.sev_fd = fd;
115 input.data = (__u64)(unsigned long)data;
117 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
119 if (error) {
120 *error = input.error;
123 return r;
126 static int
127 sev_platform_ioctl(int fd, int cmd, void *data, int *error)
129 int r;
130 struct sev_issue_cmd arg;
132 arg.cmd = cmd;
133 arg.data = (unsigned long)data;
134 r = ioctl(fd, SEV_ISSUE_CMD, &arg);
135 if (error) {
136 *error = arg.error;
139 return r;
142 static const char *
143 fw_error_to_str(int code)
145 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
146 return "unknown error";
149 return sev_fw_errlist[code];
152 static bool
153 sev_check_state(const SevGuestState *sev, SevState state)
155 assert(sev);
156 return sev->state == state ? true : false;
159 static void
160 sev_set_guest_state(SevGuestState *sev, SevState new_state)
162 assert(new_state < SEV_STATE__MAX);
163 assert(sev);
165 trace_kvm_sev_change_state(SevState_str(sev->state),
166 SevState_str(new_state));
167 sev->state = new_state;
170 static void
171 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
173 int r;
174 struct kvm_enc_region range;
175 ram_addr_t offset;
176 MemoryRegion *mr;
179 * The RAM device presents a memory region that should be treated
180 * as IO region and should not be pinned.
182 mr = memory_region_from_host(host, &offset);
183 if (mr && memory_region_is_ram_device(mr)) {
184 return;
187 range.addr = (__u64)(unsigned long)host;
188 range.size = size;
190 trace_kvm_memcrypt_register_region(host, size);
191 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
192 if (r) {
193 error_report("%s: failed to register region (%p+%#zx) error '%s'",
194 __func__, host, size, strerror(errno));
195 exit(1);
199 static void
200 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
202 int r;
203 struct kvm_enc_region range;
204 ram_addr_t offset;
205 MemoryRegion *mr;
208 * The RAM device presents a memory region that should be treated
209 * as IO region and should not have been pinned.
211 mr = memory_region_from_host(host, &offset);
212 if (mr && memory_region_is_ram_device(mr)) {
213 return;
216 range.addr = (__u64)(unsigned long)host;
217 range.size = size;
219 trace_kvm_memcrypt_unregister_region(host, size);
220 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
221 if (r) {
222 error_report("%s: failed to unregister region (%p+%#zx)",
223 __func__, host, size);
227 static struct RAMBlockNotifier sev_ram_notifier = {
228 .ram_block_added = sev_ram_block_added,
229 .ram_block_removed = sev_ram_block_removed,
232 static void
233 sev_guest_finalize(Object *obj)
237 static char *
238 sev_guest_get_session_file(Object *obj, Error **errp)
240 SevGuestState *s = SEV_GUEST(obj);
242 return s->session_file ? g_strdup(s->session_file) : NULL;
245 static void
246 sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
248 SevGuestState *s = SEV_GUEST(obj);
250 s->session_file = g_strdup(value);
253 static char *
254 sev_guest_get_dh_cert_file(Object *obj, Error **errp)
256 SevGuestState *s = SEV_GUEST(obj);
258 return g_strdup(s->dh_cert_file);
261 static void
262 sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
264 SevGuestState *s = SEV_GUEST(obj);
266 s->dh_cert_file = g_strdup(value);
269 static char *
270 sev_guest_get_sev_device(Object *obj, Error **errp)
272 SevGuestState *sev = SEV_GUEST(obj);
274 return g_strdup(sev->sev_device);
277 static void
278 sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
280 SevGuestState *sev = SEV_GUEST(obj);
282 sev->sev_device = g_strdup(value);
285 static void
286 sev_guest_class_init(ObjectClass *oc, void *data)
288 object_class_property_add_str(oc, "sev-device",
289 sev_guest_get_sev_device,
290 sev_guest_set_sev_device);
291 object_class_property_set_description(oc, "sev-device",
292 "SEV device to use");
293 object_class_property_add_str(oc, "dh-cert-file",
294 sev_guest_get_dh_cert_file,
295 sev_guest_set_dh_cert_file);
296 object_class_property_set_description(oc, "dh-cert-file",
297 "guest owners DH certificate (encoded with base64)");
298 object_class_property_add_str(oc, "session-file",
299 sev_guest_get_session_file,
300 sev_guest_set_session_file);
301 object_class_property_set_description(oc, "session-file",
302 "guest owners session parameters (encoded with base64)");
305 static void
306 sev_guest_instance_init(Object *obj)
308 SevGuestState *sev = SEV_GUEST(obj);
310 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
311 sev->policy = DEFAULT_GUEST_POLICY;
312 object_property_add_uint32_ptr(obj, "policy", &sev->policy,
313 OBJ_PROP_FLAG_READWRITE);
314 object_property_add_uint32_ptr(obj, "handle", &sev->handle,
315 OBJ_PROP_FLAG_READWRITE);
316 object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
317 OBJ_PROP_FLAG_READWRITE);
318 object_property_add_uint32_ptr(obj, "reduced-phys-bits",
319 &sev->reduced_phys_bits,
320 OBJ_PROP_FLAG_READWRITE);
323 /* sev guest info */
324 static const TypeInfo sev_guest_info = {
325 .parent = TYPE_OBJECT,
326 .name = TYPE_SEV_GUEST,
327 .instance_size = sizeof(SevGuestState),
328 .instance_finalize = sev_guest_finalize,
329 .class_init = sev_guest_class_init,
330 .instance_init = sev_guest_instance_init,
331 .interfaces = (InterfaceInfo[]) {
332 { TYPE_USER_CREATABLE },
337 static SevGuestState *
338 lookup_sev_guest_info(const char *id)
340 Object *obj;
341 SevGuestState *info;
343 obj = object_resolve_path_component(object_get_objects_root(), id);
344 if (!obj) {
345 return NULL;
348 info = (SevGuestState *)
349 object_dynamic_cast(obj, TYPE_SEV_GUEST);
350 if (!info) {
351 return NULL;
354 return info;
357 bool
358 sev_enabled(void)
360 return !!sev_guest;
363 uint64_t
364 sev_get_me_mask(void)
366 return sev_guest ? sev_guest->me_mask : ~0;
369 uint32_t
370 sev_get_cbit_position(void)
372 return sev_guest ? sev_guest->cbitpos : 0;
375 uint32_t
376 sev_get_reduced_phys_bits(void)
378 return sev_guest ? sev_guest->reduced_phys_bits : 0;
381 SevInfo *
382 sev_get_info(void)
384 SevInfo *info;
386 info = g_new0(SevInfo, 1);
387 info->enabled = sev_enabled();
389 if (info->enabled) {
390 info->api_major = sev_guest->api_major;
391 info->api_minor = sev_guest->api_minor;
392 info->build_id = sev_guest->build_id;
393 info->policy = sev_guest->policy;
394 info->state = sev_guest->state;
395 info->handle = sev_guest->handle;
398 return info;
401 static int
402 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
403 size_t *cert_chain_len, Error **errp)
405 guchar *pdh_data = NULL;
406 guchar *cert_chain_data = NULL;
407 struct sev_user_data_pdh_cert_export export = {};
408 int err, r;
410 /* query the certificate length */
411 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
412 if (r < 0) {
413 if (err != SEV_RET_INVALID_LEN) {
414 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
415 r, err, fw_error_to_str(err));
416 return 1;
420 pdh_data = g_new(guchar, export.pdh_cert_len);
421 cert_chain_data = g_new(guchar, export.cert_chain_len);
422 export.pdh_cert_address = (unsigned long)pdh_data;
423 export.cert_chain_address = (unsigned long)cert_chain_data;
425 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
426 if (r < 0) {
427 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
428 r, err, fw_error_to_str(err));
429 goto e_free;
432 *pdh = pdh_data;
433 *pdh_len = export.pdh_cert_len;
434 *cert_chain = cert_chain_data;
435 *cert_chain_len = export.cert_chain_len;
436 return 0;
438 e_free:
439 g_free(pdh_data);
440 g_free(cert_chain_data);
441 return 1;
444 SevCapability *
445 sev_get_capabilities(Error **errp)
447 SevCapability *cap = NULL;
448 guchar *pdh_data = NULL;
449 guchar *cert_chain_data = NULL;
450 size_t pdh_len = 0, cert_chain_len = 0;
451 uint32_t ebx;
452 int fd;
454 if (!kvm_enabled()) {
455 error_setg(errp, "KVM not enabled");
456 return NULL;
458 if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) {
459 error_setg(errp, "SEV is not enabled in KVM");
460 return NULL;
463 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
464 if (fd < 0) {
465 error_setg_errno(errp, errno, "Failed to open %s",
466 DEFAULT_SEV_DEVICE);
467 return NULL;
470 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
471 &cert_chain_data, &cert_chain_len, errp)) {
472 goto out;
475 cap = g_new0(SevCapability, 1);
476 cap->pdh = g_base64_encode(pdh_data, pdh_len);
477 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
479 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
480 cap->cbitpos = ebx & 0x3f;
483 * When SEV feature is enabled, we loose one bit in guest physical
484 * addressing.
486 cap->reduced_phys_bits = 1;
488 out:
489 g_free(pdh_data);
490 g_free(cert_chain_data);
491 close(fd);
492 return cap;
495 static int
496 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
498 gsize sz;
499 gchar *base64;
500 GError *error = NULL;
502 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
503 error_report("failed to read '%s' (%s)", filename, error->message);
504 g_error_free(error);
505 return -1;
508 *data = g_base64_decode(base64, len);
509 return 0;
512 static int
513 sev_launch_start(SevGuestState *sev)
515 gsize sz;
516 int ret = 1;
517 int fw_error, rc;
518 struct kvm_sev_launch_start *start;
519 guchar *session = NULL, *dh_cert = NULL;
521 start = g_new0(struct kvm_sev_launch_start, 1);
523 start->handle = sev->handle;
524 start->policy = sev->policy;
525 if (sev->session_file) {
526 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
527 goto out;
529 start->session_uaddr = (unsigned long)session;
530 start->session_len = sz;
533 if (sev->dh_cert_file) {
534 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
535 goto out;
537 start->dh_uaddr = (unsigned long)dh_cert;
538 start->dh_len = sz;
541 trace_kvm_sev_launch_start(start->policy, session, dh_cert);
542 rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
543 if (rc < 0) {
544 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
545 __func__, ret, fw_error, fw_error_to_str(fw_error));
546 goto out;
549 sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
550 sev->handle = start->handle;
551 ret = 0;
553 out:
554 g_free(start);
555 g_free(session);
556 g_free(dh_cert);
557 return ret;
560 static int
561 sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
563 int ret, fw_error;
564 struct kvm_sev_launch_update_data update;
566 if (!addr || !len) {
567 return 1;
570 update.uaddr = (__u64)(unsigned long)addr;
571 update.len = len;
572 trace_kvm_sev_launch_update_data(addr, len);
573 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
574 &update, &fw_error);
575 if (ret) {
576 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
577 __func__, ret, fw_error, fw_error_to_str(fw_error));
580 return ret;
583 static void
584 sev_launch_get_measure(Notifier *notifier, void *unused)
586 SevGuestState *sev = sev_guest;
587 int ret, error;
588 guchar *data;
589 struct kvm_sev_launch_measure *measurement;
591 if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
592 return;
595 measurement = g_new0(struct kvm_sev_launch_measure, 1);
597 /* query the measurement blob length */
598 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
599 measurement, &error);
600 if (!measurement->len) {
601 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
602 __func__, ret, error, fw_error_to_str(errno));
603 goto free_measurement;
606 data = g_new0(guchar, measurement->len);
607 measurement->uaddr = (unsigned long)data;
609 /* get the measurement blob */
610 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
611 measurement, &error);
612 if (ret) {
613 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
614 __func__, ret, error, fw_error_to_str(errno));
615 goto free_data;
618 sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
620 /* encode the measurement value and emit the event */
621 sev->measurement = g_base64_encode(data, measurement->len);
622 trace_kvm_sev_launch_measurement(sev->measurement);
624 free_data:
625 g_free(data);
626 free_measurement:
627 g_free(measurement);
630 char *
631 sev_get_launch_measurement(void)
633 if (sev_guest &&
634 sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
635 return g_strdup(sev_guest->measurement);
638 return NULL;
641 static Notifier sev_machine_done_notify = {
642 .notify = sev_launch_get_measure,
645 static void
646 sev_launch_finish(SevGuestState *sev)
648 int ret, error;
649 Error *local_err = NULL;
651 trace_kvm_sev_launch_finish();
652 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
653 if (ret) {
654 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
655 __func__, ret, error, fw_error_to_str(error));
656 exit(1);
659 sev_set_guest_state(sev, SEV_STATE_RUNNING);
661 /* add migration blocker */
662 error_setg(&sev_mig_blocker,
663 "SEV: Migration is not implemented");
664 ret = migrate_add_blocker(sev_mig_blocker, &local_err);
665 if (local_err) {
666 error_report_err(local_err);
667 error_free(sev_mig_blocker);
668 exit(1);
672 static void
673 sev_vm_state_change(void *opaque, int running, RunState state)
675 SevGuestState *sev = opaque;
677 if (running) {
678 if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
679 sev_launch_finish(sev);
684 void *
685 sev_guest_init(const char *id)
687 SevGuestState *sev;
688 char *devname;
689 int ret, fw_error;
690 uint32_t ebx;
691 uint32_t host_cbitpos;
692 struct sev_user_data_status status = {};
694 ret = ram_block_discard_disable(true);
695 if (ret) {
696 error_report("%s: cannot disable RAM discard", __func__);
697 return NULL;
700 sev = lookup_sev_guest_info(id);
701 if (!sev) {
702 error_report("%s: '%s' is not a valid '%s' object",
703 __func__, id, TYPE_SEV_GUEST);
704 goto err;
707 sev_guest = sev;
708 sev->state = SEV_STATE_UNINIT;
710 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
711 host_cbitpos = ebx & 0x3f;
713 if (host_cbitpos != sev->cbitpos) {
714 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
715 __func__, host_cbitpos, sev->cbitpos);
716 goto err;
719 if (sev->reduced_phys_bits < 1) {
720 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
721 " requested '%d'", __func__, sev->reduced_phys_bits);
722 goto err;
725 sev->me_mask = ~(1UL << sev->cbitpos);
727 devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
728 sev->sev_fd = open(devname, O_RDWR);
729 if (sev->sev_fd < 0) {
730 error_report("%s: Failed to open %s '%s'", __func__,
731 devname, strerror(errno));
733 g_free(devname);
734 if (sev->sev_fd < 0) {
735 goto err;
738 ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status,
739 &fw_error);
740 if (ret) {
741 error_report("%s: failed to get platform status ret=%d "
742 "fw_error='%d: %s'", __func__, ret, fw_error,
743 fw_error_to_str(fw_error));
744 goto err;
746 sev->build_id = status.build;
747 sev->api_major = status.api_major;
748 sev->api_minor = status.api_minor;
750 trace_kvm_sev_init();
751 ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT, NULL, &fw_error);
752 if (ret) {
753 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
754 __func__, ret, fw_error, fw_error_to_str(fw_error));
755 goto err;
758 ret = sev_launch_start(sev);
759 if (ret) {
760 error_report("%s: failed to create encryption context", __func__);
761 goto err;
764 ram_block_notifier_add(&sev_ram_notifier);
765 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
766 qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
768 return sev;
769 err:
770 sev_guest = NULL;
771 ram_block_discard_disable(false);
772 return NULL;
776 sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
778 SevGuestState *sev = handle;
780 assert(sev);
782 /* if SEV is in update state then encrypt the data else do nothing */
783 if (sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
784 return sev_launch_update_data(sev, ptr, len);
787 return 0;
790 int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
791 uint64_t gpa, Error **errp)
793 struct kvm_sev_launch_secret input;
794 g_autofree guchar *data = NULL, *hdr = NULL;
795 int error, ret = 1;
796 void *hva;
797 gsize hdr_sz = 0, data_sz = 0;
798 MemoryRegion *mr = NULL;
800 if (!sev_guest) {
801 error_setg(errp, "SEV: SEV not enabled.");
802 return 1;
805 /* secret can be injected only in this state */
806 if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
807 error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
808 sev_guest->state);
809 return 1;
812 hdr = g_base64_decode(packet_hdr, &hdr_sz);
813 if (!hdr || !hdr_sz) {
814 error_setg(errp, "SEV: Failed to decode sequence header");
815 return 1;
818 data = g_base64_decode(secret, &data_sz);
819 if (!data || !data_sz) {
820 error_setg(errp, "SEV: Failed to decode data");
821 return 1;
824 hva = gpa2hva(&mr, gpa, data_sz, errp);
825 if (!hva) {
826 error_prepend(errp, "SEV: Failed to calculate guest address: ");
827 return 1;
830 input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
831 input.hdr_len = hdr_sz;
833 input.trans_uaddr = (uint64_t)(unsigned long)data;
834 input.trans_len = data_sz;
836 input.guest_uaddr = (uint64_t)(unsigned long)hva;
837 input.guest_len = data_sz;
839 trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
840 input.trans_uaddr, input.trans_len);
842 ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
843 &input, &error);
844 if (ret) {
845 error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
846 ret, error, fw_error_to_str(error));
847 return ret;
850 return 0;
853 static void
854 sev_register_types(void)
856 type_register_static(&sev_guest_info);
859 type_init(sev_register_types);