4 * Copyright Advanced Micro Devices 2016-2018
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 <linux/kvm.h>
15 #include <linux/psp-sev.h>
17 #include <sys/ioctl.h>
19 #include "qemu/osdep.h"
20 #include "qapi/error.h"
21 #include "qom/object_interfaces.h"
22 #include "qemu/base64.h"
23 #include "sysemu/kvm.h"
25 #include "sysemu/sysemu.h"
27 #include "migration/blocker.h"
29 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
30 #define DEFAULT_SEV_DEVICE "/dev/sev"
32 static SEVState
*sev_state
;
33 static Error
*sev_mig_blocker
;
35 static const char *const sev_fw_errlist
[] = {
37 "Platform state is invalid",
38 "Guest state is invalid",
39 "Platform configuration is invalid",
41 "Platform is already owned",
42 "Certificate is invalid",
43 "Policy is not allowed",
44 "Guest is not active",
48 "Asid is already owned",
51 "DF_FLUSH is required",
52 "Guest handle is invalid",
57 "Feature not supported",
61 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
64 sev_ioctl(int fd
, int cmd
, void *data
, int *error
)
67 struct kvm_sev_cmd input
;
69 memset(&input
, 0x0, sizeof(input
));
73 input
.data
= (__u64
)(unsigned long)data
;
75 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_OP
, &input
);
85 sev_platform_ioctl(int fd
, int cmd
, void *data
, int *error
)
88 struct sev_issue_cmd arg
;
91 arg
.data
= (unsigned long)data
;
92 r
= ioctl(fd
, SEV_ISSUE_CMD
, &arg
);
101 fw_error_to_str(int code
)
103 if (code
< 0 || code
>= SEV_FW_MAX_ERROR
) {
104 return "unknown error";
107 return sev_fw_errlist
[code
];
111 sev_check_state(SevState state
)
114 return sev_state
->state
== state
? true : false;
118 sev_set_guest_state(SevState new_state
)
120 assert(new_state
< SEV_STATE__MAX
);
123 trace_kvm_sev_change_state(SevState_str(sev_state
->state
),
124 SevState_str(new_state
));
125 sev_state
->state
= new_state
;
129 sev_ram_block_added(RAMBlockNotifier
*n
, void *host
, size_t size
)
132 struct kvm_enc_region range
;
134 range
.addr
= (__u64
)(unsigned long)host
;
137 trace_kvm_memcrypt_register_region(host
, size
);
138 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_REG_REGION
, &range
);
140 error_report("%s: failed to register region (%p+%#zx) error '%s'",
141 __func__
, host
, size
, strerror(errno
));
147 sev_ram_block_removed(RAMBlockNotifier
*n
, void *host
, size_t size
)
150 struct kvm_enc_region range
;
152 range
.addr
= (__u64
)(unsigned long)host
;
155 trace_kvm_memcrypt_unregister_region(host
, size
);
156 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_UNREG_REGION
, &range
);
158 error_report("%s: failed to unregister region (%p+%#zx)",
159 __func__
, host
, size
);
163 static struct RAMBlockNotifier sev_ram_notifier
= {
164 .ram_block_added
= sev_ram_block_added
,
165 .ram_block_removed
= sev_ram_block_removed
,
169 qsev_guest_finalize(Object
*obj
)
174 qsev_guest_get_session_file(Object
*obj
, Error
**errp
)
176 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
178 return s
->session_file
? g_strdup(s
->session_file
) : NULL
;
182 qsev_guest_set_session_file(Object
*obj
, const char *value
, Error
**errp
)
184 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
186 s
->session_file
= g_strdup(value
);
190 qsev_guest_get_dh_cert_file(Object
*obj
, Error
**errp
)
192 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
194 return g_strdup(s
->dh_cert_file
);
198 qsev_guest_set_dh_cert_file(Object
*obj
, const char *value
, Error
**errp
)
200 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
202 s
->dh_cert_file
= g_strdup(value
);
206 qsev_guest_get_sev_device(Object
*obj
, Error
**errp
)
208 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
210 return g_strdup(sev
->sev_device
);
214 qsev_guest_set_sev_device(Object
*obj
, const char *value
, Error
**errp
)
216 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
218 sev
->sev_device
= g_strdup(value
);
222 qsev_guest_class_init(ObjectClass
*oc
, void *data
)
224 object_class_property_add_str(oc
, "sev-device",
225 qsev_guest_get_sev_device
,
226 qsev_guest_set_sev_device
,
228 object_class_property_set_description(oc
, "sev-device",
229 "SEV device to use", NULL
);
230 object_class_property_add_str(oc
, "dh-cert-file",
231 qsev_guest_get_dh_cert_file
,
232 qsev_guest_set_dh_cert_file
,
234 object_class_property_set_description(oc
, "dh-cert-file",
235 "guest owners DH certificate (encoded with base64)", NULL
);
236 object_class_property_add_str(oc
, "session-file",
237 qsev_guest_get_session_file
,
238 qsev_guest_set_session_file
,
240 object_class_property_set_description(oc
, "session-file",
241 "guest owners session parameters (encoded with base64)", NULL
);
245 qsev_guest_set_handle(Object
*obj
, Visitor
*v
, const char *name
,
246 void *opaque
, Error
**errp
)
248 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
251 visit_type_uint32(v
, name
, &value
, errp
);
256 qsev_guest_set_policy(Object
*obj
, Visitor
*v
, const char *name
,
257 void *opaque
, Error
**errp
)
259 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
262 visit_type_uint32(v
, name
, &value
, errp
);
267 qsev_guest_set_cbitpos(Object
*obj
, Visitor
*v
, const char *name
,
268 void *opaque
, Error
**errp
)
270 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
273 visit_type_uint32(v
, name
, &value
, errp
);
274 sev
->cbitpos
= value
;
278 qsev_guest_set_reduced_phys_bits(Object
*obj
, Visitor
*v
, const char *name
,
279 void *opaque
, Error
**errp
)
281 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
284 visit_type_uint32(v
, name
, &value
, errp
);
285 sev
->reduced_phys_bits
= value
;
289 qsev_guest_get_policy(Object
*obj
, Visitor
*v
, const char *name
,
290 void *opaque
, Error
**errp
)
293 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
296 visit_type_uint32(v
, name
, &value
, errp
);
300 qsev_guest_get_handle(Object
*obj
, Visitor
*v
, const char *name
,
301 void *opaque
, Error
**errp
)
304 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
307 visit_type_uint32(v
, name
, &value
, errp
);
311 qsev_guest_get_cbitpos(Object
*obj
, Visitor
*v
, const char *name
,
312 void *opaque
, Error
**errp
)
315 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
317 value
= sev
->cbitpos
;
318 visit_type_uint32(v
, name
, &value
, errp
);
322 qsev_guest_get_reduced_phys_bits(Object
*obj
, Visitor
*v
, const char *name
,
323 void *opaque
, Error
**errp
)
326 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
328 value
= sev
->reduced_phys_bits
;
329 visit_type_uint32(v
, name
, &value
, errp
);
333 qsev_guest_init(Object
*obj
)
335 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
337 sev
->sev_device
= g_strdup(DEFAULT_SEV_DEVICE
);
338 sev
->policy
= DEFAULT_GUEST_POLICY
;
339 object_property_add(obj
, "policy", "uint32", qsev_guest_get_policy
,
340 qsev_guest_set_policy
, NULL
, NULL
, NULL
);
341 object_property_add(obj
, "handle", "uint32", qsev_guest_get_handle
,
342 qsev_guest_set_handle
, NULL
, NULL
, NULL
);
343 object_property_add(obj
, "cbitpos", "uint32", qsev_guest_get_cbitpos
,
344 qsev_guest_set_cbitpos
, NULL
, NULL
, NULL
);
345 object_property_add(obj
, "reduced-phys-bits", "uint32",
346 qsev_guest_get_reduced_phys_bits
,
347 qsev_guest_set_reduced_phys_bits
, NULL
, NULL
, NULL
);
351 static const TypeInfo qsev_guest_info
= {
352 .parent
= TYPE_OBJECT
,
353 .name
= TYPE_QSEV_GUEST_INFO
,
354 .instance_size
= sizeof(QSevGuestInfo
),
355 .instance_finalize
= qsev_guest_finalize
,
356 .class_size
= sizeof(QSevGuestInfoClass
),
357 .class_init
= qsev_guest_class_init
,
358 .instance_init
= qsev_guest_init
,
359 .interfaces
= (InterfaceInfo
[]) {
360 { TYPE_USER_CREATABLE
},
365 static QSevGuestInfo
*
366 lookup_sev_guest_info(const char *id
)
371 obj
= object_resolve_path_component(object_get_objects_root(), id
);
376 info
= (QSevGuestInfo
*)
377 object_dynamic_cast(obj
, TYPE_QSEV_GUEST_INFO
);
388 return sev_state
? true : false;
392 sev_get_me_mask(void)
394 return sev_state
? sev_state
->me_mask
: ~0;
398 sev_get_cbit_position(void)
400 return sev_state
? sev_state
->cbitpos
: 0;
404 sev_get_reduced_phys_bits(void)
406 return sev_state
? sev_state
->reduced_phys_bits
: 0;
414 info
= g_new0(SevInfo
, 1);
415 info
->enabled
= sev_state
? true : false;
418 info
->api_major
= sev_state
->api_major
;
419 info
->api_minor
= sev_state
->api_minor
;
420 info
->build_id
= sev_state
->build_id
;
421 info
->policy
= sev_state
->policy
;
422 info
->state
= sev_state
->state
;
423 info
->handle
= sev_state
->handle
;
430 sev_get_pdh_info(int fd
, guchar
**pdh
, size_t *pdh_len
, guchar
**cert_chain
,
431 size_t *cert_chain_len
)
433 guchar
*pdh_data
, *cert_chain_data
;
434 struct sev_user_data_pdh_cert_export export
= {};
437 /* query the certificate length */
438 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
440 if (err
!= SEV_RET_INVALID_LEN
) {
441 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
442 r
, err
, fw_error_to_str(err
));
447 pdh_data
= g_new(guchar
, export
.pdh_cert_len
);
448 cert_chain_data
= g_new(guchar
, export
.cert_chain_len
);
449 export
.pdh_cert_address
= (unsigned long)pdh_data
;
450 export
.cert_chain_address
= (unsigned long)cert_chain_data
;
452 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
454 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
455 r
, err
, fw_error_to_str(err
));
460 *pdh_len
= export
.pdh_cert_len
;
461 *cert_chain
= cert_chain_data
;
462 *cert_chain_len
= export
.cert_chain_len
;
467 g_free(cert_chain_data
);
472 sev_get_capabilities(void)
475 guchar
*pdh_data
, *cert_chain_data
;
476 size_t pdh_len
= 0, cert_chain_len
= 0;
480 fd
= open(DEFAULT_SEV_DEVICE
, O_RDWR
);
482 error_report("%s: Failed to open %s '%s'", __func__
,
483 DEFAULT_SEV_DEVICE
, strerror(errno
));
487 if (sev_get_pdh_info(fd
, &pdh_data
, &pdh_len
,
488 &cert_chain_data
, &cert_chain_len
)) {
492 cap
= g_new0(SevCapability
, 1);
493 cap
->pdh
= g_base64_encode(pdh_data
, pdh_len
);
494 cap
->cert_chain
= g_base64_encode(cert_chain_data
, cert_chain_len
);
496 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
497 cap
->cbitpos
= ebx
& 0x3f;
500 * When SEV feature is enabled, we loose one bit in guest physical
503 cap
->reduced_phys_bits
= 1;
506 g_free(cert_chain_data
);
513 sev_read_file_base64(const char *filename
, guchar
**data
, gsize
*len
)
517 GError
*error
= NULL
;
519 if (!g_file_get_contents(filename
, &base64
, &sz
, &error
)) {
520 error_report("failed to read '%s' (%s)", filename
, error
->message
);
524 *data
= g_base64_decode(base64
, len
);
529 sev_launch_start(SEVState
*s
)
534 QSevGuestInfo
*sev
= s
->sev_info
;
535 struct kvm_sev_launch_start
*start
;
536 guchar
*session
= NULL
, *dh_cert
= NULL
;
538 start
= g_new0(struct kvm_sev_launch_start
, 1);
540 start
->handle
= object_property_get_int(OBJECT(sev
), "handle",
542 start
->policy
= object_property_get_int(OBJECT(sev
), "policy",
544 if (sev
->session_file
) {
545 if (sev_read_file_base64(sev
->session_file
, &session
, &sz
) < 0) {
548 start
->session_uaddr
= (unsigned long)session
;
549 start
->session_len
= sz
;
552 if (sev
->dh_cert_file
) {
553 if (sev_read_file_base64(sev
->dh_cert_file
, &dh_cert
, &sz
) < 0) {
556 start
->dh_uaddr
= (unsigned long)dh_cert
;
560 trace_kvm_sev_launch_start(start
->policy
, session
, dh_cert
);
561 ret
= sev_ioctl(s
->sev_fd
, KVM_SEV_LAUNCH_START
, start
, &fw_error
);
563 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
564 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
568 object_property_set_int(OBJECT(sev
), start
->handle
, "handle",
570 sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE
);
571 s
->handle
= start
->handle
;
572 s
->policy
= start
->policy
;
582 sev_launch_update_data(uint8_t *addr
, uint64_t len
)
585 struct kvm_sev_launch_update_data update
;
591 update
.uaddr
= (__u64
)(unsigned long)addr
;
593 trace_kvm_sev_launch_update_data(addr
, len
);
594 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_UPDATE_DATA
,
597 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
598 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
605 sev_launch_get_measure(Notifier
*notifier
, void *unused
)
609 SEVState
*s
= sev_state
;
610 struct kvm_sev_launch_measure
*measurement
;
612 if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE
)) {
616 measurement
= g_new0(struct kvm_sev_launch_measure
, 1);
618 /* query the measurement blob length */
619 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
620 measurement
, &error
);
621 if (!measurement
->len
) {
622 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
623 __func__
, ret
, error
, fw_error_to_str(errno
));
624 goto free_measurement
;
627 data
= g_new0(guchar
, measurement
->len
);
628 measurement
->uaddr
= (unsigned long)data
;
630 /* get the measurement blob */
631 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
632 measurement
, &error
);
634 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
635 __func__
, ret
, error
, fw_error_to_str(errno
));
639 sev_set_guest_state(SEV_STATE_LAUNCH_SECRET
);
641 /* encode the measurement value and emit the event */
642 s
->measurement
= g_base64_encode(data
, measurement
->len
);
643 trace_kvm_sev_launch_measurement(s
->measurement
);
652 sev_get_launch_measurement(void)
655 sev_state
->state
>= SEV_STATE_LAUNCH_SECRET
) {
656 return g_strdup(sev_state
->measurement
);
662 static Notifier sev_machine_done_notify
= {
663 .notify
= sev_launch_get_measure
,
667 sev_launch_finish(SEVState
*s
)
670 Error
*local_err
= NULL
;
672 trace_kvm_sev_launch_finish();
673 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_FINISH
, 0, &error
);
675 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
676 __func__
, ret
, error
, fw_error_to_str(error
));
680 sev_set_guest_state(SEV_STATE_RUNNING
);
682 /* add migration blocker */
683 error_setg(&sev_mig_blocker
,
684 "SEV: Migration is not implemented");
685 ret
= migrate_add_blocker(sev_mig_blocker
, &local_err
);
687 error_report_err(local_err
);
688 error_free(sev_mig_blocker
);
694 sev_vm_state_change(void *opaque
, int running
, RunState state
)
696 SEVState
*s
= opaque
;
699 if (!sev_check_state(SEV_STATE_RUNNING
)) {
700 sev_launch_finish(s
);
706 sev_guest_init(const char *id
)
712 uint32_t host_cbitpos
;
713 struct sev_user_data_status status
= {};
715 s
= g_new0(SEVState
, 1);
716 s
->sev_info
= lookup_sev_guest_info(id
);
718 error_report("%s: '%s' is not a valid '%s' object",
719 __func__
, id
, TYPE_QSEV_GUEST_INFO
);
724 s
->state
= SEV_STATE_UNINIT
;
726 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
727 host_cbitpos
= ebx
& 0x3f;
729 s
->cbitpos
= object_property_get_int(OBJECT(s
->sev_info
), "cbitpos", NULL
);
730 if (host_cbitpos
!= s
->cbitpos
) {
731 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
732 __func__
, host_cbitpos
, s
->cbitpos
);
736 s
->reduced_phys_bits
= object_property_get_int(OBJECT(s
->sev_info
),
737 "reduced-phys-bits", NULL
);
738 if (s
->reduced_phys_bits
< 1) {
739 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
740 "' requested '%d'", __func__
, s
->reduced_phys_bits
);
744 s
->me_mask
= ~(1UL << s
->cbitpos
);
746 devname
= object_property_get_str(OBJECT(s
->sev_info
), "sev-device", NULL
);
747 s
->sev_fd
= open(devname
, O_RDWR
);
749 error_report("%s: Failed to open %s '%s'", __func__
,
750 devname
, strerror(errno
));
755 ret
= sev_platform_ioctl(s
->sev_fd
, SEV_PLATFORM_STATUS
, &status
,
758 error_report("%s: failed to get platform status ret=%d"
759 "fw_error='%d: %s'", __func__
, ret
, fw_error
,
760 fw_error_to_str(fw_error
));
763 s
->build_id
= status
.build
;
764 s
->api_major
= status
.api_major
;
765 s
->api_minor
= status
.api_minor
;
767 trace_kvm_sev_init();
768 ret
= sev_ioctl(s
->sev_fd
, KVM_SEV_INIT
, NULL
, &fw_error
);
770 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
771 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
775 ret
= sev_launch_start(s
);
777 error_report("%s: failed to create encryption context", __func__
);
781 ram_block_notifier_add(&sev_ram_notifier
);
782 qemu_add_machine_init_done_notifier(&sev_machine_done_notify
);
783 qemu_add_vm_change_state_handler(sev_vm_state_change
, s
);
793 sev_encrypt_data(void *handle
, uint8_t *ptr
, uint64_t len
)
797 /* if SEV is in update state then encrypt the data else do nothing */
798 if (sev_check_state(SEV_STATE_LAUNCH_UPDATE
)) {
799 return sev_launch_update_data(ptr
, len
);
806 sev_register_types(void)
808 type_register_static(&qsev_guest_info
);
811 type_init(sev_register_types
);