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