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