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