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