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