4 * Copyright Advanced Micro Devices 2016-2018
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"
27 #include "sysemu/sysemu.h"
28 #include "sysemu/runstate.h"
30 #include "migration/blocker.h"
31 #include "qom/object.h"
32 #include "exec/address-spaces.h"
33 #include "monitor/monitor.h"
35 #define TYPE_SEV_GUEST "sev-guest"
36 OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
42 * The SevGuestState object is used for creating and managing a SEV
46 * -object sev-guest,id=sev0 \
47 * -machine ...,memory-encryption=sev0
49 struct SevGuestState {
52 /* configuration parameters */
58 uint32_t reduced_phys_bits;
71 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
72 #define DEFAULT_SEV_DEVICE "/dev/sev"
74 static SevGuestState *sev_guest;
75 static Error *sev_mig_blocker;
77 static const char *const sev_fw_errlist[] = {
79 "Platform state is invalid",
80 "Guest state is invalid",
81 "Platform configuration is invalid",
83 "Platform is already owned",
84 "Certificate is invalid",
85 "Policy is not allowed",
86 "Guest is not active",
90 "Asid is already owned",
93 "DF_FLUSH is required",
94 "Guest handle is invalid",
99 "Feature not supported",
103 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
106 sev_ioctl(int fd, int cmd, void *data, int *error)
109 struct kvm_sev_cmd input;
111 memset(&input, 0x0, sizeof(input));
115 input.data = (__u64)(unsigned long)data;
117 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
120 *error = input.error;
127 sev_platform_ioctl(int fd, int cmd, void *data, int *error)
130 struct sev_issue_cmd arg;
133 arg.data = (unsigned long)data;
134 r = ioctl(fd, SEV_ISSUE_CMD, &arg);
143 fw_error_to_str(int code)
145 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
146 return "unknown error";
149 return sev_fw_errlist[code];
153 sev_check_state(const SevGuestState *sev, SevState state)
156 return sev->state == state ? true : false;
160 sev_set_guest_state(SevGuestState *sev, SevState new_state)
162 assert(new_state < SEV_STATE__MAX);
165 trace_kvm_sev_change_state(SevState_str(sev->state),
166 SevState_str(new_state));
167 sev->state = new_state;
171 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
174 struct kvm_enc_region range;
179 * The RAM device presents a memory region that should be treated
180 * as IO region and should not be pinned.
182 mr = memory_region_from_host(host, &offset);
183 if (mr && memory_region_is_ram_device(mr)) {
187 range.addr = (__u64)(unsigned long)host;
190 trace_kvm_memcrypt_register_region(host, size);
191 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
193 error_report("%s: failed to register region (%p+%#zx) error '%s'",
194 __func__, host, size, strerror(errno));
200 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
203 struct kvm_enc_region range;
208 * The RAM device presents a memory region that should be treated
209 * as IO region and should not have been pinned.
211 mr = memory_region_from_host(host, &offset);
212 if (mr && memory_region_is_ram_device(mr)) {
216 range.addr = (__u64)(unsigned long)host;
219 trace_kvm_memcrypt_unregister_region(host, size);
220 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
222 error_report("%s: failed to unregister region (%p+%#zx)",
223 __func__, host, size);
227 static struct RAMBlockNotifier sev_ram_notifier = {
228 .ram_block_added = sev_ram_block_added,
229 .ram_block_removed = sev_ram_block_removed,
233 sev_guest_finalize(Object *obj)
238 sev_guest_get_session_file(Object *obj, Error **errp)
240 SevGuestState *s = SEV_GUEST(obj);
242 return s->session_file ? g_strdup(s->session_file) : NULL;
246 sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
248 SevGuestState *s = SEV_GUEST(obj);
250 s->session_file = g_strdup(value);
254 sev_guest_get_dh_cert_file(Object *obj, Error **errp)
256 SevGuestState *s = SEV_GUEST(obj);
258 return g_strdup(s->dh_cert_file);
262 sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
264 SevGuestState *s = SEV_GUEST(obj);
266 s->dh_cert_file = g_strdup(value);
270 sev_guest_get_sev_device(Object *obj, Error **errp)
272 SevGuestState *sev = SEV_GUEST(obj);
274 return g_strdup(sev->sev_device);
278 sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
280 SevGuestState *sev = SEV_GUEST(obj);
282 sev->sev_device = g_strdup(value);
286 sev_guest_class_init(ObjectClass *oc, void *data)
288 object_class_property_add_str(oc, "sev-device",
289 sev_guest_get_sev_device,
290 sev_guest_set_sev_device);
291 object_class_property_set_description(oc, "sev-device",
292 "SEV device to use");
293 object_class_property_add_str(oc, "dh-cert-file",
294 sev_guest_get_dh_cert_file,
295 sev_guest_set_dh_cert_file);
296 object_class_property_set_description(oc, "dh-cert-file",
297 "guest owners DH certificate (encoded with base64)");
298 object_class_property_add_str(oc, "session-file",
299 sev_guest_get_session_file,
300 sev_guest_set_session_file);
301 object_class_property_set_description(oc, "session-file",
302 "guest owners session parameters (encoded with base64)");
306 sev_guest_instance_init(Object *obj)
308 SevGuestState *sev = SEV_GUEST(obj);
310 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
311 sev->policy = DEFAULT_GUEST_POLICY;
312 object_property_add_uint32_ptr(obj, "policy", &sev->policy,
313 OBJ_PROP_FLAG_READWRITE);
314 object_property_add_uint32_ptr(obj, "handle", &sev->handle,
315 OBJ_PROP_FLAG_READWRITE);
316 object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
317 OBJ_PROP_FLAG_READWRITE);
318 object_property_add_uint32_ptr(obj, "reduced-phys-bits",
319 &sev->reduced_phys_bits,
320 OBJ_PROP_FLAG_READWRITE);
324 static const TypeInfo sev_guest_info = {
325 .parent = TYPE_OBJECT,
326 .name = TYPE_SEV_GUEST,
327 .instance_size = sizeof(SevGuestState),
328 .instance_finalize = sev_guest_finalize,
329 .class_init = sev_guest_class_init,
330 .instance_init = sev_guest_instance_init,
331 .interfaces = (InterfaceInfo[]) {
332 { TYPE_USER_CREATABLE },
337 static SevGuestState *
338 lookup_sev_guest_info(const char *id)
343 obj = object_resolve_path_component(object_get_objects_root(), id);
348 info = (SevGuestState *)
349 object_dynamic_cast(obj, TYPE_SEV_GUEST);
364 sev_get_me_mask(void)
366 return sev_guest ? sev_guest->me_mask : ~0;
370 sev_get_cbit_position(void)
372 return sev_guest ? sev_guest->cbitpos : 0;
376 sev_get_reduced_phys_bits(void)
378 return sev_guest ? sev_guest->reduced_phys_bits : 0;
386 info = g_new0(SevInfo, 1);
387 info->enabled = sev_enabled();
390 info->api_major = sev_guest->api_major;
391 info->api_minor = sev_guest->api_minor;
392 info->build_id = sev_guest->build_id;
393 info->policy = sev_guest->policy;
394 info->state = sev_guest->state;
395 info->handle = sev_guest->handle;
402 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
403 size_t *cert_chain_len, Error **errp)
405 guchar *pdh_data = NULL;
406 guchar *cert_chain_data = NULL;
407 struct sev_user_data_pdh_cert_export export = {};
410 /* query the certificate length */
411 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
413 if (err != SEV_RET_INVALID_LEN) {
414 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
415 r, err, fw_error_to_str(err));
420 pdh_data = g_new(guchar, export.pdh_cert_len);
421 cert_chain_data = g_new(guchar, export.cert_chain_len);
422 export.pdh_cert_address = (unsigned long)pdh_data;
423 export.cert_chain_address = (unsigned long)cert_chain_data;
425 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
427 error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
428 r, err, fw_error_to_str(err));
433 *pdh_len = export.pdh_cert_len;
434 *cert_chain = cert_chain_data;
435 *cert_chain_len = export.cert_chain_len;
440 g_free(cert_chain_data);
445 sev_get_capabilities(Error **errp)
447 SevCapability *cap = NULL;
448 guchar *pdh_data = NULL;
449 guchar *cert_chain_data = NULL;
450 size_t pdh_len = 0, cert_chain_len = 0;
454 if (!kvm_enabled()) {
455 error_setg(errp, "KVM not enabled");
458 if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) {
459 error_setg(errp, "SEV is not enabled in KVM");
463 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
465 error_setg_errno(errp, errno, "Failed to open %s",
470 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
471 &cert_chain_data, &cert_chain_len, errp)) {
475 cap = g_new0(SevCapability, 1);
476 cap->pdh = g_base64_encode(pdh_data, pdh_len);
477 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
479 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
480 cap->cbitpos = ebx & 0x3f;
483 * When SEV feature is enabled, we loose one bit in guest physical
486 cap->reduced_phys_bits = 1;
490 g_free(cert_chain_data);
496 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
500 GError *error = NULL;
502 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
503 error_report("failed to read '%s' (%s)", filename, error->message);
508 *data = g_base64_decode(base64, len);
513 sev_launch_start(SevGuestState *sev)
518 struct kvm_sev_launch_start *start;
519 guchar *session = NULL, *dh_cert = NULL;
521 start = g_new0(struct kvm_sev_launch_start, 1);
523 start->handle = sev->handle;
524 start->policy = sev->policy;
525 if (sev->session_file) {
526 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
529 start->session_uaddr = (unsigned long)session;
530 start->session_len = sz;
533 if (sev->dh_cert_file) {
534 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
537 start->dh_uaddr = (unsigned long)dh_cert;
541 trace_kvm_sev_launch_start(start->policy, session, dh_cert);
542 rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
544 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
545 __func__, ret, fw_error, fw_error_to_str(fw_error));
549 sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
550 sev->handle = start->handle;
561 sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
564 struct kvm_sev_launch_update_data update;
570 update.uaddr = (__u64)(unsigned long)addr;
572 trace_kvm_sev_launch_update_data(addr, len);
573 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
576 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
577 __func__, ret, fw_error, fw_error_to_str(fw_error));
584 sev_launch_get_measure(Notifier *notifier, void *unused)
586 SevGuestState *sev = sev_guest;
589 struct kvm_sev_launch_measure *measurement;
591 if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
595 measurement = g_new0(struct kvm_sev_launch_measure, 1);
597 /* query the measurement blob length */
598 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
599 measurement, &error);
600 if (!measurement->len) {
601 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
602 __func__, ret, error, fw_error_to_str(errno));
603 goto free_measurement;
606 data = g_new0(guchar, measurement->len);
607 measurement->uaddr = (unsigned long)data;
609 /* get the measurement blob */
610 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
611 measurement, &error);
613 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
614 __func__, ret, error, fw_error_to_str(errno));
618 sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
620 /* encode the measurement value and emit the event */
621 sev->measurement = g_base64_encode(data, measurement->len);
622 trace_kvm_sev_launch_measurement(sev->measurement);
631 sev_get_launch_measurement(void)
634 sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
635 return g_strdup(sev_guest->measurement);
641 static Notifier sev_machine_done_notify = {
642 .notify = sev_launch_get_measure,
646 sev_launch_finish(SevGuestState *sev)
649 Error *local_err = NULL;
651 trace_kvm_sev_launch_finish();
652 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
654 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
655 __func__, ret, error, fw_error_to_str(error));
659 sev_set_guest_state(sev, SEV_STATE_RUNNING);
661 /* add migration blocker */
662 error_setg(&sev_mig_blocker,
663 "SEV: Migration is not implemented");
664 ret = migrate_add_blocker(sev_mig_blocker, &local_err);
666 error_report_err(local_err);
667 error_free(sev_mig_blocker);
673 sev_vm_state_change(void *opaque, int running, RunState state)
675 SevGuestState *sev = opaque;
678 if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
679 sev_launch_finish(sev);
685 sev_guest_init(const char *id)
691 uint32_t host_cbitpos;
692 struct sev_user_data_status status = {};
694 ret = ram_block_discard_disable(true);
696 error_report("%s: cannot disable RAM discard", __func__);
700 sev = lookup_sev_guest_info(id);
702 error_report("%s: '%s' is not a valid '%s' object",
703 __func__, id, TYPE_SEV_GUEST);
708 sev->state = SEV_STATE_UNINIT;
710 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
711 host_cbitpos = ebx & 0x3f;
713 if (host_cbitpos != sev->cbitpos) {
714 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
715 __func__, host_cbitpos, sev->cbitpos);
719 if (sev->reduced_phys_bits < 1) {
720 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
721 " requested '%d'", __func__, sev->reduced_phys_bits);
725 sev->me_mask = ~(1UL << sev->cbitpos);
727 devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
728 sev->sev_fd = open(devname, O_RDWR);
729 if (sev->sev_fd < 0) {
730 error_report("%s: Failed to open %s '%s'", __func__,
731 devname, strerror(errno));
734 if (sev->sev_fd < 0) {
738 ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status,
741 error_report("%s: failed to get platform status ret=%d "
742 "fw_error='%d: %s'", __func__, ret, fw_error,
743 fw_error_to_str(fw_error));
746 sev->build_id = status.build;
747 sev->api_major = status.api_major;
748 sev->api_minor = status.api_minor;
750 trace_kvm_sev_init();
751 ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT, NULL, &fw_error);
753 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
754 __func__, ret, fw_error, fw_error_to_str(fw_error));
758 ret = sev_launch_start(sev);
760 error_report("%s: failed to create encryption context", __func__);
764 ram_block_notifier_add(&sev_ram_notifier);
765 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
766 qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
771 ram_block_discard_disable(false);
776 sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
778 SevGuestState *sev = handle;
782 /* if SEV is in update state then encrypt the data else do nothing */
783 if (sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
784 return sev_launch_update_data(sev, ptr, len);
790 int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
791 uint64_t gpa, Error **errp)
793 struct kvm_sev_launch_secret input;
794 g_autofree guchar *data = NULL, *hdr = NULL;
797 gsize hdr_sz = 0, data_sz = 0;
798 MemoryRegion *mr = NULL;
801 error_setg(errp, "SEV: SEV not enabled.");
805 /* secret can be injected only in this state */
806 if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
807 error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
812 hdr = g_base64_decode(packet_hdr, &hdr_sz);
813 if (!hdr || !hdr_sz) {
814 error_setg(errp, "SEV: Failed to decode sequence header");
818 data = g_base64_decode(secret, &data_sz);
819 if (!data || !data_sz) {
820 error_setg(errp, "SEV: Failed to decode data");
824 hva = gpa2hva(&mr, gpa, data_sz, errp);
826 error_prepend(errp, "SEV: Failed to calculate guest address: ");
830 input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
831 input.hdr_len = hdr_sz;
833 input.trans_uaddr = (uint64_t)(unsigned long)data;
834 input.trans_len = data_sz;
836 input.guest_uaddr = (uint64_t)(unsigned long)hva;
837 input.guest_len = data_sz;
839 trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
840 input.trans_uaddr, input.trans_len);
842 ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
845 error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
846 ret, error, fw_error_to_str(error));
854 sev_register_types(void)
856 type_register_static(&sev_guest_info);
859 type_init(sev_register_types);