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 "sysemu/kvm.h"
26 #include "sysemu/sysemu.h"
28 #include "migration/blocker.h"
30 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
31 #define DEFAULT_SEV_DEVICE "/dev/sev"
33 static SEVState *sev_state;
34 static Error *sev_mig_blocker;
36 static const char *const sev_fw_errlist[] = {
38 "Platform state is invalid",
39 "Guest state is invalid",
40 "Platform configuration is invalid",
42 "Platform is already owned",
43 "Certificate is invalid",
44 "Policy is not allowed",
45 "Guest is not active",
49 "Asid is already owned",
52 "DF_FLUSH is required",
53 "Guest handle is invalid",
58 "Feature not supported",
62 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
65 sev_ioctl(int fd, int cmd, void *data, int *error)
68 struct kvm_sev_cmd input;
70 memset(&input, 0x0, sizeof(input));
74 input.data = (__u64)(unsigned long)data;
76 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
86 sev_platform_ioctl(int fd, int cmd, void *data, int *error)
89 struct sev_issue_cmd arg;
92 arg.data = (unsigned long)data;
93 r = ioctl(fd, SEV_ISSUE_CMD, &arg);
102 fw_error_to_str(int code)
104 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
105 return "unknown error";
108 return sev_fw_errlist[code];
112 sev_check_state(SevState state)
115 return sev_state->state == state ? true : false;
119 sev_set_guest_state(SevState new_state)
121 assert(new_state < SEV_STATE__MAX);
124 trace_kvm_sev_change_state(SevState_str(sev_state->state),
125 SevState_str(new_state));
126 sev_state->state = new_state;
130 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
133 struct kvm_enc_region range;
135 range.addr = (__u64)(unsigned long)host;
138 trace_kvm_memcrypt_register_region(host, size);
139 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
141 error_report("%s: failed to register region (%p+%#zx) error '%s'",
142 __func__, host, size, strerror(errno));
148 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
151 struct kvm_enc_region range;
153 range.addr = (__u64)(unsigned long)host;
156 trace_kvm_memcrypt_unregister_region(host, size);
157 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
159 error_report("%s: failed to unregister region (%p+%#zx)",
160 __func__, host, size);
164 static struct RAMBlockNotifier sev_ram_notifier = {
165 .ram_block_added = sev_ram_block_added,
166 .ram_block_removed = sev_ram_block_removed,
170 qsev_guest_finalize(Object *obj)
175 qsev_guest_get_session_file(Object *obj, Error **errp)
177 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
179 return s->session_file ? g_strdup(s->session_file) : NULL;
183 qsev_guest_set_session_file(Object *obj, const char *value, Error **errp)
185 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
187 s->session_file = g_strdup(value);
191 qsev_guest_get_dh_cert_file(Object *obj, Error **errp)
193 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
195 return g_strdup(s->dh_cert_file);
199 qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
201 QSevGuestInfo *s = QSEV_GUEST_INFO(obj);
203 s->dh_cert_file = g_strdup(value);
207 qsev_guest_get_sev_device(Object *obj, Error **errp)
209 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
211 return g_strdup(sev->sev_device);
215 qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
217 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
219 sev->sev_device = g_strdup(value);
223 qsev_guest_class_init(ObjectClass *oc, void *data)
225 object_class_property_add_str(oc, "sev-device",
226 qsev_guest_get_sev_device,
227 qsev_guest_set_sev_device,
229 object_class_property_set_description(oc, "sev-device",
230 "SEV device to use", NULL);
231 object_class_property_add_str(oc, "dh-cert-file",
232 qsev_guest_get_dh_cert_file,
233 qsev_guest_set_dh_cert_file,
235 object_class_property_set_description(oc, "dh-cert-file",
236 "guest owners DH certificate (encoded with base64)", NULL);
237 object_class_property_add_str(oc, "session-file",
238 qsev_guest_get_session_file,
239 qsev_guest_set_session_file,
241 object_class_property_set_description(oc, "session-file",
242 "guest owners session parameters (encoded with base64)", NULL);
246 qsev_guest_set_handle(Object *obj, Visitor *v, const char *name,
247 void *opaque, Error **errp)
249 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
252 visit_type_uint32(v, name, &value, errp);
257 qsev_guest_set_policy(Object *obj, Visitor *v, const char *name,
258 void *opaque, Error **errp)
260 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
263 visit_type_uint32(v, name, &value, errp);
268 qsev_guest_set_cbitpos(Object *obj, Visitor *v, const char *name,
269 void *opaque, Error **errp)
271 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
274 visit_type_uint32(v, name, &value, errp);
275 sev->cbitpos = value;
279 qsev_guest_set_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
280 void *opaque, Error **errp)
282 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
285 visit_type_uint32(v, name, &value, errp);
286 sev->reduced_phys_bits = value;
290 qsev_guest_get_policy(Object *obj, Visitor *v, const char *name,
291 void *opaque, Error **errp)
294 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
297 visit_type_uint32(v, name, &value, errp);
301 qsev_guest_get_handle(Object *obj, Visitor *v, const char *name,
302 void *opaque, Error **errp)
305 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
308 visit_type_uint32(v, name, &value, errp);
312 qsev_guest_get_cbitpos(Object *obj, Visitor *v, const char *name,
313 void *opaque, Error **errp)
316 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
318 value = sev->cbitpos;
319 visit_type_uint32(v, name, &value, errp);
323 qsev_guest_get_reduced_phys_bits(Object *obj, Visitor *v, const char *name,
324 void *opaque, Error **errp)
327 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
329 value = sev->reduced_phys_bits;
330 visit_type_uint32(v, name, &value, errp);
334 qsev_guest_init(Object *obj)
336 QSevGuestInfo *sev = QSEV_GUEST_INFO(obj);
338 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
339 sev->policy = DEFAULT_GUEST_POLICY;
340 object_property_add(obj, "policy", "uint32", qsev_guest_get_policy,
341 qsev_guest_set_policy, NULL, NULL, NULL);
342 object_property_add(obj, "handle", "uint32", qsev_guest_get_handle,
343 qsev_guest_set_handle, NULL, NULL, NULL);
344 object_property_add(obj, "cbitpos", "uint32", qsev_guest_get_cbitpos,
345 qsev_guest_set_cbitpos, NULL, NULL, NULL);
346 object_property_add(obj, "reduced-phys-bits", "uint32",
347 qsev_guest_get_reduced_phys_bits,
348 qsev_guest_set_reduced_phys_bits, NULL, NULL, NULL);
352 static const TypeInfo qsev_guest_info = {
353 .parent = TYPE_OBJECT,
354 .name = TYPE_QSEV_GUEST_INFO,
355 .instance_size = sizeof(QSevGuestInfo),
356 .instance_finalize = qsev_guest_finalize,
357 .class_size = sizeof(QSevGuestInfoClass),
358 .class_init = qsev_guest_class_init,
359 .instance_init = qsev_guest_init,
360 .interfaces = (InterfaceInfo[]) {
361 { TYPE_USER_CREATABLE },
366 static QSevGuestInfo *
367 lookup_sev_guest_info(const char *id)
372 obj = object_resolve_path_component(object_get_objects_root(), id);
377 info = (QSevGuestInfo *)
378 object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO);
389 return sev_state ? true : false;
393 sev_get_me_mask(void)
395 return sev_state ? sev_state->me_mask : ~0;
399 sev_get_cbit_position(void)
401 return sev_state ? sev_state->cbitpos : 0;
405 sev_get_reduced_phys_bits(void)
407 return sev_state ? sev_state->reduced_phys_bits : 0;
415 info = g_new0(SevInfo, 1);
416 info->enabled = sev_state ? true : false;
419 info->api_major = sev_state->api_major;
420 info->api_minor = sev_state->api_minor;
421 info->build_id = sev_state->build_id;
422 info->policy = sev_state->policy;
423 info->state = sev_state->state;
424 info->handle = sev_state->handle;
431 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
432 size_t *cert_chain_len)
434 guchar *pdh_data = NULL;
435 guchar *cert_chain_data = NULL;
436 struct sev_user_data_pdh_cert_export export = {};
439 /* query the certificate length */
440 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
442 if (err != SEV_RET_INVALID_LEN) {
443 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
444 r, err, fw_error_to_str(err));
449 pdh_data = g_new(guchar, export.pdh_cert_len);
450 cert_chain_data = g_new(guchar, export.cert_chain_len);
451 export.pdh_cert_address = (unsigned long)pdh_data;
452 export.cert_chain_address = (unsigned long)cert_chain_data;
454 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
456 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
457 r, err, fw_error_to_str(err));
462 *pdh_len = export.pdh_cert_len;
463 *cert_chain = cert_chain_data;
464 *cert_chain_len = export.cert_chain_len;
469 g_free(cert_chain_data);
474 sev_get_capabilities(void)
476 SevCapability *cap = NULL;
477 guchar *pdh_data = NULL;
478 guchar *cert_chain_data = NULL;
479 size_t pdh_len = 0, cert_chain_len = 0;
483 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
485 error_report("%s: Failed to open %s '%s'", __func__,
486 DEFAULT_SEV_DEVICE, strerror(errno));
490 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
491 &cert_chain_data, &cert_chain_len)) {
495 cap = g_new0(SevCapability, 1);
496 cap->pdh = g_base64_encode(pdh_data, pdh_len);
497 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
499 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
500 cap->cbitpos = ebx & 0x3f;
503 * When SEV feature is enabled, we loose one bit in guest physical
506 cap->reduced_phys_bits = 1;
510 g_free(cert_chain_data);
516 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
520 GError *error = NULL;
522 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
523 error_report("failed to read '%s' (%s)", filename, error->message);
527 *data = g_base64_decode(base64, len);
532 sev_launch_start(SEVState *s)
537 QSevGuestInfo *sev = s->sev_info;
538 struct kvm_sev_launch_start *start;
539 guchar *session = NULL, *dh_cert = NULL;
541 start = g_new0(struct kvm_sev_launch_start, 1);
543 start->handle = object_property_get_int(OBJECT(sev), "handle",
545 start->policy = object_property_get_int(OBJECT(sev), "policy",
547 if (sev->session_file) {
548 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
551 start->session_uaddr = (unsigned long)session;
552 start->session_len = sz;
555 if (sev->dh_cert_file) {
556 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
559 start->dh_uaddr = (unsigned long)dh_cert;
563 trace_kvm_sev_launch_start(start->policy, session, dh_cert);
564 rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
566 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
567 __func__, ret, fw_error, fw_error_to_str(fw_error));
571 object_property_set_int(OBJECT(sev), start->handle, "handle",
573 sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE);
574 s->handle = start->handle;
575 s->policy = start->policy;
586 sev_launch_update_data(uint8_t *addr, uint64_t len)
589 struct kvm_sev_launch_update_data update;
595 update.uaddr = (__u64)(unsigned long)addr;
597 trace_kvm_sev_launch_update_data(addr, len);
598 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
601 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
602 __func__, ret, fw_error, fw_error_to_str(fw_error));
609 sev_launch_get_measure(Notifier *notifier, void *unused)
613 SEVState *s = sev_state;
614 struct kvm_sev_launch_measure *measurement;
616 if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE)) {
620 measurement = g_new0(struct kvm_sev_launch_measure, 1);
622 /* query the measurement blob length */
623 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE,
624 measurement, &error);
625 if (!measurement->len) {
626 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
627 __func__, ret, error, fw_error_to_str(errno));
628 goto free_measurement;
631 data = g_new0(guchar, measurement->len);
632 measurement->uaddr = (unsigned long)data;
634 /* get the measurement blob */
635 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE,
636 measurement, &error);
638 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
639 __func__, ret, error, fw_error_to_str(errno));
643 sev_set_guest_state(SEV_STATE_LAUNCH_SECRET);
645 /* encode the measurement value and emit the event */
646 s->measurement = g_base64_encode(data, measurement->len);
647 trace_kvm_sev_launch_measurement(s->measurement);
656 sev_get_launch_measurement(void)
659 sev_state->state >= SEV_STATE_LAUNCH_SECRET) {
660 return g_strdup(sev_state->measurement);
666 static Notifier sev_machine_done_notify = {
667 .notify = sev_launch_get_measure,
671 sev_launch_finish(SEVState *s)
674 Error *local_err = NULL;
676 trace_kvm_sev_launch_finish();
677 ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
679 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
680 __func__, ret, error, fw_error_to_str(error));
684 sev_set_guest_state(SEV_STATE_RUNNING);
686 /* add migration blocker */
687 error_setg(&sev_mig_blocker,
688 "SEV: Migration is not implemented");
689 ret = migrate_add_blocker(sev_mig_blocker, &local_err);
691 error_report_err(local_err);
692 error_free(sev_mig_blocker);
698 sev_vm_state_change(void *opaque, int running, RunState state)
700 SEVState *s = opaque;
703 if (!sev_check_state(SEV_STATE_RUNNING)) {
704 sev_launch_finish(s);
710 sev_guest_init(const char *id)
716 uint32_t host_cbitpos;
717 struct sev_user_data_status status = {};
719 sev_state = s = g_new0(SEVState, 1);
720 s->sev_info = lookup_sev_guest_info(id);
722 error_report("%s: '%s' is not a valid '%s' object",
723 __func__, id, TYPE_QSEV_GUEST_INFO);
727 s->state = SEV_STATE_UNINIT;
729 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
730 host_cbitpos = ebx & 0x3f;
732 s->cbitpos = object_property_get_int(OBJECT(s->sev_info), "cbitpos", NULL);
733 if (host_cbitpos != s->cbitpos) {
734 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
735 __func__, host_cbitpos, s->cbitpos);
739 s->reduced_phys_bits = object_property_get_int(OBJECT(s->sev_info),
740 "reduced-phys-bits", NULL);
741 if (s->reduced_phys_bits < 1) {
742 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
743 "' requested '%d'", __func__, s->reduced_phys_bits);
747 s->me_mask = ~(1UL << s->cbitpos);
749 devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL);
750 s->sev_fd = open(devname, O_RDWR);
752 error_report("%s: Failed to open %s '%s'", __func__,
753 devname, strerror(errno));
760 ret = sev_platform_ioctl(s->sev_fd, SEV_PLATFORM_STATUS, &status,
763 error_report("%s: failed to get platform status ret=%d"
764 "fw_error='%d: %s'", __func__, ret, fw_error,
765 fw_error_to_str(fw_error));
768 s->build_id = status.build;
769 s->api_major = status.api_major;
770 s->api_minor = status.api_minor;
772 trace_kvm_sev_init();
773 ret = sev_ioctl(s->sev_fd, KVM_SEV_INIT, NULL, &fw_error);
775 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
776 __func__, ret, fw_error, fw_error_to_str(fw_error));
780 ret = sev_launch_start(s);
782 error_report("%s: failed to create encryption context", __func__);
786 ram_block_notifier_add(&sev_ram_notifier);
787 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
788 qemu_add_vm_change_state_handler(sev_vm_state_change, s);
798 sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
802 /* if SEV is in update state then encrypt the data else do nothing */
803 if (sev_check_state(SEV_STATE_LAUNCH_UPDATE)) {
804 return sev_launch_update_data(ptr, len);
811 sev_register_types(void)
813 type_register_static(&qsev_guest_info);
816 type_init(sev_register_types);