xref: /qemu/target/i386/sev.c (revision abff1abf)
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         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