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