xref: /qemu/target/i386/sev.c (revision e3a6e0da)
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 DECLARE_INSTANCE_CHECKER(SevGuestState, SEV_GUEST,
36                          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);
797