]> git.ipfire.org Git - thirdparty/qemu.git/blob - target/i386/sev.c
Move QOM typedefs and add missing includes
[thirdparty/qemu.git] / target / i386 / sev.c
1 /*
2 * QEMU SEV support
3 *
4 * Copyright Advanced Micro Devices 2016-2018
5 *
6 * Author:
7 * Brijesh Singh <brijesh.singh@amd.com>
8 *
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.
11 *
12 */
13
14 #include "qemu/osdep.h"
15
16 #include <linux/kvm.h>
17 #include <linux/psp-sev.h>
18
19 #include <sys/ioctl.h>
20
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
33 #define TYPE_SEV_GUEST "sev-guest"
34 typedef struct SevGuestState SevGuestState;
35 #define SEV_GUEST(obj) \
36 OBJECT_CHECK(SevGuestState, (obj), TYPE_SEV_GUEST)
37
38
39 /**
40 * SevGuestState:
41 *
42 * The SevGuestState object is used for creating and managing a SEV
43 * guest.
44 *
45 * # $QEMU \
46 * -object sev-guest,id=sev0 \
47 * -machine ...,memory-encryption=sev0
48 */
49 struct SevGuestState {
50 Object parent_obj;
51
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;
59
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;
69 };
70
71 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
72 #define DEFAULT_SEV_DEVICE "/dev/sev"
73
74 static SevGuestState *sev_guest;
75 static Error *sev_mig_blocker;
76
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"
101 };
102
103 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
104
105 static int
106 sev_ioctl(int fd, int cmd, void *data, int *error)
107 {
108 int r;
109 struct kvm_sev_cmd input;
110
111 memset(&input, 0x0, sizeof(input));
112
113 input.id = cmd;
114 input.sev_fd = fd;
115 input.data = (__u64)(unsigned long)data;
116
117 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
118
119 if (error) {
120 *error = input.error;
121 }
122
123 return r;
124 }
125
126 static int
127 sev_platform_ioctl(int fd, int cmd, void *data, int *error)
128 {
129 int r;
130 struct sev_issue_cmd arg;
131
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;
137 }
138
139 return r;
140 }
141
142 static const char *
143 fw_error_to_str(int code)
144 {
145 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
146 return "unknown error";
147 }
148
149 return sev_fw_errlist[code];
150 }
151
152 static bool
153 sev_check_state(const SevGuestState *sev, SevState state)
154 {
155 assert(sev);
156 return sev->state == state ? true : false;
157 }
158
159 static void
160 sev_set_guest_state(SevGuestState *sev, SevState new_state)
161 {
162 assert(new_state < SEV_STATE__MAX);
163 assert(sev);
164
165 trace_kvm_sev_change_state(SevState_str(sev->state),
166 SevState_str(new_state));
167 sev->state = new_state;
168 }
169
170 static void
171 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
172 {
173 int r;
174 struct kvm_enc_region range;
175 ram_addr_t offset;
176 MemoryRegion *mr;
177
178 /*
179 * The RAM device presents a memory region that should be treated
180 * as IO region and should not be pinned.
181 */
182 mr = memory_region_from_host(host, &offset);
183 if (mr && memory_region_is_ram_device(mr)) {
184 return;
185 }
186
187 range.addr = (__u64)(unsigned long)host;
188 range.size = size;
189
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);
196 }
197 }
198
199 static void
200 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
201 {
202 int r;
203 struct kvm_enc_region range;
204 ram_addr_t offset;
205 MemoryRegion *mr;
206
207 /*
208 * The RAM device presents a memory region that should be treated
209 * as IO region and should not have been pinned.
210 */
211 mr = memory_region_from_host(host, &offset);
212 if (mr && memory_region_is_ram_device(mr)) {
213 return;
214 }
215
216 range.addr = (__u64)(unsigned long)host;
217 range.size = size;
218
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);
224 }
225 }
226
227 static struct RAMBlockNotifier sev_ram_notifier = {
228 .ram_block_added = sev_ram_block_added,
229 .ram_block_removed = sev_ram_block_removed,
230 };
231
232 static void
233 sev_guest_finalize(Object *obj)
234 {
235 }
236
237 static char *
238 sev_guest_get_session_file(Object *obj, Error **errp)
239 {
240 SevGuestState *s = SEV_GUEST(obj);
241
242 return s->session_file ? g_strdup(s->session_file) : NULL;
243 }
244
245 static void
246 sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
247 {
248 SevGuestState *s = SEV_GUEST(obj);
249
250 s->session_file = g_strdup(value);
251 }
252
253 static char *
254 sev_guest_get_dh_cert_file(Object *obj, Error **errp)
255 {
256 SevGuestState *s = SEV_GUEST(obj);
257
258 return g_strdup(s->dh_cert_file);
259 }
260
261 static void
262 sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
263 {
264 SevGuestState *s = SEV_GUEST(obj);
265
266 s->dh_cert_file = g_strdup(value);
267 }
268
269 static char *
270 sev_guest_get_sev_device(Object *obj, Error **errp)
271 {
272 SevGuestState *sev = SEV_GUEST(obj);
273
274 return g_strdup(sev->sev_device);
275 }
276
277 static void
278 sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
279 {
280 SevGuestState *sev = SEV_GUEST(obj);
281
282 sev->sev_device = g_strdup(value);
283 }
284
285 static void
286 sev_guest_class_init(ObjectClass *oc, void *data)
287 {
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)");
303 }
304
305 static void
306 sev_guest_instance_init(Object *obj)
307 {
308 SevGuestState *sev = SEV_GUEST(obj);
309
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);
321 }
322
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 },
333 { }
334 }
335 };
336
337 static SevGuestState *
338 lookup_sev_guest_info(const char *id)
339 {
340 Object *obj;
341 SevGuestState *info;
342
343 obj = object_resolve_path_component(object_get_objects_root(), id);
344 if (!obj) {
345 return NULL;
346 }
347
348 info = (SevGuestState *)
349 object_dynamic_cast(obj, TYPE_SEV_GUEST);
350 if (!info) {
351 return NULL;
352 }
353
354 return info;
355 }
356
357 bool
358 sev_enabled(void)
359 {
360 return !!sev_guest;
361 }
362
363 uint64_t
364 sev_get_me_mask(void)
365 {
366 return sev_guest ? sev_guest->me_mask : ~0;
367 }
368
369 uint32_t
370 sev_get_cbit_position(void)
371 {
372 return sev_guest ? sev_guest->cbitpos : 0;
373 }
374
375 uint32_t
376 sev_get_reduced_phys_bits(void)
377 {
378 return sev_guest ? sev_guest->reduced_phys_bits : 0;
379 }
380
381 SevInfo *
382 sev_get_info(void)
383 {
384 SevInfo *info;
385
386 info = g_new0(SevInfo, 1);
387 info->enabled = sev_enabled();
388
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;
396 }
397
398 return info;
399 }
400
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)
404 {
405 guchar *pdh_data = NULL;
406 guchar *cert_chain_data = NULL;
407 struct sev_user_data_pdh_cert_export export = {};
408 int err, r;
409
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;
417 }
418 }
419
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;
424
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;
430 }
431
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;
437
438 e_free:
439 g_free(pdh_data);
440 g_free(cert_chain_data);
441 return 1;
442 }
443
444 SevCapability *
445 sev_get_capabilities(Error **errp)
446 {
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;
453
454 if (!kvm_enabled()) {
455 error_setg(errp, "KVM not enabled");
456 return NULL;
457 }
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;
461 }
462
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;
468 }
469
470 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
471 &cert_chain_data, &cert_chain_len, errp)) {
472 goto out;
473 }
474
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);
478
479 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
480 cap->cbitpos = ebx & 0x3f;
481
482 /*
483 * When SEV feature is enabled, we loose one bit in guest physical
484 * addressing.
485 */
486 cap->reduced_phys_bits = 1;
487
488 out:
489 g_free(pdh_data);
490 g_free(cert_chain_data);
491 close(fd);
492 return cap;
493 }
494
495 static int
496 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
497 {
498 gsize sz;
499 gchar *base64;
500 GError *error = NULL;
501
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;
506 }
507
508 *data = g_base64_decode(base64, len);
509 return 0;
510 }
511
512 static int
513 sev_launch_start(SevGuestState *sev)
514 {
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;
520
521 start = g_new0(struct kvm_sev_launch_start, 1);
522
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;
528 }
529 start->session_uaddr = (unsigned long)session;
530 start->session_len = sz;
531 }
532
533 if (sev->dh_cert_file) {
534 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
535 goto out;
536 }
537 start->dh_uaddr = (unsigned long)dh_cert;
538 start->dh_len = sz;
539 }
540
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;
547 }
548
549 sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
550 sev->handle = start->handle;
551 ret = 0;
552
553 out:
554 g_free(start);
555 g_free(session);
556 g_free(dh_cert);
557 return ret;
558 }
559
560 static int
561 sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
562 {
563 int ret, fw_error;
564 struct kvm_sev_launch_update_data update;
565
566 if (!addr || !len) {
567 return 1;
568 }
569
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));
578 }
579
580 return ret;
581 }
582
583 static void
584 sev_launch_get_measure(Notifier *notifier, void *unused)
585 {
586 SevGuestState *sev = sev_guest;
587 int ret, error;
588 guchar *data;
589 struct kvm_sev_launch_measure *measurement;
590
591 if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
592 return;
593 }
594
595 measurement = g_new0(struct kvm_sev_launch_measure, 1);
596
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;
604 }
605
606 data = g_new0(guchar, measurement->len);
607 measurement->uaddr = (unsigned long)data;
608
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;
616 }
617
618 sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
619
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);
623
624 free_data:
625 g_free(data);
626 free_measurement:
627 g_free(measurement);
628 }
629
630 char *
631 sev_get_launch_measurement(void)
632 {
633 if (sev_guest &&
634 sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
635 return g_strdup(sev_guest->measurement);
636 }
637
638 return NULL;
639 }
640
641 static Notifier sev_machine_done_notify = {
642 .notify = sev_launch_get_measure,
643 };
644
645 static void
646 sev_launch_finish(SevGuestState *sev)
647 {
648 int ret, error;
649 Error *local_err = NULL;
650
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);
657 }
658
659 sev_set_guest_state(sev, SEV_STATE_RUNNING);
660
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);
669 }
670 }
671
672 static void
673 sev_vm_state_change(void *opaque, int running, RunState state)
674 {
675 SevGuestState *sev = opaque;
676
677 if (running) {
678 if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
679 sev_launch_finish(sev);
680 }
681 }
682 }
683
684 void *
685 sev_guest_init(const char *id)
686 {
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 = {};
693
694 ret = ram_block_discard_disable(true);
695 if (ret) {
696 error_report("%s: cannot disable RAM discard", __func__);
697 return NULL;
698 }
699
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;
705 }
706
707 sev_guest = sev;
708 sev->state = SEV_STATE_UNINIT;
709
710 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
711 host_cbitpos = ebx & 0x3f;
712
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;
717 }
718
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;
723 }
724
725 sev->me_mask = ~(1UL << sev->cbitpos);
726
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));
732 }
733 g_free(devname);
734 if (sev->sev_fd < 0) {
735 goto err;
736 }
737
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;
745 }
746 sev->build_id = status.build;
747 sev->api_major = status.api_major;
748 sev->api_minor = status.api_minor;
749
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;
756 }
757
758 ret = sev_launch_start(sev);
759 if (ret) {
760 error_report("%s: failed to create encryption context", __func__);
761 goto err;
762 }
763
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);
767
768 return sev;
769 err:
770 sev_guest = NULL;
771 ram_block_discard_disable(false);
772 return NULL;
773 }
774
775 int
776 sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
777 {
778 SevGuestState *sev = handle;
779
780 assert(sev);
781
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);
785 }
786
787 return 0;
788 }
789
790 static void
791 sev_register_types(void)
792 {
793 type_register_static(&sev_guest_info);
794 }
795
796 type_init(sev_register_types);