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 "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"
33 #define TYPE_SEV_GUEST "sev-guest"
34 OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState
, SEV_GUEST
)
40 * The SevGuestState object is used for creating and managing a SEV
44 * -object sev-guest,id=sev0 \
45 * -machine ...,memory-encryption=sev0
47 struct SevGuestState
{
50 /* configuration parameters */
56 uint32_t reduced_phys_bits
;
69 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
70 #define DEFAULT_SEV_DEVICE "/dev/sev"
72 static SevGuestState
*sev_guest
;
73 static Error
*sev_mig_blocker
;
75 static const char *const sev_fw_errlist
[] = {
77 "Platform state is invalid",
78 "Guest state is invalid",
79 "Platform configuration is invalid",
81 "Platform is already owned",
82 "Certificate is invalid",
83 "Policy is not allowed",
84 "Guest is not active",
88 "Asid is already owned",
91 "DF_FLUSH is required",
92 "Guest handle is invalid",
97 "Feature not supported",
101 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
104 sev_ioctl(int fd
, int cmd
, void *data
, int *error
)
107 struct kvm_sev_cmd input
;
109 memset(&input
, 0x0, sizeof(input
));
113 input
.data
= (__u64
)(unsigned long)data
;
115 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_OP
, &input
);
118 *error
= input
.error
;
125 sev_platform_ioctl(int fd
, int cmd
, void *data
, int *error
)
128 struct sev_issue_cmd arg
;
131 arg
.data
= (unsigned long)data
;
132 r
= ioctl(fd
, SEV_ISSUE_CMD
, &arg
);
141 fw_error_to_str(int code
)
143 if (code
< 0 || code
>= SEV_FW_MAX_ERROR
) {
144 return "unknown error";
147 return sev_fw_errlist
[code
];
151 sev_check_state(const SevGuestState
*sev
, SevState state
)
154 return sev
->state
== state
? true : false;
158 sev_set_guest_state(SevGuestState
*sev
, SevState new_state
)
160 assert(new_state
< SEV_STATE__MAX
);
163 trace_kvm_sev_change_state(SevState_str(sev
->state
),
164 SevState_str(new_state
));
165 sev
->state
= new_state
;
169 sev_ram_block_added(RAMBlockNotifier
*n
, void *host
, size_t size
)
172 struct kvm_enc_region range
;
177 * The RAM device presents a memory region that should be treated
178 * as IO region and should not be pinned.
180 mr
= memory_region_from_host(host
, &offset
);
181 if (mr
&& memory_region_is_ram_device(mr
)) {
185 range
.addr
= (__u64
)(unsigned long)host
;
188 trace_kvm_memcrypt_register_region(host
, size
);
189 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_REG_REGION
, &range
);
191 error_report("%s: failed to register region (%p+%#zx) error '%s'",
192 __func__
, host
, size
, strerror(errno
));
198 sev_ram_block_removed(RAMBlockNotifier
*n
, void *host
, size_t size
)
201 struct kvm_enc_region range
;
206 * The RAM device presents a memory region that should be treated
207 * as IO region and should not have been pinned.
209 mr
= memory_region_from_host(host
, &offset
);
210 if (mr
&& memory_region_is_ram_device(mr
)) {
214 range
.addr
= (__u64
)(unsigned long)host
;
217 trace_kvm_memcrypt_unregister_region(host
, size
);
218 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_UNREG_REGION
, &range
);
220 error_report("%s: failed to unregister region (%p+%#zx)",
221 __func__
, host
, size
);
225 static struct RAMBlockNotifier sev_ram_notifier
= {
226 .ram_block_added
= sev_ram_block_added
,
227 .ram_block_removed
= sev_ram_block_removed
,
231 sev_guest_finalize(Object
*obj
)
236 sev_guest_get_session_file(Object
*obj
, Error
**errp
)
238 SevGuestState
*s
= SEV_GUEST(obj
);
240 return s
->session_file
? g_strdup(s
->session_file
) : NULL
;
244 sev_guest_set_session_file(Object
*obj
, const char *value
, Error
**errp
)
246 SevGuestState
*s
= SEV_GUEST(obj
);
248 s
->session_file
= g_strdup(value
);
252 sev_guest_get_dh_cert_file(Object
*obj
, Error
**errp
)
254 SevGuestState
*s
= SEV_GUEST(obj
);
256 return g_strdup(s
->dh_cert_file
);
260 sev_guest_set_dh_cert_file(Object
*obj
, const char *value
, Error
**errp
)
262 SevGuestState
*s
= SEV_GUEST(obj
);
264 s
->dh_cert_file
= g_strdup(value
);
268 sev_guest_get_sev_device(Object
*obj
, Error
**errp
)
270 SevGuestState
*sev
= SEV_GUEST(obj
);
272 return g_strdup(sev
->sev_device
);
276 sev_guest_set_sev_device(Object
*obj
, const char *value
, Error
**errp
)
278 SevGuestState
*sev
= SEV_GUEST(obj
);
280 sev
->sev_device
= g_strdup(value
);
284 sev_guest_class_init(ObjectClass
*oc
, void *data
)
286 object_class_property_add_str(oc
, "sev-device",
287 sev_guest_get_sev_device
,
288 sev_guest_set_sev_device
);
289 object_class_property_set_description(oc
, "sev-device",
290 "SEV device to use");
291 object_class_property_add_str(oc
, "dh-cert-file",
292 sev_guest_get_dh_cert_file
,
293 sev_guest_set_dh_cert_file
);
294 object_class_property_set_description(oc
, "dh-cert-file",
295 "guest owners DH certificate (encoded with base64)");
296 object_class_property_add_str(oc
, "session-file",
297 sev_guest_get_session_file
,
298 sev_guest_set_session_file
);
299 object_class_property_set_description(oc
, "session-file",
300 "guest owners session parameters (encoded with base64)");
304 sev_guest_instance_init(Object
*obj
)
306 SevGuestState
*sev
= SEV_GUEST(obj
);
308 sev
->sev_device
= g_strdup(DEFAULT_SEV_DEVICE
);
309 sev
->policy
= DEFAULT_GUEST_POLICY
;
310 object_property_add_uint32_ptr(obj
, "policy", &sev
->policy
,
311 OBJ_PROP_FLAG_READWRITE
);
312 object_property_add_uint32_ptr(obj
, "handle", &sev
->handle
,
313 OBJ_PROP_FLAG_READWRITE
);
314 object_property_add_uint32_ptr(obj
, "cbitpos", &sev
->cbitpos
,
315 OBJ_PROP_FLAG_READWRITE
);
316 object_property_add_uint32_ptr(obj
, "reduced-phys-bits",
317 &sev
->reduced_phys_bits
,
318 OBJ_PROP_FLAG_READWRITE
);
322 static const TypeInfo sev_guest_info
= {
323 .parent
= TYPE_OBJECT
,
324 .name
= TYPE_SEV_GUEST
,
325 .instance_size
= sizeof(SevGuestState
),
326 .instance_finalize
= sev_guest_finalize
,
327 .class_init
= sev_guest_class_init
,
328 .instance_init
= sev_guest_instance_init
,
329 .interfaces
= (InterfaceInfo
[]) {
330 { TYPE_USER_CREATABLE
},
335 static SevGuestState
*
336 lookup_sev_guest_info(const char *id
)
341 obj
= object_resolve_path_component(object_get_objects_root(), id
);
346 info
= (SevGuestState
*)
347 object_dynamic_cast(obj
, TYPE_SEV_GUEST
);
362 sev_get_me_mask(void)
364 return sev_guest
? sev_guest
->me_mask
: ~0;
368 sev_get_cbit_position(void)
370 return sev_guest
? sev_guest
->cbitpos
: 0;
374 sev_get_reduced_phys_bits(void)
376 return sev_guest
? sev_guest
->reduced_phys_bits
: 0;
384 info
= g_new0(SevInfo
, 1);
385 info
->enabled
= sev_enabled();
388 info
->api_major
= sev_guest
->api_major
;
389 info
->api_minor
= sev_guest
->api_minor
;
390 info
->build_id
= sev_guest
->build_id
;
391 info
->policy
= sev_guest
->policy
;
392 info
->state
= sev_guest
->state
;
393 info
->handle
= sev_guest
->handle
;
400 sev_get_pdh_info(int fd
, guchar
**pdh
, size_t *pdh_len
, guchar
**cert_chain
,
401 size_t *cert_chain_len
, Error
**errp
)
403 guchar
*pdh_data
= NULL
;
404 guchar
*cert_chain_data
= NULL
;
405 struct sev_user_data_pdh_cert_export export
= {};
408 /* query the certificate length */
409 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
411 if (err
!= SEV_RET_INVALID_LEN
) {
412 error_setg(errp
, "failed to export PDH cert ret=%d fw_err=%d (%s)",
413 r
, err
, fw_error_to_str(err
));
418 pdh_data
= g_new(guchar
, export
.pdh_cert_len
);
419 cert_chain_data
= g_new(guchar
, export
.cert_chain_len
);
420 export
.pdh_cert_address
= (unsigned long)pdh_data
;
421 export
.cert_chain_address
= (unsigned long)cert_chain_data
;
423 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
425 error_setg(errp
, "failed to export PDH cert ret=%d fw_err=%d (%s)",
426 r
, err
, fw_error_to_str(err
));
431 *pdh_len
= export
.pdh_cert_len
;
432 *cert_chain
= cert_chain_data
;
433 *cert_chain_len
= export
.cert_chain_len
;
438 g_free(cert_chain_data
);
443 sev_get_capabilities(Error
**errp
)
445 SevCapability
*cap
= NULL
;
446 guchar
*pdh_data
= NULL
;
447 guchar
*cert_chain_data
= NULL
;
448 size_t pdh_len
= 0, cert_chain_len
= 0;
452 if (!kvm_enabled()) {
453 error_setg(errp
, "KVM not enabled");
456 if (kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_OP
, NULL
) < 0) {
457 error_setg(errp
, "SEV is not enabled in KVM");
461 fd
= open(DEFAULT_SEV_DEVICE
, O_RDWR
);
463 error_setg_errno(errp
, errno
, "Failed to open %s",
468 if (sev_get_pdh_info(fd
, &pdh_data
, &pdh_len
,
469 &cert_chain_data
, &cert_chain_len
, errp
)) {
473 cap
= g_new0(SevCapability
, 1);
474 cap
->pdh
= g_base64_encode(pdh_data
, pdh_len
);
475 cap
->cert_chain
= g_base64_encode(cert_chain_data
, cert_chain_len
);
477 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
478 cap
->cbitpos
= ebx
& 0x3f;
481 * When SEV feature is enabled, we loose one bit in guest physical
484 cap
->reduced_phys_bits
= 1;
488 g_free(cert_chain_data
);
494 sev_read_file_base64(const char *filename
, guchar
**data
, gsize
*len
)
498 GError
*error
= NULL
;
500 if (!g_file_get_contents(filename
, &base64
, &sz
, &error
)) {
501 error_report("failed to read '%s' (%s)", filename
, error
->message
);
506 *data
= g_base64_decode(base64
, len
);
511 sev_launch_start(SevGuestState
*sev
)
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) {
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) {
535 start
->dh_uaddr
= (unsigned long)dh_cert
;
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
);
542 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
543 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
547 sev_set_guest_state(sev
, SEV_STATE_LAUNCH_UPDATE
);
548 sev
->handle
= start
->handle
;
559 sev_launch_update_data(SevGuestState
*sev
, uint8_t *addr
, uint64_t len
)
562 struct kvm_sev_launch_update_data update
;
568 update
.uaddr
= (__u64
)(unsigned long)addr
;
570 trace_kvm_sev_launch_update_data(addr
, len
);
571 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_UPDATE_DATA
,
574 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
575 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
582 sev_launch_get_measure(Notifier
*notifier
, void *unused
)
584 SevGuestState
*sev
= sev_guest
;
587 struct kvm_sev_launch_measure
*measurement
;
589 if (!sev_check_state(sev
, SEV_STATE_LAUNCH_UPDATE
)) {
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
);
611 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
612 __func__
, ret
, error
, fw_error_to_str(errno
));
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
);
629 sev_get_launch_measurement(void)
632 sev_guest
->state
>= SEV_STATE_LAUNCH_SECRET
) {
633 return g_strdup(sev_guest
->measurement
);
639 static Notifier sev_machine_done_notify
= {
640 .notify
= sev_launch_get_measure
,
644 sev_launch_finish(SevGuestState
*sev
)
647 Error
*local_err
= NULL
;
649 trace_kvm_sev_launch_finish();
650 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_FINISH
, 0, &error
);
652 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
653 __func__
, ret
, error
, fw_error_to_str(error
));
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
);
664 error_report_err(local_err
);
665 error_free(sev_mig_blocker
);
671 sev_vm_state_change(void *opaque
, int running
, RunState state
)
673 SevGuestState
*sev
= opaque
;
676 if (!sev_check_state(sev
, SEV_STATE_RUNNING
)) {
677 sev_launch_finish(sev
);
683 sev_guest_init(const char *id
)
689 uint32_t host_cbitpos
;
690 struct sev_user_data_status status
= {};
692 ret
= ram_block_discard_disable(true);
694 error_report("%s: cannot disable RAM discard", __func__
);
698 sev
= lookup_sev_guest_info(id
);
700 error_report("%s: '%s' is not a valid '%s' object",
701 __func__
, id
, TYPE_SEV_GUEST
);
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
);
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
);
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
));
732 if (sev
->sev_fd
< 0) {
736 ret
= sev_platform_ioctl(sev
->sev_fd
, SEV_PLATFORM_STATUS
, &status
,
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
));
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
);
751 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
752 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
756 ret
= sev_launch_start(sev
);
758 error_report("%s: failed to create encryption context", __func__
);
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
);
769 ram_block_discard_disable(false);
774 sev_encrypt_data(void *handle
, uint8_t *ptr
, uint64_t len
)
776 SevGuestState
*sev
= handle
;
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
);
789 sev_register_types(void)
791 type_register_static(&sev_guest_info
);
794 type_init(sev_register_types
);