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