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"
32 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
33 #define DEFAULT_SEV_DEVICE "/dev/sev"
35 static SEVState
*sev_state
;
36 static Error
*sev_mig_blocker
;
38 static const char *const sev_fw_errlist
[] = {
40 "Platform state is invalid",
41 "Guest state is invalid",
42 "Platform configuration is invalid",
44 "Platform is already owned",
45 "Certificate is invalid",
46 "Policy is not allowed",
47 "Guest is not active",
51 "Asid is already owned",
54 "DF_FLUSH is required",
55 "Guest handle is invalid",
60 "Feature not supported",
64 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
67 sev_ioctl(int fd
, int cmd
, void *data
, int *error
)
70 struct kvm_sev_cmd input
;
72 memset(&input
, 0x0, sizeof(input
));
76 input
.data
= (__u64
)(unsigned long)data
;
78 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_OP
, &input
);
88 sev_platform_ioctl(int fd
, int cmd
, void *data
, int *error
)
91 struct sev_issue_cmd arg
;
94 arg
.data
= (unsigned long)data
;
95 r
= ioctl(fd
, SEV_ISSUE_CMD
, &arg
);
104 fw_error_to_str(int code
)
106 if (code
< 0 || code
>= SEV_FW_MAX_ERROR
) {
107 return "unknown error";
110 return sev_fw_errlist
[code
];
114 sev_check_state(SevState state
)
117 return sev_state
->state
== state
? true : false;
121 sev_set_guest_state(SevState new_state
)
123 assert(new_state
< SEV_STATE__MAX
);
126 trace_kvm_sev_change_state(SevState_str(sev_state
->state
),
127 SevState_str(new_state
));
128 sev_state
->state
= new_state
;
132 sev_ram_block_added(RAMBlockNotifier
*n
, void *host
, size_t size
)
135 struct kvm_enc_region range
;
140 * The RAM device presents a memory region that should be treated
141 * as IO region and should not be pinned.
143 mr
= memory_region_from_host(host
, &offset
);
144 if (mr
&& memory_region_is_ram_device(mr
)) {
148 range
.addr
= (__u64
)(unsigned long)host
;
151 trace_kvm_memcrypt_register_region(host
, size
);
152 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_REG_REGION
, &range
);
154 error_report("%s: failed to register region (%p+%#zx) error '%s'",
155 __func__
, host
, size
, strerror(errno
));
161 sev_ram_block_removed(RAMBlockNotifier
*n
, void *host
, size_t size
)
164 struct kvm_enc_region range
;
169 * The RAM device presents a memory region that should be treated
170 * as IO region and should not have been pinned.
172 mr
= memory_region_from_host(host
, &offset
);
173 if (mr
&& memory_region_is_ram_device(mr
)) {
177 range
.addr
= (__u64
)(unsigned long)host
;
180 trace_kvm_memcrypt_unregister_region(host
, size
);
181 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_UNREG_REGION
, &range
);
183 error_report("%s: failed to unregister region (%p+%#zx)",
184 __func__
, host
, size
);
188 static struct RAMBlockNotifier sev_ram_notifier
= {
189 .ram_block_added
= sev_ram_block_added
,
190 .ram_block_removed
= sev_ram_block_removed
,
194 qsev_guest_finalize(Object
*obj
)
199 qsev_guest_get_session_file(Object
*obj
, Error
**errp
)
201 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
203 return s
->session_file
? g_strdup(s
->session_file
) : NULL
;
207 qsev_guest_set_session_file(Object
*obj
, const char *value
, Error
**errp
)
209 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
211 s
->session_file
= g_strdup(value
);
215 qsev_guest_get_dh_cert_file(Object
*obj
, Error
**errp
)
217 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
219 return g_strdup(s
->dh_cert_file
);
223 qsev_guest_set_dh_cert_file(Object
*obj
, const char *value
, Error
**errp
)
225 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
227 s
->dh_cert_file
= g_strdup(value
);
231 qsev_guest_get_sev_device(Object
*obj
, Error
**errp
)
233 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
235 return g_strdup(sev
->sev_device
);
239 qsev_guest_set_sev_device(Object
*obj
, const char *value
, Error
**errp
)
241 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
243 sev
->sev_device
= g_strdup(value
);
247 qsev_guest_class_init(ObjectClass
*oc
, void *data
)
249 object_class_property_add_str(oc
, "sev-device",
250 qsev_guest_get_sev_device
,
251 qsev_guest_set_sev_device
,
253 object_class_property_set_description(oc
, "sev-device",
254 "SEV device to use", NULL
);
255 object_class_property_add_str(oc
, "dh-cert-file",
256 qsev_guest_get_dh_cert_file
,
257 qsev_guest_set_dh_cert_file
,
259 object_class_property_set_description(oc
, "dh-cert-file",
260 "guest owners DH certificate (encoded with base64)", NULL
);
261 object_class_property_add_str(oc
, "session-file",
262 qsev_guest_get_session_file
,
263 qsev_guest_set_session_file
,
265 object_class_property_set_description(oc
, "session-file",
266 "guest owners session parameters (encoded with base64)", NULL
);
270 qsev_guest_set_handle(Object
*obj
, Visitor
*v
, const char *name
,
271 void *opaque
, Error
**errp
)
273 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
276 visit_type_uint32(v
, name
, &value
, errp
);
281 qsev_guest_set_policy(Object
*obj
, Visitor
*v
, const char *name
,
282 void *opaque
, Error
**errp
)
284 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
287 visit_type_uint32(v
, name
, &value
, errp
);
292 qsev_guest_set_cbitpos(Object
*obj
, Visitor
*v
, const char *name
,
293 void *opaque
, Error
**errp
)
295 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
298 visit_type_uint32(v
, name
, &value
, errp
);
299 sev
->cbitpos
= value
;
303 qsev_guest_set_reduced_phys_bits(Object
*obj
, Visitor
*v
, const char *name
,
304 void *opaque
, Error
**errp
)
306 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
309 visit_type_uint32(v
, name
, &value
, errp
);
310 sev
->reduced_phys_bits
= value
;
314 qsev_guest_get_policy(Object
*obj
, Visitor
*v
, const char *name
,
315 void *opaque
, Error
**errp
)
318 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
321 visit_type_uint32(v
, name
, &value
, errp
);
325 qsev_guest_get_handle(Object
*obj
, Visitor
*v
, const char *name
,
326 void *opaque
, Error
**errp
)
329 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
332 visit_type_uint32(v
, name
, &value
, errp
);
336 qsev_guest_get_cbitpos(Object
*obj
, Visitor
*v
, const char *name
,
337 void *opaque
, Error
**errp
)
340 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
342 value
= sev
->cbitpos
;
343 visit_type_uint32(v
, name
, &value
, errp
);
347 qsev_guest_get_reduced_phys_bits(Object
*obj
, Visitor
*v
, const char *name
,
348 void *opaque
, Error
**errp
)
351 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
353 value
= sev
->reduced_phys_bits
;
354 visit_type_uint32(v
, name
, &value
, errp
);
358 qsev_guest_init(Object
*obj
)
360 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
362 sev
->sev_device
= g_strdup(DEFAULT_SEV_DEVICE
);
363 sev
->policy
= DEFAULT_GUEST_POLICY
;
364 object_property_add(obj
, "policy", "uint32", qsev_guest_get_policy
,
365 qsev_guest_set_policy
, NULL
, NULL
, NULL
);
366 object_property_add(obj
, "handle", "uint32", qsev_guest_get_handle
,
367 qsev_guest_set_handle
, NULL
, NULL
, NULL
);
368 object_property_add(obj
, "cbitpos", "uint32", qsev_guest_get_cbitpos
,
369 qsev_guest_set_cbitpos
, NULL
, NULL
, NULL
);
370 object_property_add(obj
, "reduced-phys-bits", "uint32",
371 qsev_guest_get_reduced_phys_bits
,
372 qsev_guest_set_reduced_phys_bits
, NULL
, NULL
, NULL
);
376 static const TypeInfo qsev_guest_info
= {
377 .parent
= TYPE_OBJECT
,
378 .name
= TYPE_QSEV_GUEST_INFO
,
379 .instance_size
= sizeof(QSevGuestInfo
),
380 .instance_finalize
= qsev_guest_finalize
,
381 .class_size
= sizeof(QSevGuestInfoClass
),
382 .class_init
= qsev_guest_class_init
,
383 .instance_init
= qsev_guest_init
,
384 .interfaces
= (InterfaceInfo
[]) {
385 { TYPE_USER_CREATABLE
},
390 static QSevGuestInfo
*
391 lookup_sev_guest_info(const char *id
)
396 obj
= object_resolve_path_component(object_get_objects_root(), id
);
401 info
= (QSevGuestInfo
*)
402 object_dynamic_cast(obj
, TYPE_QSEV_GUEST_INFO
);
413 return sev_state
? true : false;
417 sev_get_me_mask(void)
419 return sev_state
? sev_state
->me_mask
: ~0;
423 sev_get_cbit_position(void)
425 return sev_state
? sev_state
->cbitpos
: 0;
429 sev_get_reduced_phys_bits(void)
431 return sev_state
? sev_state
->reduced_phys_bits
: 0;
439 info
= g_new0(SevInfo
, 1);
440 info
->enabled
= sev_state
? true : false;
443 info
->api_major
= sev_state
->api_major
;
444 info
->api_minor
= sev_state
->api_minor
;
445 info
->build_id
= sev_state
->build_id
;
446 info
->policy
= sev_state
->policy
;
447 info
->state
= sev_state
->state
;
448 info
->handle
= sev_state
->handle
;
455 sev_get_pdh_info(int fd
, guchar
**pdh
, size_t *pdh_len
, guchar
**cert_chain
,
456 size_t *cert_chain_len
)
458 guchar
*pdh_data
= NULL
;
459 guchar
*cert_chain_data
= NULL
;
460 struct sev_user_data_pdh_cert_export export
= {};
463 /* query the certificate length */
464 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
466 if (err
!= SEV_RET_INVALID_LEN
) {
467 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
468 r
, err
, fw_error_to_str(err
));
473 pdh_data
= g_new(guchar
, export
.pdh_cert_len
);
474 cert_chain_data
= g_new(guchar
, export
.cert_chain_len
);
475 export
.pdh_cert_address
= (unsigned long)pdh_data
;
476 export
.cert_chain_address
= (unsigned long)cert_chain_data
;
478 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
480 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
481 r
, err
, fw_error_to_str(err
));
486 *pdh_len
= export
.pdh_cert_len
;
487 *cert_chain
= cert_chain_data
;
488 *cert_chain_len
= export
.cert_chain_len
;
493 g_free(cert_chain_data
);
498 sev_get_capabilities(void)
500 SevCapability
*cap
= NULL
;
501 guchar
*pdh_data
= NULL
;
502 guchar
*cert_chain_data
= NULL
;
503 size_t pdh_len
= 0, cert_chain_len
= 0;
507 fd
= open(DEFAULT_SEV_DEVICE
, O_RDWR
);
509 error_report("%s: Failed to open %s '%s'", __func__
,
510 DEFAULT_SEV_DEVICE
, strerror(errno
));
514 if (sev_get_pdh_info(fd
, &pdh_data
, &pdh_len
,
515 &cert_chain_data
, &cert_chain_len
)) {
519 cap
= g_new0(SevCapability
, 1);
520 cap
->pdh
= g_base64_encode(pdh_data
, pdh_len
);
521 cap
->cert_chain
= g_base64_encode(cert_chain_data
, cert_chain_len
);
523 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
524 cap
->cbitpos
= ebx
& 0x3f;
527 * When SEV feature is enabled, we loose one bit in guest physical
530 cap
->reduced_phys_bits
= 1;
534 g_free(cert_chain_data
);
540 sev_read_file_base64(const char *filename
, guchar
**data
, gsize
*len
)
544 GError
*error
= NULL
;
546 if (!g_file_get_contents(filename
, &base64
, &sz
, &error
)) {
547 error_report("failed to read '%s' (%s)", filename
, error
->message
);
551 *data
= g_base64_decode(base64
, len
);
556 sev_launch_start(SEVState
*s
)
561 QSevGuestInfo
*sev
= s
->sev_info
;
562 struct kvm_sev_launch_start
*start
;
563 guchar
*session
= NULL
, *dh_cert
= NULL
;
565 start
= g_new0(struct kvm_sev_launch_start
, 1);
567 start
->handle
= object_property_get_int(OBJECT(sev
), "handle",
569 start
->policy
= object_property_get_int(OBJECT(sev
), "policy",
571 if (sev
->session_file
) {
572 if (sev_read_file_base64(sev
->session_file
, &session
, &sz
) < 0) {
575 start
->session_uaddr
= (unsigned long)session
;
576 start
->session_len
= sz
;
579 if (sev
->dh_cert_file
) {
580 if (sev_read_file_base64(sev
->dh_cert_file
, &dh_cert
, &sz
) < 0) {
583 start
->dh_uaddr
= (unsigned long)dh_cert
;
587 trace_kvm_sev_launch_start(start
->policy
, session
, dh_cert
);
588 rc
= sev_ioctl(s
->sev_fd
, KVM_SEV_LAUNCH_START
, start
, &fw_error
);
590 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
591 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
595 object_property_set_int(OBJECT(sev
), start
->handle
, "handle",
597 sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE
);
598 s
->handle
= start
->handle
;
599 s
->policy
= start
->policy
;
610 sev_launch_update_data(uint8_t *addr
, uint64_t len
)
613 struct kvm_sev_launch_update_data update
;
619 update
.uaddr
= (__u64
)(unsigned long)addr
;
621 trace_kvm_sev_launch_update_data(addr
, len
);
622 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_UPDATE_DATA
,
625 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
626 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
633 sev_launch_get_measure(Notifier
*notifier
, void *unused
)
637 SEVState
*s
= sev_state
;
638 struct kvm_sev_launch_measure
*measurement
;
640 if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE
)) {
644 measurement
= g_new0(struct kvm_sev_launch_measure
, 1);
646 /* query the measurement blob length */
647 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
648 measurement
, &error
);
649 if (!measurement
->len
) {
650 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
651 __func__
, ret
, error
, fw_error_to_str(errno
));
652 goto free_measurement
;
655 data
= g_new0(guchar
, measurement
->len
);
656 measurement
->uaddr
= (unsigned long)data
;
658 /* get the measurement blob */
659 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
660 measurement
, &error
);
662 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
663 __func__
, ret
, error
, fw_error_to_str(errno
));
667 sev_set_guest_state(SEV_STATE_LAUNCH_SECRET
);
669 /* encode the measurement value and emit the event */
670 s
->measurement
= g_base64_encode(data
, measurement
->len
);
671 trace_kvm_sev_launch_measurement(s
->measurement
);
680 sev_get_launch_measurement(void)
683 sev_state
->state
>= SEV_STATE_LAUNCH_SECRET
) {
684 return g_strdup(sev_state
->measurement
);
690 static Notifier sev_machine_done_notify
= {
691 .notify
= sev_launch_get_measure
,
695 sev_launch_finish(SEVState
*s
)
698 Error
*local_err
= NULL
;
700 trace_kvm_sev_launch_finish();
701 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_FINISH
, 0, &error
);
703 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
704 __func__
, ret
, error
, fw_error_to_str(error
));
708 sev_set_guest_state(SEV_STATE_RUNNING
);
710 /* add migration blocker */
711 error_setg(&sev_mig_blocker
,
712 "SEV: Migration is not implemented");
713 ret
= migrate_add_blocker(sev_mig_blocker
, &local_err
);
715 error_report_err(local_err
);
716 error_free(sev_mig_blocker
);
722 sev_vm_state_change(void *opaque
, int running
, RunState state
)
724 SEVState
*s
= opaque
;
727 if (!sev_check_state(SEV_STATE_RUNNING
)) {
728 sev_launch_finish(s
);
734 sev_guest_init(const char *id
)
740 uint32_t host_cbitpos
;
741 struct sev_user_data_status status
= {};
743 sev_state
= s
= g_new0(SEVState
, 1);
744 s
->sev_info
= lookup_sev_guest_info(id
);
746 error_report("%s: '%s' is not a valid '%s' object",
747 __func__
, id
, TYPE_QSEV_GUEST_INFO
);
751 s
->state
= SEV_STATE_UNINIT
;
753 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
754 host_cbitpos
= ebx
& 0x3f;
756 s
->cbitpos
= object_property_get_int(OBJECT(s
->sev_info
), "cbitpos", NULL
);
757 if (host_cbitpos
!= s
->cbitpos
) {
758 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
759 __func__
, host_cbitpos
, s
->cbitpos
);
763 s
->reduced_phys_bits
= object_property_get_int(OBJECT(s
->sev_info
),
764 "reduced-phys-bits", NULL
);
765 if (s
->reduced_phys_bits
< 1) {
766 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
767 " requested '%d'", __func__
, s
->reduced_phys_bits
);
771 s
->me_mask
= ~(1UL << s
->cbitpos
);
773 devname
= object_property_get_str(OBJECT(s
->sev_info
), "sev-device", NULL
);
774 s
->sev_fd
= open(devname
, O_RDWR
);
776 error_report("%s: Failed to open %s '%s'", __func__
,
777 devname
, strerror(errno
));
784 ret
= sev_platform_ioctl(s
->sev_fd
, SEV_PLATFORM_STATUS
, &status
,
787 error_report("%s: failed to get platform status ret=%d "
788 "fw_error='%d: %s'", __func__
, ret
, fw_error
,
789 fw_error_to_str(fw_error
));
792 s
->build_id
= status
.build
;
793 s
->api_major
= status
.api_major
;
794 s
->api_minor
= status
.api_minor
;
796 trace_kvm_sev_init();
797 ret
= sev_ioctl(s
->sev_fd
, KVM_SEV_INIT
, NULL
, &fw_error
);
799 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
800 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
804 ret
= sev_launch_start(s
);
806 error_report("%s: failed to create encryption context", __func__
);
810 ram_block_notifier_add(&sev_ram_notifier
);
811 qemu_add_machine_init_done_notifier(&sev_machine_done_notify
);
812 qemu_add_vm_change_state_handler(sev_vm_state_change
, s
);
822 sev_encrypt_data(void *handle
, uint8_t *ptr
, uint64_t len
)
826 /* if SEV is in update state then encrypt the data else do nothing */
827 if (sev_check_state(SEV_STATE_LAUNCH_UPDATE
)) {
828 return sev_launch_update_data(ptr
, len
);
835 sev_register_types(void)
837 type_register_static(&qsev_guest_info
);
840 type_init(sev_register_types
);