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