xref: /qemu/target/i386/sev.c (revision 4e2d8bf6)
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
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
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 *
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
114 sev_check_state(SevState state)
115 {
116     assert(sev_state);
117     return sev_state->state == state ? true : false;
118 }
119 
120 static void
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
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
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
194 qsev_guest_finalize(Object *obj)
195 {
196 }
197 
198 static char *
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
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 *
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
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 *
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
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
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
270 qsev_guest_set_handle(Object *obj, Visitor *v, const char *name,
271                       void *opaque, Error **errp)
272 {
273     QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
274     uint32_t value;
275 
276     visit_type_uint32(v, name, &value, errp);
277     sev->handle = value;
278 }
279 
280 static void
281 qsev_guest_set_policy(Object *obj, Visitor *v, const char *name,
282                       void *opaque, Error **errp)
283 {
284     QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
285     uint32_t value;
286 
287     visit_type_uint32(v, name, &value, errp);
288     sev->policy = value;
289 }
290 
291 static void
292 qsev_guest_set_cbitpos(Object *obj, Visitor *v, const char *name,
293                        void *opaque, Error **errp)
294 {
295     QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
296     uint32_t value;
297 
298     visit_type_uint32(v, name, &value, errp);
299     sev->cbitpos = value;
300 }
301 
302 static void
303 qsev_guest_set_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
304                                    void *opaque, Error **errp)
305 {
306     QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
307     uint32_t value;
308 
309     visit_type_uint32(v, name, &value, errp);
310     sev->reduced_phys_bits = value;
311 }
312 
313 static void
314 qsev_guest_get_policy(Object *obj, Visitor *v, const char *name,
315                       void *opaque, Error **errp)
316 {
317     uint32_t value;
318     QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
319 
320     value = sev->policy;
321     visit_type_uint32(v, name, &value, errp);
322 }
323 
324 static void
325 qsev_guest_get_handle(Object *obj, Visitor *v, const char *name,
326                       void *opaque, Error **errp)
327 {
328     uint32_t value;
329     QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
330 
331     value = sev->handle;
332     visit_type_uint32(v, name, &value, errp);
333 }
334 
335 static void
336 qsev_guest_get_cbitpos(Object *obj, Visitor *v, const char *name,
337                        void *opaque, Error **errp)
338 {
339     uint32_t value;
340     QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
341 
342     value = sev->cbitpos;
343     visit_type_uint32(v, name, &value, errp);
344 }
345 
346 static void
347 qsev_guest_get_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
348                                    void *opaque, Error **errp)
349 {
350     uint32_t value;
351     QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
352 
353     value = sev->reduced_phys_bits;
354     visit_type_uint32(v, name, &value, errp);
355 }
356 
357 static void
358 qsev_guest_init(Object *obj)
359 {
360     QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
361 
362     sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
363     sev->policy = DEFAULT_GUEST_POLICY;
364     object_property_add(obj, "policy", "uint32", qsev_guest_get_policy,
365                         qsev_guest_set_policy, NULL, NULL, NULL);
366     object_property_add(obj, "handle", "uint32", qsev_guest_get_handle,
367                         qsev_guest_set_handle, NULL, NULL, NULL);
368     object_property_add(obj, "cbitpos", "uint32", qsev_guest_get_cbitpos,
369                         qsev_guest_set_cbitpos, NULL, NULL, NULL);
370     object_property_add(obj, "reduced-phys-bits", "uint32",
371                         qsev_guest_get_reduced_phys_bits,
372                         qsev_guest_set_reduced_phys_bits, NULL, NULL, NULL);
373 }
374 
375 /* sev guest info */
376 static const TypeInfo qsev_guest_info = {
377     .parent = TYPE_OBJECT,
378     .name = TYPE_QSEV_GUEST_INFO,
379     .instance_size = sizeof(QSevGuestInfo),
380     .instance_finalize = qsev_guest_finalize,
381     .class_size = sizeof(QSevGuestInfoClass),
382     .class_init = qsev_guest_class_init,
383     .instance_init = qsev_guest_init,
384     .interfaces = (InterfaceInfo[]) {
385         { TYPE_USER_CREATABLE },
386         { }
387     }
388 };
389 
390 static QSevGuestInfo *
391 lookup_sev_guest_info(const char *id)
392 {
393     Object *obj;
394     QSevGuestInfo *info;
395 
396     obj = object_resolve_path_component(object_get_objects_root(), id);
397     if (!obj) {
398         return NULL;
399     }
400 
401     info = (QSevGuestInfo *)
402             object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO);
403     if (!info) {
404         return NULL;
405     }
406 
407     return info;
408 }
409 
410 bool
411 sev_enabled(void)
412 {
413     return sev_state ? true : false;
414 }
415 
416 uint64_t
417 sev_get_me_mask(void)
418 {
419     return sev_state ? sev_state->me_mask : ~0;
420 }
421 
422 uint32_t
423 sev_get_cbit_position(void)
424 {
425     return sev_state ? sev_state->cbitpos : 0;
426 }
427 
428 uint32_t
429 sev_get_reduced_phys_bits(void)
430 {
431     return sev_state ? sev_state->reduced_phys_bits : 0;
432 }
433 
434 SevInfo *
435 sev_get_info(void)
436 {
437     SevInfo *info;
438 
439     info = g_new0(SevInfo, 1);
440     info->enabled = sev_state ? true : false;
441 
442     if (info->enabled) {
443         info->api_major = sev_state->api_major;
444         info->api_minor = sev_state->api_minor;
445         info->build_id = sev_state->build_id;
446         info->policy = sev_state->policy;
447         info->state = sev_state->state;
448         info->handle = sev_state->handle;
449     }
450 
451     return info;
452 }
453 
454 static int
455 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
456                  size_t *cert_chain_len)
457 {
458     guchar *pdh_data = NULL;
459     guchar *cert_chain_data = NULL;
460     struct sev_user_data_pdh_cert_export export = {};
461     int err, r;
462 
463     /* query the certificate length */
464     r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
465     if (r < 0) {
466         if (err != SEV_RET_INVALID_LEN) {
467             error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
468                          r, err, fw_error_to_str(err));
469             return 1;
470         }
471     }
472 
473     pdh_data = g_new(guchar, export.pdh_cert_len);
474     cert_chain_data = g_new(guchar, export.cert_chain_len);
475     export.pdh_cert_address = (unsigned long)pdh_data;
476     export.cert_chain_address = (unsigned long)cert_chain_data;
477 
478     r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
479     if (r < 0) {
480         error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
481                      r, err, fw_error_to_str(err));
482         goto e_free;
483     }
484 
485     *pdh = pdh_data;
486     *pdh_len = export.pdh_cert_len;
487     *cert_chain = cert_chain_data;
488     *cert_chain_len = export.cert_chain_len;
489     return 0;
490 
491 e_free:
492     g_free(pdh_data);
493     g_free(cert_chain_data);
494     return 1;
495 }
496 
497 SevCapability *
498 sev_get_capabilities(void)
499 {
500     SevCapability *cap = NULL;
501     guchar *pdh_data = NULL;
502     guchar *cert_chain_data = NULL;
503     size_t pdh_len = 0, cert_chain_len = 0;
504     uint32_t ebx;
505     int fd;
506 
507     fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
508     if (fd < 0) {
509         error_report("%s: Failed to open %s '%s'", __func__,
510                      DEFAULT_SEV_DEVICE, strerror(errno));
511         return NULL;
512     }
513 
514     if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
515                          &cert_chain_data, &cert_chain_len)) {
516         goto out;
517     }
518 
519     cap = g_new0(SevCapability, 1);
520     cap->pdh = g_base64_encode(pdh_data, pdh_len);
521     cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
522 
523     host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
524     cap->cbitpos = ebx & 0x3f;
525 
526     /*
527      * When SEV feature is enabled, we loose one bit in guest physical
528      * addressing.
529      */
530     cap->reduced_phys_bits = 1;
531 
532 out:
533     g_free(pdh_data);
534     g_free(cert_chain_data);
535     close(fd);
536     return cap;
537 }
538 
539 static int
540 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
541 {
542     gsize sz;
543     gchar *base64;
544     GError *error = NULL;
545 
546     if (!g_file_get_contents(filename, &base64, &sz, &error)) {
547         error_report("failed to read '%s' (%s)", filename, error->message);
548         return -1;
549     }
550 
551     *data = g_base64_decode(base64, len);
552     return 0;
553 }
554 
555 static int
556 sev_launch_start(SEVState *s)
557 {
558     gsize sz;
559     int ret = 1;
560     int fw_error, rc;
561     QSevGuestInfo *sev = s->sev_info;
562     struct kvm_sev_launch_start *start;
563     guchar *session = NULL, *dh_cert = NULL;
564 
565     start = g_new0(struct kvm_sev_launch_start, 1);
566 
567     start->handle = object_property_get_int(OBJECT(sev), "handle",
568                                             &error_abort);
569     start->policy = object_property_get_int(OBJECT(sev), "policy",
570                                             &error_abort);
571     if (sev->session_file) {
572         if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
573             goto out;
574         }
575         start->session_uaddr = (unsigned long)session;
576         start->session_len = sz;
577     }
578 
579     if (sev->dh_cert_file) {
580         if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
581             goto out;
582         }
583         start->dh_uaddr = (unsigned long)dh_cert;
584         start->dh_len = sz;
585     }
586 
587     trace_kvm_sev_launch_start(start->policy, session, dh_cert);
588     rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
589     if (rc < 0) {
590         error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
591                 __func__, ret, fw_error, fw_error_to_str(fw_error));
592         goto out;
593     }
594 
595     object_property_set_int(OBJECT(sev), start->handle, "handle",
596                             &error_abort);
597     sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE);
598     s->handle = start->handle;
599     s->policy = start->policy;
600     ret = 0;
601 
602 out:
603     g_free(start);
604     g_free(session);
605     g_free(dh_cert);
606     return ret;
607 }
608 
609 static int
610 sev_launch_update_data(uint8_t *addr, uint64_t len)
611 {
612     int ret, fw_error;
613     struct kvm_sev_launch_update_data update;
614 
615     if (!addr || !len) {
616         return 1;
617     }
618 
619     update.uaddr = (__u64)(unsigned long)addr;
620     update.len = len;
621     trace_kvm_sev_launch_update_data(addr, len);
622     ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
623                     &update, &fw_error);
624     if (ret) {
625         error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
626                 __func__, ret, fw_error, fw_error_to_str(fw_error));
627     }
628 
629     return ret;
630 }
631 
632 static void
633 sev_launch_get_measure(Notifier *notifier, void *unused)
634 {
635     int ret, error;
636     guchar *data;
637     SEVState *s = sev_state;
638     struct kvm_sev_launch_measure *measurement;
639 
640     if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE)) {
641         return;
642     }
643 
644     measurement = g_new0(struct kvm_sev_launch_measure, 1);
645 
646     /* query the measurement blob length */
647     ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE,
648                     measurement, &error);
649     if (!measurement->len) {
650         error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
651                      __func__, ret, error, fw_error_to_str(errno));
652         goto free_measurement;
653     }
654 
655     data = g_new0(guchar, measurement->len);
656     measurement->uaddr = (unsigned long)data;
657 
658     /* get the measurement blob */
659     ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE,
660                     measurement, &error);
661     if (ret) {
662         error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
663                      __func__, ret, error, fw_error_to_str(errno));
664         goto free_data;
665     }
666 
667     sev_set_guest_state(SEV_STATE_LAUNCH_SECRET);
668 
669     /* encode the measurement value and emit the event */
670     s->measurement = g_base64_encode(data, measurement->len);
671     trace_kvm_sev_launch_measurement(s->measurement);
672 
673 free_data:
674     g_free(data);
675 free_measurement:
676     g_free(measurement);
677 }
678 
679 char *
680 sev_get_launch_measurement(void)
681 {
682     if (sev_state &&
683         sev_state->state >= SEV_STATE_LAUNCH_SECRET) {
684         return g_strdup(sev_state->measurement);
685     }
686 
687     return NULL;
688 }
689 
690 static Notifier sev_machine_done_notify = {
691     .notify = sev_launch_get_measure,
692 };
693 
694 static void
695 sev_launch_finish(SEVState *s)
696 {
697     int ret, error;
698     Error *local_err = NULL;
699 
700     trace_kvm_sev_launch_finish();
701     ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
702     if (ret) {
703         error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
704                      __func__, ret, error, fw_error_to_str(error));
705         exit(1);
706     }
707 
708     sev_set_guest_state(SEV_STATE_RUNNING);
709 
710     /* add migration blocker */
711     error_setg(&sev_mig_blocker,
712                "SEV: Migration is not implemented");
713     ret = migrate_add_blocker(sev_mig_blocker, &local_err);
714     if (local_err) {
715         error_report_err(local_err);
716         error_free(sev_mig_blocker);
717         exit(1);
718     }
719 }
720 
721 static void
722 sev_vm_state_change(void *opaque, int running, RunState state)
723 {
724     SEVState *s = opaque;
725 
726     if (running) {
727         if (!sev_check_state(SEV_STATE_RUNNING)) {
728             sev_launch_finish(s);
729         }
730     }
731 }
732 
733 void *
734 sev_guest_init(const char *id)
735 {
736     SEVState *s;
737     char *devname;
738     int ret, fw_error;
739     uint32_t ebx;
740     uint32_t host_cbitpos;
741     struct sev_user_data_status status = {};
742 
743     sev_state = s = g_new0(SEVState, 1);
744     s->sev_info = lookup_sev_guest_info(id);
745     if (!s->sev_info) {
746         error_report("%s: '%s' is not a valid '%s' object",
747                      __func__, id, TYPE_QSEV_GUEST_INFO);
748         goto err;
749     }
750 
751     s->state = SEV_STATE_UNINIT;
752 
753     host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
754     host_cbitpos = ebx & 0x3f;
755 
756     s->cbitpos = object_property_get_int(OBJECT(s->sev_info), "cbitpos", NULL);
757     if (host_cbitpos != s->cbitpos) {
758         error_report("%s: cbitpos check failed, host '%d' requested '%d'",
759                      __func__, host_cbitpos, s->cbitpos);
760         goto err;
761     }
762 
763     s->reduced_phys_bits = object_property_get_int(OBJECT(s->sev_info),
764                                         "reduced-phys-bits", NULL);
765     if (s->reduced_phys_bits < 1) {
766         error_report("%s: reduced_phys_bits check failed, it should be >=1,"
767                      " requested '%d'", __func__, s->reduced_phys_bits);
768         goto err;
769     }
770 
771     s->me_mask = ~(1UL << s->cbitpos);
772 
773     devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL);
774     s->sev_fd = open(devname, O_RDWR);
775     if (s->sev_fd < 0) {
776         error_report("%s: Failed to open %s '%s'", __func__,
777                      devname, strerror(errno));
778     }
779     g_free(devname);
780     if (s->sev_fd < 0) {
781         goto err;
782     }
783 
784     ret = sev_platform_ioctl(s->sev_fd, SEV_PLATFORM_STATUS, &status,
785                              &fw_error);
786     if (ret) {
787         error_report("%s: failed to get platform status ret=%d "
788                      "fw_error='%d: %s'", __func__, ret, fw_error,
789                      fw_error_to_str(fw_error));
790         goto err;
791     }
792     s->build_id = status.build;
793     s->api_major = status.api_major;
794     s->api_minor = status.api_minor;
795 
796     trace_kvm_sev_init();
797     ret = sev_ioctl(s->sev_fd, KVM_SEV_INIT, NULL, &fw_error);
798     if (ret) {
799         error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
800                      __func__, ret, fw_error, fw_error_to_str(fw_error));
801         goto err;
802     }
803 
804     ret = sev_launch_start(s);
805     if (ret) {
806         error_report("%s: failed to create encryption context", __func__);
807         goto err;
808     }
809 
810     ram_block_notifier_add(&sev_ram_notifier);
811     qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
812     qemu_add_vm_change_state_handler(sev_vm_state_change, s);
813 
814     return s;
815 err:
816     g_free(sev_state);
817     sev_state = NULL;
818     return NULL;
819 }
820 
821 int
822 sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
823 {
824     assert(handle);
825 
826     /* if SEV is in update state then encrypt the data else do nothing */
827     if (sev_check_state(SEV_STATE_LAUNCH_UPDATE)) {
828         return sev_launch_update_data(ptr, len);
829     }
830 
831     return 0;
832 }
833 
834 static void
835 sev_register_types(void)
836 {
837     type_register_static(&qsev_guest_info);
838 }
839 
840 type_init(sev_register_types);
841