virtio-ccw-input: fix description
[qemu/ar7.git] / target / i386 / sev.c
blobc3ecf8670427010a5cc789daf0c613c0513eb250
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 "sysemu/runstate.h"
29 #include "trace.h"
30 #include "migration/blocker.h"
32 #define TYPE_SEV_GUEST "sev-guest"
33 #define SEV_GUEST(obj) \
34 OBJECT_CHECK(SevGuestState, (obj), TYPE_SEV_GUEST)
36 typedef struct SevGuestState SevGuestState;
38 /**
39 * SevGuestState:
41 * The SevGuestState object is used for creating and managing a SEV
42 * guest.
44 * # $QEMU \
45 * -object sev-guest,id=sev0 \
46 * -machine ...,memory-encryption=sev0
48 struct SevGuestState {
49 Object parent_obj;
51 /* configuration parameters */
52 char *sev_device;
53 uint32_t policy;
54 char *dh_cert_file;
55 char *session_file;
56 uint32_t cbitpos;
57 uint32_t reduced_phys_bits;
59 /* runtime state */
60 uint32_t handle;
61 uint8_t api_major;
62 uint8_t api_minor;
63 uint8_t build_id;
64 uint64_t me_mask;
65 int sev_fd;
66 SevState state;
67 gchar *measurement;
70 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
71 #define DEFAULT_SEV_DEVICE "/dev/sev"
73 static SevGuestState *sev_guest;
74 static Error *sev_mig_blocker;
76 static const char *const sev_fw_errlist[] = {
77 "",
78 "Platform state is invalid",
79 "Guest state is invalid",
80 "Platform configuration is invalid",
81 "Buffer too small",
82 "Platform is already owned",
83 "Certificate is invalid",
84 "Policy is not allowed",
85 "Guest is not active",
86 "Invalid address",
87 "Bad signature",
88 "Bad measurement",
89 "Asid is already owned",
90 "Invalid ASID",
91 "WBINVD is required",
92 "DF_FLUSH is required",
93 "Guest handle is invalid",
94 "Invalid command",
95 "Guest is active",
96 "Hardware error",
97 "Hardware unsafe",
98 "Feature not supported",
99 "Invalid parameter"
102 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
104 static int
105 sev_ioctl(int fd, int cmd, void *data, int *error)
107 int r;
108 struct kvm_sev_cmd input;
110 memset(&input, 0x0, sizeof(input));
112 input.id = cmd;
113 input.sev_fd = fd;
114 input.data = (__u64)(unsigned long)data;
116 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
118 if (error) {
119 *error = input.error;
122 return r;
125 static int
126 sev_platform_ioctl(int fd, int cmd, void *data, int *error)
128 int r;
129 struct sev_issue_cmd arg;
131 arg.cmd = cmd;
132 arg.data = (unsigned long)data;
133 r = ioctl(fd, SEV_ISSUE_CMD, &arg);
134 if (error) {
135 *error = arg.error;
138 return r;
141 static const char *
142 fw_error_to_str(int code)
144 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
145 return "unknown error";
148 return sev_fw_errlist[code];
151 static bool
152 sev_check_state(const SevGuestState *sev, SevState state)
154 assert(sev);
155 return sev->state == state ? true : false;
158 static void
159 sev_set_guest_state(SevGuestState *sev, SevState new_state)
161 assert(new_state < SEV_STATE__MAX);
162 assert(sev);
164 trace_kvm_sev_change_state(SevState_str(sev->state),
165 SevState_str(new_state));
166 sev->state = new_state;
169 static void
170 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
172 int r;
173 struct kvm_enc_region range;
174 ram_addr_t offset;
175 MemoryRegion *mr;
178 * The RAM device presents a memory region that should be treated
179 * as IO region and should not be pinned.
181 mr = memory_region_from_host(host, &offset);
182 if (mr && memory_region_is_ram_device(mr)) {
183 return;
186 range.addr = (__u64)(unsigned long)host;
187 range.size = size;
189 trace_kvm_memcrypt_register_region(host, size);
190 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
191 if (r) {
192 error_report("%s: failed to register region (%p+%#zx) error '%s'",
193 __func__, host, size, strerror(errno));
194 exit(1);
198 static void
199 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
201 int r;
202 struct kvm_enc_region range;
203 ram_addr_t offset;
204 MemoryRegion *mr;
207 * The RAM device presents a memory region that should be treated
208 * as IO region and should not have been pinned.
210 mr = memory_region_from_host(host, &offset);
211 if (mr && memory_region_is_ram_device(mr)) {
212 return;
215 range.addr = (__u64)(unsigned long)host;
216 range.size = size;
218 trace_kvm_memcrypt_unregister_region(host, size);
219 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
220 if (r) {
221 error_report("%s: failed to unregister region (%p+%#zx)",
222 __func__, host, size);
226 static struct RAMBlockNotifier sev_ram_notifier = {
227 .ram_block_added = sev_ram_block_added,
228 .ram_block_removed = sev_ram_block_removed,
231 static void
232 sev_guest_finalize(Object *obj)
236 static char *
237 sev_guest_get_session_file(Object *obj, Error **errp)
239 SevGuestState *s = SEV_GUEST(obj);
241 return s->session_file ? g_strdup(s->session_file) : NULL;
244 static void
245 sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
247 SevGuestState *s = SEV_GUEST(obj);
249 s->session_file = g_strdup(value);
252 static char *
253 sev_guest_get_dh_cert_file(Object *obj, Error **errp)
255 SevGuestState *s = SEV_GUEST(obj);
257 return g_strdup(s->dh_cert_file);
260 static void
261 sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
263 SevGuestState *s = SEV_GUEST(obj);
265 s->dh_cert_file = g_strdup(value);
268 static char *
269 sev_guest_get_sev_device(Object *obj, Error **errp)
271 SevGuestState *sev = SEV_GUEST(obj);
273 return g_strdup(sev->sev_device);
276 static void
277 sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
279 SevGuestState *sev = SEV_GUEST(obj);
281 sev->sev_device = g_strdup(value);
284 static void
285 sev_guest_class_init(ObjectClass *oc, void *data)
287 object_class_property_add_str(oc, "sev-device",
288 sev_guest_get_sev_device,
289 sev_guest_set_sev_device);
290 object_class_property_set_description(oc, "sev-device",
291 "SEV device to use");
292 object_class_property_add_str(oc, "dh-cert-file",
293 sev_guest_get_dh_cert_file,
294 sev_guest_set_dh_cert_file);
295 object_class_property_set_description(oc, "dh-cert-file",
296 "guest owners DH certificate (encoded with base64)");
297 object_class_property_add_str(oc, "session-file",
298 sev_guest_get_session_file,
299 sev_guest_set_session_file);
300 object_class_property_set_description(oc, "session-file",
301 "guest owners session parameters (encoded with base64)");
304 static void
305 sev_guest_instance_init(Object *obj)
307 SevGuestState *sev = SEV_GUEST(obj);
309 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
310 sev->policy = DEFAULT_GUEST_POLICY;
311 object_property_add_uint32_ptr(obj, "policy", &sev->policy,
312 OBJ_PROP_FLAG_READWRITE);
313 object_property_add_uint32_ptr(obj, "handle", &sev->handle,
314 OBJ_PROP_FLAG_READWRITE);
315 object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
316 OBJ_PROP_FLAG_READWRITE);
317 object_property_add_uint32_ptr(obj, "reduced-phys-bits",
318 &sev->reduced_phys_bits,
319 OBJ_PROP_FLAG_READWRITE);
322 /* sev guest info */
323 static const TypeInfo sev_guest_info = {
324 .parent = TYPE_OBJECT,
325 .name = TYPE_SEV_GUEST,
326 .instance_size = sizeof(SevGuestState),
327 .instance_finalize = sev_guest_finalize,
328 .class_init = sev_guest_class_init,
329 .instance_init = sev_guest_instance_init,
330 .interfaces = (InterfaceInfo[]) {
331 { TYPE_USER_CREATABLE },
336 static SevGuestState *
337 lookup_sev_guest_info(const char *id)
339 Object *obj;
340 SevGuestState *info;
342 obj = object_resolve_path_component(object_get_objects_root(), id);
343 if (!obj) {
344 return NULL;
347 info = (SevGuestState *)
348 object_dynamic_cast(obj, TYPE_SEV_GUEST);
349 if (!info) {
350 return NULL;
353 return info;
356 bool
357 sev_enabled(void)
359 return !!sev_guest;
362 uint64_t
363 sev_get_me_mask(void)
365 return sev_guest ? sev_guest->me_mask : ~0;
368 uint32_t
369 sev_get_cbit_position(void)
371 return sev_guest ? sev_guest->cbitpos : 0;
374 uint32_t
375 sev_get_reduced_phys_bits(void)
377 return sev_guest ? sev_guest->reduced_phys_bits : 0;
380 SevInfo *
381 sev_get_info(void)
383 SevInfo *info;
385 info = g_new0(SevInfo, 1);
386 info->enabled = sev_enabled();
388 if (info->enabled) {
389 info->api_major = sev_guest->api_major;
390 info->api_minor = sev_guest->api_minor;
391 info->build_id = sev_guest->build_id;
392 info->policy = sev_guest->policy;
393 info->state = sev_guest->state;
394 info->handle = sev_guest->handle;
397 return info;
400 static int
401 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
402 size_t *cert_chain_len, Error **errp)
404 guchar *pdh_data = NULL;
405 guchar *cert_chain_data = NULL;
406 struct sev_user_data_pdh_cert_export export = {};
407 int err, r;
409 /* query the certificate length */
410 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
411 if (r < 0) {
412 if (err != SEV_RET_INVALID_LEN) {
413 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
414 r, err, fw_error_to_str(err));
415 return 1;
419 pdh_data = g_new(guchar, export.pdh_cert_len);
420 cert_chain_data = g_new(guchar, export.cert_chain_len);
421 export.pdh_cert_address = (unsigned long)pdh_data;
422 export.cert_chain_address = (unsigned long)cert_chain_data;
424 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
425 if (r < 0) {
426 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
427 r, err, fw_error_to_str(err));
428 goto e_free;
431 *pdh = pdh_data;
432 *pdh_len = export.pdh_cert_len;
433 *cert_chain = cert_chain_data;
434 *cert_chain_len = export.cert_chain_len;
435 return 0;
437 e_free:
438 g_free(pdh_data);
439 g_free(cert_chain_data);
440 return 1;
443 SevCapability *
444 sev_get_capabilities(Error **errp)
446 SevCapability *cap = NULL;
447 guchar *pdh_data = NULL;
448 guchar *cert_chain_data = NULL;
449 size_t pdh_len = 0, cert_chain_len = 0;
450 uint32_t ebx;
451 int fd;
453 if (!kvm_enabled()) {
454 error_setg(errp, "KVM not enabled");
455 return NULL;
457 if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) {
458 error_setg(errp, "SEV is not enabled in KVM");
459 return NULL;
462 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
463 if (fd < 0) {
464 error_setg_errno(errp, errno, "Failed to open %s",
465 DEFAULT_SEV_DEVICE);
466 return NULL;
469 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
470 &cert_chain_data, &cert_chain_len, errp)) {
471 goto out;
474 cap = g_new0(SevCapability, 1);
475 cap->pdh = g_base64_encode(pdh_data, pdh_len);
476 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
478 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
479 cap->cbitpos = ebx & 0x3f;
482 * When SEV feature is enabled, we loose one bit in guest physical
483 * addressing.
485 cap->reduced_phys_bits = 1;
487 out:
488 g_free(pdh_data);
489 g_free(cert_chain_data);
490 close(fd);
491 return cap;
494 static int
495 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
497 gsize sz;
498 gchar *base64;
499 GError *error = NULL;
501 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
502 error_report("failed to read '%s' (%s)", filename, error->message);
503 return -1;
506 *data = g_base64_decode(base64, len);
507 return 0;
510 static int
511 sev_launch_start(SevGuestState *sev)
513 gsize sz;
514 int ret = 1;
515 int fw_error, rc;
516 struct kvm_sev_launch_start *start;
517 guchar *session = NULL, *dh_cert = NULL;
519 start = g_new0(struct kvm_sev_launch_start, 1);
521 start->handle = sev->handle;
522 start->policy = sev->policy;
523 if (sev->session_file) {
524 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
525 goto out;
527 start->session_uaddr = (unsigned long)session;
528 start->session_len = sz;
531 if (sev->dh_cert_file) {
532 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
533 goto out;
535 start->dh_uaddr = (unsigned long)dh_cert;
536 start->dh_len = sz;
539 trace_kvm_sev_launch_start(start->policy, session, dh_cert);
540 rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
541 if (rc < 0) {
542 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
543 __func__, ret, fw_error, fw_error_to_str(fw_error));
544 goto out;
547 sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
548 sev->handle = start->handle;
549 ret = 0;
551 out:
552 g_free(start);
553 g_free(session);
554 g_free(dh_cert);
555 return ret;
558 static int
559 sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
561 int ret, fw_error;
562 struct kvm_sev_launch_update_data update;
564 if (!addr || !len) {
565 return 1;
568 update.uaddr = (__u64)(unsigned long)addr;
569 update.len = len;
570 trace_kvm_sev_launch_update_data(addr, len);
571 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
572 &update, &fw_error);
573 if (ret) {
574 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
575 __func__, ret, fw_error, fw_error_to_str(fw_error));
578 return ret;
581 static void
582 sev_launch_get_measure(Notifier *notifier, void *unused)
584 SevGuestState *sev = sev_guest;
585 int ret, error;
586 guchar *data;
587 struct kvm_sev_launch_measure *measurement;
589 if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
590 return;
593 measurement = g_new0(struct kvm_sev_launch_measure, 1);
595 /* query the measurement blob length */
596 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
597 measurement, &error);
598 if (!measurement->len) {
599 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
600 __func__, ret, error, fw_error_to_str(errno));
601 goto free_measurement;
604 data = g_new0(guchar, measurement->len);
605 measurement->uaddr = (unsigned long)data;
607 /* get the measurement blob */
608 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
609 measurement, &error);
610 if (ret) {
611 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
612 __func__, ret, error, fw_error_to_str(errno));
613 goto free_data;
616 sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
618 /* encode the measurement value and emit the event */
619 sev->measurement = g_base64_encode(data, measurement->len);
620 trace_kvm_sev_launch_measurement(sev->measurement);
622 free_data:
623 g_free(data);
624 free_measurement:
625 g_free(measurement);
628 char *
629 sev_get_launch_measurement(void)
631 if (sev_guest &&
632 sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
633 return g_strdup(sev_guest->measurement);
636 return NULL;
639 static Notifier sev_machine_done_notify = {
640 .notify = sev_launch_get_measure,
643 static void
644 sev_launch_finish(SevGuestState *sev)
646 int ret, error;
647 Error *local_err = NULL;
649 trace_kvm_sev_launch_finish();
650 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
651 if (ret) {
652 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
653 __func__, ret, error, fw_error_to_str(error));
654 exit(1);
657 sev_set_guest_state(sev, SEV_STATE_RUNNING);
659 /* add migration blocker */
660 error_setg(&sev_mig_blocker,
661 "SEV: Migration is not implemented");
662 ret = migrate_add_blocker(sev_mig_blocker, &local_err);
663 if (local_err) {
664 error_report_err(local_err);
665 error_free(sev_mig_blocker);
666 exit(1);
670 static void
671 sev_vm_state_change(void *opaque, int running, RunState state)
673 SevGuestState *sev = opaque;
675 if (running) {
676 if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
677 sev_launch_finish(sev);
682 void *
683 sev_guest_init(const char *id)
685 SevGuestState *sev;
686 char *devname;
687 int ret, fw_error;
688 uint32_t ebx;
689 uint32_t host_cbitpos;
690 struct sev_user_data_status status = {};
692 ret = ram_block_discard_disable(true);
693 if (ret) {
694 error_report("%s: cannot disable RAM discard", __func__);
695 return NULL;
698 sev = lookup_sev_guest_info(id);
699 if (!sev) {
700 error_report("%s: '%s' is not a valid '%s' object",
701 __func__, id, TYPE_SEV_GUEST);
702 goto err;
705 sev_guest = sev;
706 sev->state = SEV_STATE_UNINIT;
708 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
709 host_cbitpos = ebx & 0x3f;
711 if (host_cbitpos != sev->cbitpos) {
712 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
713 __func__, host_cbitpos, sev->cbitpos);
714 goto err;
717 if (sev->reduced_phys_bits < 1) {
718 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
719 " requested '%d'", __func__, sev->reduced_phys_bits);
720 goto err;
723 sev->me_mask = ~(1UL << sev->cbitpos);
725 devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
726 sev->sev_fd = open(devname, O_RDWR);
727 if (sev->sev_fd < 0) {
728 error_report("%s: Failed to open %s '%s'", __func__,
729 devname, strerror(errno));
731 g_free(devname);
732 if (sev->sev_fd < 0) {
733 goto err;
736 ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status,
737 &fw_error);
738 if (ret) {
739 error_report("%s: failed to get platform status ret=%d "
740 "fw_error='%d: %s'", __func__, ret, fw_error,
741 fw_error_to_str(fw_error));
742 goto err;
744 sev->build_id = status.build;
745 sev->api_major = status.api_major;
746 sev->api_minor = status.api_minor;
748 trace_kvm_sev_init();
749 ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT, NULL, &fw_error);
750 if (ret) {
751 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
752 __func__, ret, fw_error, fw_error_to_str(fw_error));
753 goto err;
756 ret = sev_launch_start(sev);
757 if (ret) {
758 error_report("%s: failed to create encryption context", __func__);
759 goto err;
762 ram_block_notifier_add(&sev_ram_notifier);
763 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
764 qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
766 return sev;
767 err:
768 sev_guest = NULL;
769 ram_block_discard_disable(false);
770 return NULL;
774 sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
776 SevGuestState *sev = handle;
778 assert(sev);
780 /* if SEV is in update state then encrypt the data else do nothing */
781 if (sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
782 return sev_launch_update_data(sev, ptr, len);
785 return 0;
788 static void
789 sev_register_types(void)
791 type_register_static(&sev_guest_info);
794 type_init(sev_register_types);