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