qemu-tech.texi: Remove "QEMU compared to other emulators" section
[qemu/ar7.git] / target / i386 / sev.c
blob6dbdc3cdf10f78d9c1a30a9feedee0f0a51f644d
1 /*
2 * QEMU SEV support
4 * Copyright Advanced Micro Devices 2016-2018
6 * Author:
7 * Brijesh Singh <brijesh.singh@amd.com>
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.
14 #include "qemu/osdep.h"
16 #include <linux/kvm.h>
17 #include <linux/psp-sev.h>
19 #include <sys/ioctl.h>
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"
31 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
32 #define DEFAULT_SEV_DEVICE "/dev/sev"
34 static SEVState *sev_state;
35 static Error *sev_mig_blocker;
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"
63 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
65 static int
66 sev_ioctl(int fd, int cmd, void *data, int *error)
68 int r;
69 struct kvm_sev_cmd input;
71 memset(&input, 0x0, sizeof(input));
73 input.id = cmd;
74 input.sev_fd = fd;
75 input.data = (__u64)(unsigned long)data;
77 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
79 if (error) {
80 *error = input.error;
83 return r;
86 static int
87 sev_platform_ioctl(int fd, int cmd, void *data, int *error)
89 int r;
90 struct sev_issue_cmd arg;
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;
99 return r;
102 static const char *
103 fw_error_to_str(int code)
105 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
106 return "unknown error";
109 return sev_fw_errlist[code];
112 static bool
113 sev_check_state(SevState state)
115 assert(sev_state);
116 return sev_state->state == state ? true : false;
119 static void
120 sev_set_guest_state(SevState new_state)
122 assert(new_state < SEV_STATE__MAX);
123 assert(sev_state);
125 trace_kvm_sev_change_state(SevState_str(sev_state->state),
126 SevState_str(new_state));
127 sev_state->state = new_state;
130 static void
131 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
133 int r;
134 struct kvm_enc_region range;
135 ram_addr_t offset;
136 MemoryRegion *mr;
139 * The RAM device presents a memory region that should be treated
140 * as IO region and should not be pinned.
142 mr = memory_region_from_host(host, &offset);
143 if (mr && memory_region_is_ram_device(mr)) {
144 return;
147 range.addr = (__u64)(unsigned long)host;
148 range.size = size;
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);
159 static void
160 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
162 int r;
163 struct kvm_enc_region range;
165 range.addr = (__u64)(unsigned long)host;
166 range.size = size;
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);
176 static struct RAMBlockNotifier sev_ram_notifier = {
177 .ram_block_added = sev_ram_block_added,
178 .ram_block_removed = sev_ram_block_removed,
181 static void
182 qsev_guest_finalize(Object *obj)
186 static char *
187 qsev_guest_get_session_file(Object *obj, Error **errp)
189 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
191 return s->session_file ? g_strdup(s->session_file) : NULL;
194 static void
195 qsev_guest_set_session_file(Object *obj, const char *value, Error **errp)
197 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
199 s->session_file = g_strdup(value);
202 static char *
203 qsev_guest_get_dh_cert_file(Object *obj, Error **errp)
205 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
207 return g_strdup(s->dh_cert_file);
210 static void
211 qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
213 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
215 s->dh_cert_file = g_strdup(value);
218 static char *
219 qsev_guest_get_sev_device(Object *obj, Error **errp)
221 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
223 return g_strdup(sev->sev_device);
226 static void
227 qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
229 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
231 sev->sev_device = g_strdup(value);
234 static void
235 qsev_guest_class_init(ObjectClass *oc, void *data)
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);
257 static void
258 qsev_guest_set_handle(Object *obj, Visitor *v, const char *name,
259 void *opaque, Error **errp)
261 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
262 uint32_t value;
264 visit_type_uint32(v, name, &value, errp);
265 sev->handle = value;
268 static void
269 qsev_guest_set_policy(Object *obj, Visitor *v, const char *name,
270 void *opaque, Error **errp)
272 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
273 uint32_t value;
275 visit_type_uint32(v, name, &value, errp);
276 sev->policy = value;
279 static void
280 qsev_guest_set_cbitpos(Object *obj, Visitor *v, const char *name,
281 void *opaque, Error **errp)
283 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
284 uint32_t value;
286 visit_type_uint32(v, name, &value, errp);
287 sev->cbitpos = value;
290 static void
291 qsev_guest_set_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
292 void *opaque, Error **errp)
294 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
295 uint32_t value;
297 visit_type_uint32(v, name, &value, errp);
298 sev->reduced_phys_bits = value;
301 static void
302 qsev_guest_get_policy(Object *obj, Visitor *v, const char *name,
303 void *opaque, Error **errp)
305 uint32_t value;
306 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
308 value = sev->policy;
309 visit_type_uint32(v, name, &value, errp);
312 static void
313 qsev_guest_get_handle(Object *obj, Visitor *v, const char *name,
314 void *opaque, Error **errp)
316 uint32_t value;
317 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
319 value = sev->handle;
320 visit_type_uint32(v, name, &value, errp);
323 static void
324 qsev_guest_get_cbitpos(Object *obj, Visitor *v, const char *name,
325 void *opaque, Error **errp)
327 uint32_t value;
328 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
330 value = sev->cbitpos;
331 visit_type_uint32(v, name, &value, errp);
334 static void
335 qsev_guest_get_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
336 void *opaque, Error **errp)
338 uint32_t value;
339 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
341 value = sev->reduced_phys_bits;
342 visit_type_uint32(v, name, &value, errp);
345 static void
346 qsev_guest_init(Object *obj)
348 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
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);
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 },
378 static QSevGuestInfo *
379 lookup_sev_guest_info(const char *id)
381 Object *obj;
382 QSevGuestInfo *info;
384 obj = object_resolve_path_component(object_get_objects_root(), id);
385 if (!obj) {
386 return NULL;
389 info = (QSevGuestInfo *)
390 object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO);
391 if (!info) {
392 return NULL;
395 return info;
398 bool
399 sev_enabled(void)
401 return sev_state ? true : false;
404 uint64_t
405 sev_get_me_mask(void)
407 return sev_state ? sev_state->me_mask : ~0;
410 uint32_t
411 sev_get_cbit_position(void)
413 return sev_state ? sev_state->cbitpos : 0;
416 uint32_t
417 sev_get_reduced_phys_bits(void)
419 return sev_state ? sev_state->reduced_phys_bits : 0;
422 SevInfo *
423 sev_get_info(void)
425 SevInfo *info;
427 info = g_new0(SevInfo, 1);
428 info->enabled = sev_state ? true : false;
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;
439 return info;
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)
446 guchar *pdh_data = NULL;
447 guchar *cert_chain_data = NULL;
448 struct sev_user_data_pdh_cert_export export = {};
449 int err, r;
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;
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;
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;
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;
479 e_free:
480 g_free(pdh_data);
481 g_free(cert_chain_data);
482 return 1;
485 SevCapability *
486 sev_get_capabilities(void)
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;
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;
502 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
503 &cert_chain_data, &cert_chain_len)) {
504 goto out;
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);
511 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
512 cap->cbitpos = ebx & 0x3f;
515 * When SEV feature is enabled, we loose one bit in guest physical
516 * addressing.
518 cap->reduced_phys_bits = 1;
520 out:
521 g_free(pdh_data);
522 g_free(cert_chain_data);
523 close(fd);
524 return cap;
527 static int
528 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
530 gsize sz;
531 gchar *base64;
532 GError *error = NULL;
534 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
535 error_report("failed to read '%s' (%s)", filename, error->message);
536 return -1;
539 *data = g_base64_decode(base64, len);
540 return 0;
543 static int
544 sev_launch_start(SEVState *s)
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;
553 start = g_new0(struct kvm_sev_launch_start, 1);
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;
563 start->session_uaddr = (unsigned long)session;
564 start->session_len = sz;
567 if (sev->dh_cert_file) {
568 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
569 goto out;
571 start->dh_uaddr = (unsigned long)dh_cert;
572 start->dh_len = sz;
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;
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;
590 out:
591 g_free(start);
592 g_free(session);
593 g_free(dh_cert);
594 return ret;
597 static int
598 sev_launch_update_data(uint8_t *addr, uint64_t len)
600 int ret, fw_error;
601 struct kvm_sev_launch_update_data update;
603 if (!addr || !len) {
604 return 1;
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));
617 return ret;
620 static void
621 sev_launch_get_measure(Notifier *notifier, void *unused)
623 int ret, error;
624 guchar *data;
625 SEVState *s = sev_state;
626 struct kvm_sev_launch_measure *measurement;
628 if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE)) {
629 return;
632 measurement = g_new0(struct kvm_sev_launch_measure, 1);
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;
643 data = g_new0(guchar, measurement->len);
644 measurement->uaddr = (unsigned long)data;
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;
655 sev_set_guest_state(SEV_STATE_LAUNCH_SECRET);
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);
661 free_data:
662 g_free(data);
663 free_measurement:
664 g_free(measurement);
667 char *
668 sev_get_launch_measurement(void)
670 if (sev_state &&
671 sev_state->state >= SEV_STATE_LAUNCH_SECRET) {
672 return g_strdup(sev_state->measurement);
675 return NULL;
678 static Notifier sev_machine_done_notify = {
679 .notify = sev_launch_get_measure,
682 static void
683 sev_launch_finish(SEVState *s)
685 int ret, error;
686 Error *local_err = NULL;
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);
696 sev_set_guest_state(SEV_STATE_RUNNING);
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);
709 static void
710 sev_vm_state_change(void *opaque, int running, RunState state)
712 SEVState *s = opaque;
714 if (running) {
715 if (!sev_check_state(SEV_STATE_RUNNING)) {
716 sev_launch_finish(s);
721 void *
722 sev_guest_init(const char *id)
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 = {};
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;
739 s->state = SEV_STATE_UNINIT;
741 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
742 host_cbitpos = ebx & 0x3f;
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;
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;
759 s->me_mask = ~(1UL << s->cbitpos);
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));
767 g_free(devname);
768 if (s->sev_fd < 0) {
769 goto err;
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;
780 s->build_id = status.build;
781 s->api_major = status.api_major;
782 s->api_minor = status.api_minor;
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;
792 ret = sev_launch_start(s);
793 if (ret) {
794 error_report("%s: failed to create encryption context", __func__);
795 goto err;
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);
802 return s;
803 err:
804 g_free(sev_state);
805 sev_state = NULL;
806 return NULL;
810 sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
812 assert(handle);
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);
819 return 0;
822 static void
823 sev_register_types(void)
825 type_register_static(&qsev_guest_info);
828 type_init(sev_register_types);