1
2
3
4
5
6
7
8
9
10
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 "sysemu/kvm.h"
25#include "sev_i386.h"
26#include "sysemu/sysemu.h"
27#include "trace.h"
28#include "migration/blocker.h"
29
30#define DEFAULT_GUEST_POLICY 0x1
31#define DEFAULT_SEV_DEVICE "/dev/sev"
32
33static SEVState *sev_state;
34static Error *sev_mig_blocker;
35
36static const char *const sev_fw_errlist[] = {
37 "",
38 "Platform state is invalid",
39 "Guest state is invalid",
40 "Platform configuration is invalid",
41 "Buffer too small",
42 "Platform is already owned",
43 "Certificate is invalid",
44 "Policy is not allowed",
45 "Guest is not active",
46 "Invalid address",
47 "Bad signature",
48 "Bad measurement",
49 "Asid is already owned",
50 "Invalid ASID",
51 "WBINVD is required",
52 "DF_FLUSH is required",
53 "Guest handle is invalid",
54 "Invalid command",
55 "Guest is active",
56 "Hardware error",
57 "Hardware unsafe",
58 "Feature not supported",
59 "Invalid parameter"
60};
61
62#define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
63
64static int
65sev_ioctl(int fd, int cmd, void *data, int *error)
66{
67 int r;
68 struct kvm_sev_cmd input;
69
70 memset(&input, 0x0, sizeof(input));
71
72 input.id = cmd;
73 input.sev_fd = fd;
74 input.data = (__u64)(unsigned long)data;
75
76 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
77
78 if (error) {
79 *error = input.error;
80 }
81
82 return r;
83}
84
85static int
86sev_platform_ioctl(int fd, int cmd, void *data, int *error)
87{
88 int r;
89 struct sev_issue_cmd arg;
90
91 arg.cmd = cmd;
92 arg.data = (unsigned long)data;
93 r = ioctl(fd, SEV_ISSUE_CMD, &arg);
94 if (error) {
95 *error = arg.error;
96 }
97
98 return r;
99}
100
101static const char *
102fw_error_to_str(int code)
103{
104 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
105 return "unknown error";
106 }
107
108 return sev_fw_errlist[code];
109}
110
111static bool
112sev_check_state(SevState state)
113{
114 assert(sev_state);
115 return sev_state->state == state ? true : false;
116}
117
118static void
119sev_set_guest_state(SevState new_state)
120{
121 assert(new_state < SEV_STATE__MAX);
122 assert(sev_state);
123
124 trace_kvm_sev_change_state(SevState_str(sev_state->state),
125 SevState_str(new_state));
126 sev_state->state = new_state;
127}
128
129static void
130sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
131{
132 int r;
133 struct kvm_enc_region range;
134 ram_addr_t offset;
135 MemoryRegion *mr;
136
137
138
139
140
141 mr = memory_region_from_host(host, &offset);
142 if (mr && memory_region_is_ram_device(mr)) {
143 return;
144 }
145
146 range.addr = (__u64)(unsigned long)host;
147 range.size = size;
148
149 trace_kvm_memcrypt_register_region(host, size);
150 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
151 if (r) {
152 error_report("%s: failed to register region (%p+%#zx) error '%s'",
153 __func__, host, size, strerror(errno));
154 exit(1);
155 }
156}
157
158static void
159sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
160{
161 int r;
162 struct kvm_enc_region range;
163
164 range.addr = (__u64)(unsigned long)host;
165 range.size = size;
166
167 trace_kvm_memcrypt_unregister_region(host, size);
168 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
169 if (r) {
170 error_report("%s: failed to unregister region (%p+%#zx)",
171 __func__, host, size);
172 }
173}
174
175static struct RAMBlockNotifier sev_ram_notifier = {
176 .ram_block_added = sev_ram_block_added,
177 .ram_block_removed = sev_ram_block_removed,
178};
179
180static void
181qsev_guest_finalize(Object *obj)
182{
183}
184
185static char *
186qsev_guest_get_session_file(Object *obj, Error **errp)
187{
188 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
189
190 return s->session_file ? g_strdup(s->session_file) : NULL;
191}
192
193static void
194qsev_guest_set_session_file(Object *obj, const char *value, Error **errp)
195{
196 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
197
198 s->session_file = g_strdup(value);
199}
200
201static char *
202qsev_guest_get_dh_cert_file(Object *obj, Error **errp)
203{
204 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
205
206 return g_strdup(s->dh_cert_file);
207}
208
209static void
210qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
211{
212 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
213
214 s->dh_cert_file = g_strdup(value);
215}
216
217static char *
218qsev_guest_get_sev_device(Object *obj, Error **errp)
219{
220 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
221
222 return g_strdup(sev->sev_device);
223}
224
225static void
226qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
227{
228 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
229
230 sev->sev_device = g_strdup(value);
231}
232
233static void
234qsev_guest_class_init(ObjectClass *oc, void *data)
235{
236 object_class_property_add_str(oc, "sev-device",
237 qsev_guest_get_sev_device,
238 qsev_guest_set_sev_device,
239 NULL);
240 object_class_property_set_description(oc, "sev-device",
241 "SEV device to use", NULL);
242 object_class_property_add_str(oc, "dh-cert-file",
243 qsev_guest_get_dh_cert_file,
244 qsev_guest_set_dh_cert_file,
245 NULL);
246 object_class_property_set_description(oc, "dh-cert-file",
247 "guest owners DH certificate (encoded with base64)", NULL);
248 object_class_property_add_str(oc, "session-file",
249 qsev_guest_get_session_file,
250 qsev_guest_set_session_file,
251 NULL);
252 object_class_property_set_description(oc, "session-file",
253 "guest owners session parameters (encoded with base64)", NULL);
254}
255
256static void
257qsev_guest_set_handle(Object *obj, Visitor *v, const char *name,
258 void *opaque, Error **errp)
259{
260 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
261 uint32_t value;
262
263 visit_type_uint32(v, name, &value, errp);
264 sev->handle = value;
265}
266
267static void
268qsev_guest_set_policy(Object *obj, Visitor *v, const char *name,
269 void *opaque, Error **errp)
270{
271 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
272 uint32_t value;
273
274 visit_type_uint32(v, name, &value, errp);
275 sev->policy = value;
276}
277
278static void
279qsev_guest_set_cbitpos(Object *obj, Visitor *v, const char *name,
280 void *opaque, Error **errp)
281{
282 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
283 uint32_t value;
284
285 visit_type_uint32(v, name, &value, errp);
286 sev->cbitpos = value;
287}
288
289static void
290qsev_guest_set_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
291 void *opaque, Error **errp)
292{
293 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
294 uint32_t value;
295
296 visit_type_uint32(v, name, &value, errp);
297 sev->reduced_phys_bits = value;
298}
299
300static void
301qsev_guest_get_policy(Object *obj, Visitor *v, const char *name,
302 void *opaque, Error **errp)
303{
304 uint32_t value;
305 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
306
307 value = sev->policy;
308 visit_type_uint32(v, name, &value, errp);
309}
310
311static void
312qsev_guest_get_handle(Object *obj, Visitor *v, const char *name,
313 void *opaque, Error **errp)
314{
315 uint32_t value;
316 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
317
318 value = sev->handle;
319 visit_type_uint32(v, name, &value, errp);
320}
321
322static void
323qsev_guest_get_cbitpos(Object *obj, Visitor *v, const char *name,
324 void *opaque, Error **errp)
325{
326 uint32_t value;
327 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
328
329 value = sev->cbitpos;
330 visit_type_uint32(v, name, &value, errp);
331}
332
333static void
334qsev_guest_get_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
335 void *opaque, Error **errp)
336{
337 uint32_t value;
338 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
339
340 value = sev->reduced_phys_bits;
341 visit_type_uint32(v, name, &value, errp);
342}
343
344static void
345qsev_guest_init(Object *obj)
346{
347 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
348
349 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
350 sev->policy = DEFAULT_GUEST_POLICY;
351 object_property_add(obj, "policy", "uint32", qsev_guest_get_policy,
352 qsev_guest_set_policy, NULL, NULL, NULL);
353 object_property_add(obj, "handle", "uint32", qsev_guest_get_handle,
354 qsev_guest_set_handle, NULL, NULL, NULL);
355 object_property_add(obj, "cbitpos", "uint32", qsev_guest_get_cbitpos,
356 qsev_guest_set_cbitpos, NULL, NULL, NULL);
357 object_property_add(obj, "reduced-phys-bits", "uint32",
358 qsev_guest_get_reduced_phys_bits,
359 qsev_guest_set_reduced_phys_bits, NULL, NULL, NULL);
360}
361
362
363static const TypeInfo qsev_guest_info = {
364 .parent = TYPE_OBJECT,
365 .name = TYPE_QSEV_GUEST_INFO,
366 .instance_size = sizeof(QSevGuestInfo),
367 .instance_finalize = qsev_guest_finalize,
368 .class_size = sizeof(QSevGuestInfoClass),
369 .class_init = qsev_guest_class_init,
370 .instance_init = qsev_guest_init,
371 .interfaces = (InterfaceInfo[]) {
372 { TYPE_USER_CREATABLE },
373 { }
374 }
375};
376
377static QSevGuestInfo *
378lookup_sev_guest_info(const char *id)
379{
380 Object *obj;
381 QSevGuestInfo *info;
382
383 obj = object_resolve_path_component(object_get_objects_root(), id);
384 if (!obj) {
385 return NULL;
386 }
387
388 info = (QSevGuestInfo *)
389 object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO);
390 if (!info) {
391 return NULL;
392 }
393
394 return info;
395}
396
397bool
398sev_enabled(void)
399{
400 return sev_state ? true : false;
401}
402
403uint64_t
404sev_get_me_mask(void)
405{
406 return sev_state ? sev_state->me_mask : ~0;
407}
408
409uint32_t
410sev_get_cbit_position(void)
411{
412 return sev_state ? sev_state->cbitpos : 0;
413}
414
415uint32_t
416sev_get_reduced_phys_bits(void)
417{
418 return sev_state ? sev_state->reduced_phys_bits : 0;
419}
420
421SevInfo *
422sev_get_info(void)
423{
424 SevInfo *info;
425
426 info = g_new0(SevInfo, 1);
427 info->enabled = sev_state ? true : false;
428
429 if (info->enabled) {
430 info->api_major = sev_state->api_major;
431 info->api_minor = sev_state->api_minor;
432 info->build_id = sev_state->build_id;
433 info->policy = sev_state->policy;
434 info->state = sev_state->state;
435 info->handle = sev_state->handle;
436 }
437
438 return info;
439}
440
441static int
442sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
443 size_t *cert_chain_len)
444{
445 guchar *pdh_data = NULL;
446 guchar *cert_chain_data = NULL;
447 struct sev_user_data_pdh_cert_export export = {};
448 int err, r;
449
450
451 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
452 if (r < 0) {
453 if (err != SEV_RET_INVALID_LEN) {
454 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
455 r, err, fw_error_to_str(err));
456 return 1;
457 }
458 }
459
460 pdh_data = g_new(guchar, export.pdh_cert_len);
461 cert_chain_data = g_new(guchar, export.cert_chain_len);
462 export.pdh_cert_address = (unsigned long)pdh_data;
463 export.cert_chain_address = (unsigned long)cert_chain_data;
464
465 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
466 if (r < 0) {
467 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
468 r, err, fw_error_to_str(err));
469 goto e_free;
470 }
471
472 *pdh = pdh_data;
473 *pdh_len = export.pdh_cert_len;
474 *cert_chain = cert_chain_data;
475 *cert_chain_len = export.cert_chain_len;
476 return 0;
477
478e_free:
479 g_free(pdh_data);
480 g_free(cert_chain_data);
481 return 1;
482}
483
484SevCapability *
485sev_get_capabilities(void)
486{
487 SevCapability *cap = NULL;
488 guchar *pdh_data = NULL;
489 guchar *cert_chain_data = NULL;
490 size_t pdh_len = 0, cert_chain_len = 0;
491 uint32_t ebx;
492 int fd;
493
494 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
495 if (fd < 0) {
496 error_report("%s: Failed to open %s '%s'", __func__,
497 DEFAULT_SEV_DEVICE, strerror(errno));
498 return NULL;
499 }
500
501 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
502 &cert_chain_data, &cert_chain_len)) {
503 goto out;
504 }
505
506 cap = g_new0(SevCapability, 1);
507 cap->pdh = g_base64_encode(pdh_data, pdh_len);
508 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
509
510 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
511 cap->cbitpos = ebx & 0x3f;
512
513
514
515
516
517 cap->reduced_phys_bits = 1;
518
519out:
520 g_free(pdh_data);
521 g_free(cert_chain_data);
522 close(fd);
523 return cap;
524}
525
526static int
527sev_read_file_base64(const char *filename, guchar **data, gsize *len)
528{
529 gsize sz;
530 gchar *base64;
531 GError *error = NULL;
532
533 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
534 error_report("failed to read '%s' (%s)", filename, error->message);
535 return -1;
536 }
537
538 *data = g_base64_decode(base64, len);
539 return 0;
540}
541
542static int
543sev_launch_start(SEVState *s)
544{
545 gsize sz;
546 int ret = 1;
547 int fw_error, rc;
548 QSevGuestInfo *sev = s->sev_info;
549 struct kvm_sev_launch_start *start;
550 guchar *session = NULL, *dh_cert = NULL;
551
552 start = g_new0(struct kvm_sev_launch_start, 1);
553
554 start->handle = object_property_get_int(OBJECT(sev), "handle",
555 &error_abort);
556 start->policy = object_property_get_int(OBJECT(sev), "policy",
557 &error_abort);
558 if (sev->session_file) {
559 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
560 goto out;
561 }
562 start->session_uaddr = (unsigned long)session;
563 start->session_len = sz;
564 }
565
566 if (sev->dh_cert_file) {
567 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
568 goto out;
569 }
570 start->dh_uaddr = (unsigned long)dh_cert;
571 start->dh_len = sz;
572 }
573
574 trace_kvm_sev_launch_start(start->policy, session, dh_cert);
575 rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
576 if (rc < 0) {
577 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
578 __func__, ret, fw_error, fw_error_to_str(fw_error));
579 goto out;
580 }
581
582 object_property_set_int(OBJECT(sev), start->handle, "handle",
583 &error_abort);
584 sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE);
585 s->handle = start->handle;
586 s->policy = start->policy;
587 ret = 0;
588
589out:
590 g_free(start);
591 g_free(session);
592 g_free(dh_cert);
593 return ret;
594}
595
596static int
597sev_launch_update_data(uint8_t *addr, uint64_t len)
598{
599 int ret, fw_error;
600 struct kvm_sev_launch_update_data update;
601
602 if (!addr || !len) {
603 return 1;
604 }
605
606 update.uaddr = (__u64)(unsigned long)addr;
607 update.len = len;
608 trace_kvm_sev_launch_update_data(addr, len);
609 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
610 &update, &fw_error);
611 if (ret) {
612 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
613 __func__, ret, fw_error, fw_error_to_str(fw_error));
614 }
615
616 return ret;
617}
618
619static void
620sev_launch_get_measure(Notifier *notifier, void *unused)
621{
622 int ret, error;
623 guchar *data;
624 SEVState *s = sev_state;
625 struct kvm_sev_launch_measure *measurement;
626
627 if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE)) {
628 return;
629 }
630
631 measurement = g_new0(struct kvm_sev_launch_measure, 1);
632
633
634 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE,
635 measurement, &error);
636 if (!measurement->len) {
637 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
638 __func__, ret, error, fw_error_to_str(errno));
639 goto free_measurement;
640 }
641
642 data = g_new0(guchar, measurement->len);
643 measurement->uaddr = (unsigned long)data;
644
645
646 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE,
647 measurement, &error);
648 if (ret) {
649 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
650 __func__, ret, error, fw_error_to_str(errno));
651 goto free_data;
652 }
653
654 sev_set_guest_state(SEV_STATE_LAUNCH_SECRET);
655
656
657 s->measurement = g_base64_encode(data, measurement->len);
658 trace_kvm_sev_launch_measurement(s->measurement);
659
660free_data:
661 g_free(data);
662free_measurement:
663 g_free(measurement);
664}
665
666char *
667sev_get_launch_measurement(void)
668{
669 if (sev_state &&
670 sev_state->state >= SEV_STATE_LAUNCH_SECRET) {
671 return g_strdup(sev_state->measurement);
672 }
673
674 return NULL;
675}
676
677static Notifier sev_machine_done_notify = {
678 .notify = sev_launch_get_measure,
679};
680
681static void
682sev_launch_finish(SEVState *s)
683{
684 int ret, error;
685 Error *local_err = NULL;
686
687 trace_kvm_sev_launch_finish();
688 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
689 if (ret) {
690 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
691 __func__, ret, error, fw_error_to_str(error));
692 exit(1);
693 }
694
695 sev_set_guest_state(SEV_STATE_RUNNING);
696
697
698 error_setg(&sev_mig_blocker,
699 "SEV: Migration is not implemented");
700 ret = migrate_add_blocker(sev_mig_blocker, &local_err);
701 if (local_err) {
702 error_report_err(local_err);
703 error_free(sev_mig_blocker);
704 exit(1);
705 }
706}
707
708static void
709sev_vm_state_change(void *opaque, int running, RunState state)
710{
711 SEVState *s = opaque;
712
713 if (running) {
714 if (!sev_check_state(SEV_STATE_RUNNING)) {
715 sev_launch_finish(s);
716 }
717 }
718}
719
720void *
721sev_guest_init(const char *id)
722{
723 SEVState *s;
724 char *devname;
725 int ret, fw_error;
726 uint32_t ebx;
727 uint32_t host_cbitpos;
728 struct sev_user_data_status status = {};
729
730 sev_state = s = g_new0(SEVState, 1);
731 s->sev_info = lookup_sev_guest_info(id);
732 if (!s->sev_info) {
733 error_report("%s: '%s' is not a valid '%s' object",
734 __func__, id, TYPE_QSEV_GUEST_INFO);
735 goto err;
736 }
737
738 s->state = SEV_STATE_UNINIT;
739
740 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
741 host_cbitpos = ebx & 0x3f;
742
743 s->cbitpos = object_property_get_int(OBJECT(s->sev_info), "cbitpos", NULL);
744 if (host_cbitpos != s->cbitpos) {
745 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
746 __func__, host_cbitpos, s->cbitpos);
747 goto err;
748 }
749
750 s->reduced_phys_bits = object_property_get_int(OBJECT(s->sev_info),
751 "reduced-phys-bits", NULL);
752 if (s->reduced_phys_bits < 1) {
753 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
754 "' requested '%d'", __func__, s->reduced_phys_bits);
755 goto err;
756 }
757
758 s->me_mask = ~(1UL << s->cbitpos);
759
760 devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL);
761 s->sev_fd = open(devname, O_RDWR);
762 if (s->sev_fd < 0) {
763 error_report("%s: Failed to open %s '%s'", __func__,
764 devname, strerror(errno));
765 }
766 g_free(devname);
767 if (s->sev_fd < 0) {
768 goto err;
769 }
770
771 ret = sev_platform_ioctl(s->sev_fd, SEV_PLATFORM_STATUS, &status,
772 &fw_error);
773 if (ret) {
774 error_report("%s: failed to get platform status ret=%d"
775 "fw_error='%d: %s'", __func__, ret, fw_error,
776 fw_error_to_str(fw_error));
777 goto err;
778 }
779 s->build_id = status.build;
780 s->api_major = status.api_major;
781 s->api_minor = status.api_minor;
782
783 trace_kvm_sev_init();
784 ret = sev_ioctl(s->sev_fd, KVM_SEV_INIT, NULL, &fw_error);
785 if (ret) {
786 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
787 __func__, ret, fw_error, fw_error_to_str(fw_error));
788 goto err;
789 }
790
791 ret = sev_launch_start(s);
792 if (ret) {
793 error_report("%s: failed to create encryption context", __func__);
794 goto err;
795 }
796
797 ram_block_notifier_add(&sev_ram_notifier);
798 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
799 qemu_add_vm_change_state_handler(sev_vm_state_change, s);
800
801 return s;
802err:
803 g_free(sev_state);
804 sev_state = NULL;
805 return NULL;
806}
807
808int
809sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
810{
811 assert(handle);
812
813
814 if (sev_check_state(SEV_STATE_LAUNCH_UPDATE)) {
815 return sev_launch_update_data(ptr, len);
816 }
817
818 return 0;
819}
820
821static void
822sev_register_types(void)
823{
824 type_register_static(&qsev_guest_info);
825}
826
827type_init(sev_register_types);
828