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