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"
29 #include "migration/blocker.h"
31 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
32 #define DEFAULT_SEV_DEVICE "/dev/sev"
34 static SEVState
*sev_state
;
35 static Error
*sev_mig_blocker
;
37 static const char *const sev_fw_errlist
[] = {
39 "Platform state is invalid",
40 "Guest state is invalid",
41 "Platform configuration is invalid",
43 "Platform is already owned",
44 "Certificate is invalid",
45 "Policy is not allowed",
46 "Guest is not active",
50 "Asid is already owned",
53 "DF_FLUSH is required",
54 "Guest handle is invalid",
59 "Feature not supported",
63 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
66 sev_ioctl(int fd
, int cmd
, void *data
, int *error
)
69 struct kvm_sev_cmd input
;
71 memset(&input
, 0x0, sizeof(input
));
75 input
.data
= (__u64
)(unsigned long)data
;
77 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_OP
, &input
);
87 sev_platform_ioctl(int fd
, int cmd
, void *data
, int *error
)
90 struct sev_issue_cmd arg
;
93 arg
.data
= (unsigned long)data
;
94 r
= ioctl(fd
, SEV_ISSUE_CMD
, &arg
);
103 fw_error_to_str(int code
)
105 if (code
< 0 || code
>= SEV_FW_MAX_ERROR
) {
106 return "unknown error";
109 return sev_fw_errlist
[code
];
113 sev_check_state(SevState state
)
116 return sev_state
->state
== state
? true : false;
120 sev_set_guest_state(SevState new_state
)
122 assert(new_state
< SEV_STATE__MAX
);
125 trace_kvm_sev_change_state(SevState_str(sev_state
->state
),
126 SevState_str(new_state
));
127 sev_state
->state
= new_state
;
131 sev_ram_block_added(RAMBlockNotifier
*n
, void *host
, size_t size
)
134 struct kvm_enc_region range
;
139 * The RAM device presents a memory region that should be treated
140 * as IO region and should not be pinned.
142 mr
= memory_region_from_host(host
, &offset
);
143 if (mr
&& memory_region_is_ram_device(mr
)) {
147 range
.addr
= (__u64
)(unsigned long)host
;
150 trace_kvm_memcrypt_register_region(host
, size
);
151 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_REG_REGION
, &range
);
153 error_report("%s: failed to register region (%p+%#zx) error '%s'",
154 __func__
, host
, size
, strerror(errno
));
160 sev_ram_block_removed(RAMBlockNotifier
*n
, void *host
, size_t size
)
163 struct kvm_enc_region range
;
165 range
.addr
= (__u64
)(unsigned long)host
;
168 trace_kvm_memcrypt_unregister_region(host
, size
);
169 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_UNREG_REGION
, &range
);
171 error_report("%s: failed to unregister region (%p+%#zx)",
172 __func__
, host
, size
);
176 static struct RAMBlockNotifier sev_ram_notifier
= {
177 .ram_block_added
= sev_ram_block_added
,
178 .ram_block_removed
= sev_ram_block_removed
,
182 qsev_guest_finalize(Object
*obj
)
187 qsev_guest_get_session_file(Object
*obj
, Error
**errp
)
189 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
191 return s
->session_file
? g_strdup(s
->session_file
) : NULL
;
195 qsev_guest_set_session_file(Object
*obj
, const char *value
, Error
**errp
)
197 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
199 s
->session_file
= g_strdup(value
);
203 qsev_guest_get_dh_cert_file(Object
*obj
, Error
**errp
)
205 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
207 return g_strdup(s
->dh_cert_file
);
211 qsev_guest_set_dh_cert_file(Object
*obj
, const char *value
, Error
**errp
)
213 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
215 s
->dh_cert_file
= g_strdup(value
);
219 qsev_guest_get_sev_device(Object
*obj
, Error
**errp
)
221 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
223 return g_strdup(sev
->sev_device
);
227 qsev_guest_set_sev_device(Object
*obj
, const char *value
, Error
**errp
)
229 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
231 sev
->sev_device
= g_strdup(value
);
235 qsev_guest_class_init(ObjectClass
*oc
, void *data
)
237 object_class_property_add_str(oc
, "sev-device",
238 qsev_guest_get_sev_device
,
239 qsev_guest_set_sev_device
,
241 object_class_property_set_description(oc
, "sev-device",
242 "SEV device to use", NULL
);
243 object_class_property_add_str(oc
, "dh-cert-file",
244 qsev_guest_get_dh_cert_file
,
245 qsev_guest_set_dh_cert_file
,
247 object_class_property_set_description(oc
, "dh-cert-file",
248 "guest owners DH certificate (encoded with base64)", NULL
);
249 object_class_property_add_str(oc
, "session-file",
250 qsev_guest_get_session_file
,
251 qsev_guest_set_session_file
,
253 object_class_property_set_description(oc
, "session-file",
254 "guest owners session parameters (encoded with base64)", NULL
);
258 qsev_guest_set_handle(Object
*obj
, Visitor
*v
, const char *name
,
259 void *opaque
, Error
**errp
)
261 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
264 visit_type_uint32(v
, name
, &value
, errp
);
269 qsev_guest_set_policy(Object
*obj
, Visitor
*v
, const char *name
,
270 void *opaque
, Error
**errp
)
272 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
275 visit_type_uint32(v
, name
, &value
, errp
);
280 qsev_guest_set_cbitpos(Object
*obj
, Visitor
*v
, const char *name
,
281 void *opaque
, Error
**errp
)
283 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
286 visit_type_uint32(v
, name
, &value
, errp
);
287 sev
->cbitpos
= value
;
291 qsev_guest_set_reduced_phys_bits(Object
*obj
, Visitor
*v
, const char *name
,
292 void *opaque
, Error
**errp
)
294 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
297 visit_type_uint32(v
, name
, &value
, errp
);
298 sev
->reduced_phys_bits
= value
;
302 qsev_guest_get_policy(Object
*obj
, Visitor
*v
, const char *name
,
303 void *opaque
, Error
**errp
)
306 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
309 visit_type_uint32(v
, name
, &value
, errp
);
313 qsev_guest_get_handle(Object
*obj
, Visitor
*v
, const char *name
,
314 void *opaque
, Error
**errp
)
317 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
320 visit_type_uint32(v
, name
, &value
, errp
);
324 qsev_guest_get_cbitpos(Object
*obj
, Visitor
*v
, const char *name
,
325 void *opaque
, Error
**errp
)
328 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
330 value
= sev
->cbitpos
;
331 visit_type_uint32(v
, name
, &value
, errp
);
335 qsev_guest_get_reduced_phys_bits(Object
*obj
, Visitor
*v
, const char *name
,
336 void *opaque
, Error
**errp
)
339 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
341 value
= sev
->reduced_phys_bits
;
342 visit_type_uint32(v
, name
, &value
, errp
);
346 qsev_guest_init(Object
*obj
)
348 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
350 sev
->sev_device
= g_strdup(DEFAULT_SEV_DEVICE
);
351 sev
->policy
= DEFAULT_GUEST_POLICY
;
352 object_property_add(obj
, "policy", "uint32", qsev_guest_get_policy
,
353 qsev_guest_set_policy
, NULL
, NULL
, NULL
);
354 object_property_add(obj
, "handle", "uint32", qsev_guest_get_handle
,
355 qsev_guest_set_handle
, NULL
, NULL
, NULL
);
356 object_property_add(obj
, "cbitpos", "uint32", qsev_guest_get_cbitpos
,
357 qsev_guest_set_cbitpos
, NULL
, NULL
, NULL
);
358 object_property_add(obj
, "reduced-phys-bits", "uint32",
359 qsev_guest_get_reduced_phys_bits
,
360 qsev_guest_set_reduced_phys_bits
, NULL
, NULL
, NULL
);
364 static const TypeInfo qsev_guest_info
= {
365 .parent
= TYPE_OBJECT
,
366 .name
= TYPE_QSEV_GUEST_INFO
,
367 .instance_size
= sizeof(QSevGuestInfo
),
368 .instance_finalize
= qsev_guest_finalize
,
369 .class_size
= sizeof(QSevGuestInfoClass
),
370 .class_init
= qsev_guest_class_init
,
371 .instance_init
= qsev_guest_init
,
372 .interfaces
= (InterfaceInfo
[]) {
373 { TYPE_USER_CREATABLE
},
378 static QSevGuestInfo
*
379 lookup_sev_guest_info(const char *id
)
384 obj
= object_resolve_path_component(object_get_objects_root(), id
);
389 info
= (QSevGuestInfo
*)
390 object_dynamic_cast(obj
, TYPE_QSEV_GUEST_INFO
);
401 return sev_state
? true : false;
405 sev_get_me_mask(void)
407 return sev_state
? sev_state
->me_mask
: ~0;
411 sev_get_cbit_position(void)
413 return sev_state
? sev_state
->cbitpos
: 0;
417 sev_get_reduced_phys_bits(void)
419 return sev_state
? sev_state
->reduced_phys_bits
: 0;
427 info
= g_new0(SevInfo
, 1);
428 info
->enabled
= sev_state
? true : false;
431 info
->api_major
= sev_state
->api_major
;
432 info
->api_minor
= sev_state
->api_minor
;
433 info
->build_id
= sev_state
->build_id
;
434 info
->policy
= sev_state
->policy
;
435 info
->state
= sev_state
->state
;
436 info
->handle
= sev_state
->handle
;
443 sev_get_pdh_info(int fd
, guchar
**pdh
, size_t *pdh_len
, guchar
**cert_chain
,
444 size_t *cert_chain_len
)
446 guchar
*pdh_data
= NULL
;
447 guchar
*cert_chain_data
= NULL
;
448 struct sev_user_data_pdh_cert_export export
= {};
451 /* query the certificate length */
452 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
454 if (err
!= SEV_RET_INVALID_LEN
) {
455 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
456 r
, err
, fw_error_to_str(err
));
461 pdh_data
= g_new(guchar
, export
.pdh_cert_len
);
462 cert_chain_data
= g_new(guchar
, export
.cert_chain_len
);
463 export
.pdh_cert_address
= (unsigned long)pdh_data
;
464 export
.cert_chain_address
= (unsigned long)cert_chain_data
;
466 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
468 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
469 r
, err
, fw_error_to_str(err
));
474 *pdh_len
= export
.pdh_cert_len
;
475 *cert_chain
= cert_chain_data
;
476 *cert_chain_len
= export
.cert_chain_len
;
481 g_free(cert_chain_data
);
486 sev_get_capabilities(void)
488 SevCapability
*cap
= NULL
;
489 guchar
*pdh_data
= NULL
;
490 guchar
*cert_chain_data
= NULL
;
491 size_t pdh_len
= 0, cert_chain_len
= 0;
495 fd
= open(DEFAULT_SEV_DEVICE
, O_RDWR
);
497 error_report("%s: Failed to open %s '%s'", __func__
,
498 DEFAULT_SEV_DEVICE
, strerror(errno
));
502 if (sev_get_pdh_info(fd
, &pdh_data
, &pdh_len
,
503 &cert_chain_data
, &cert_chain_len
)) {
507 cap
= g_new0(SevCapability
, 1);
508 cap
->pdh
= g_base64_encode(pdh_data
, pdh_len
);
509 cap
->cert_chain
= g_base64_encode(cert_chain_data
, cert_chain_len
);
511 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
512 cap
->cbitpos
= ebx
& 0x3f;
515 * When SEV feature is enabled, we loose one bit in guest physical
518 cap
->reduced_phys_bits
= 1;
522 g_free(cert_chain_data
);
528 sev_read_file_base64(const char *filename
, guchar
**data
, gsize
*len
)
532 GError
*error
= NULL
;
534 if (!g_file_get_contents(filename
, &base64
, &sz
, &error
)) {
535 error_report("failed to read '%s' (%s)", filename
, error
->message
);
539 *data
= g_base64_decode(base64
, len
);
544 sev_launch_start(SEVState
*s
)
549 QSevGuestInfo
*sev
= s
->sev_info
;
550 struct kvm_sev_launch_start
*start
;
551 guchar
*session
= NULL
, *dh_cert
= NULL
;
553 start
= g_new0(struct kvm_sev_launch_start
, 1);
555 start
->handle
= object_property_get_int(OBJECT(sev
), "handle",
557 start
->policy
= object_property_get_int(OBJECT(sev
), "policy",
559 if (sev
->session_file
) {
560 if (sev_read_file_base64(sev
->session_file
, &session
, &sz
) < 0) {
563 start
->session_uaddr
= (unsigned long)session
;
564 start
->session_len
= sz
;
567 if (sev
->dh_cert_file
) {
568 if (sev_read_file_base64(sev
->dh_cert_file
, &dh_cert
, &sz
) < 0) {
571 start
->dh_uaddr
= (unsigned long)dh_cert
;
575 trace_kvm_sev_launch_start(start
->policy
, session
, dh_cert
);
576 rc
= sev_ioctl(s
->sev_fd
, KVM_SEV_LAUNCH_START
, start
, &fw_error
);
578 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
579 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
583 object_property_set_int(OBJECT(sev
), start
->handle
, "handle",
585 sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE
);
586 s
->handle
= start
->handle
;
587 s
->policy
= start
->policy
;
598 sev_launch_update_data(uint8_t *addr
, uint64_t len
)
601 struct kvm_sev_launch_update_data update
;
607 update
.uaddr
= (__u64
)(unsigned long)addr
;
609 trace_kvm_sev_launch_update_data(addr
, len
);
610 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_UPDATE_DATA
,
613 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
614 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
621 sev_launch_get_measure(Notifier
*notifier
, void *unused
)
625 SEVState
*s
= sev_state
;
626 struct kvm_sev_launch_measure
*measurement
;
628 if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE
)) {
632 measurement
= g_new0(struct kvm_sev_launch_measure
, 1);
634 /* query the measurement blob length */
635 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
636 measurement
, &error
);
637 if (!measurement
->len
) {
638 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
639 __func__
, ret
, error
, fw_error_to_str(errno
));
640 goto free_measurement
;
643 data
= g_new0(guchar
, measurement
->len
);
644 measurement
->uaddr
= (unsigned long)data
;
646 /* get the measurement blob */
647 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
648 measurement
, &error
);
650 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
651 __func__
, ret
, error
, fw_error_to_str(errno
));
655 sev_set_guest_state(SEV_STATE_LAUNCH_SECRET
);
657 /* encode the measurement value and emit the event */
658 s
->measurement
= g_base64_encode(data
, measurement
->len
);
659 trace_kvm_sev_launch_measurement(s
->measurement
);
668 sev_get_launch_measurement(void)
671 sev_state
->state
>= SEV_STATE_LAUNCH_SECRET
) {
672 return g_strdup(sev_state
->measurement
);
678 static Notifier sev_machine_done_notify
= {
679 .notify
= sev_launch_get_measure
,
683 sev_launch_finish(SEVState
*s
)
686 Error
*local_err
= NULL
;
688 trace_kvm_sev_launch_finish();
689 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_FINISH
, 0, &error
);
691 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
692 __func__
, ret
, error
, fw_error_to_str(error
));
696 sev_set_guest_state(SEV_STATE_RUNNING
);
698 /* add migration blocker */
699 error_setg(&sev_mig_blocker
,
700 "SEV: Migration is not implemented");
701 ret
= migrate_add_blocker(sev_mig_blocker
, &local_err
);
703 error_report_err(local_err
);
704 error_free(sev_mig_blocker
);
710 sev_vm_state_change(void *opaque
, int running
, RunState state
)
712 SEVState
*s
= opaque
;
715 if (!sev_check_state(SEV_STATE_RUNNING
)) {
716 sev_launch_finish(s
);
722 sev_guest_init(const char *id
)
728 uint32_t host_cbitpos
;
729 struct sev_user_data_status status
= {};
731 sev_state
= s
= g_new0(SEVState
, 1);
732 s
->sev_info
= lookup_sev_guest_info(id
);
734 error_report("%s: '%s' is not a valid '%s' object",
735 __func__
, id
, TYPE_QSEV_GUEST_INFO
);
739 s
->state
= SEV_STATE_UNINIT
;
741 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
742 host_cbitpos
= ebx
& 0x3f;
744 s
->cbitpos
= object_property_get_int(OBJECT(s
->sev_info
), "cbitpos", NULL
);
745 if (host_cbitpos
!= s
->cbitpos
) {
746 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
747 __func__
, host_cbitpos
, s
->cbitpos
);
751 s
->reduced_phys_bits
= object_property_get_int(OBJECT(s
->sev_info
),
752 "reduced-phys-bits", NULL
);
753 if (s
->reduced_phys_bits
< 1) {
754 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
755 "' requested '%d'", __func__
, s
->reduced_phys_bits
);
759 s
->me_mask
= ~(1UL << s
->cbitpos
);
761 devname
= object_property_get_str(OBJECT(s
->sev_info
), "sev-device", NULL
);
762 s
->sev_fd
= open(devname
, O_RDWR
);
764 error_report("%s: Failed to open %s '%s'", __func__
,
765 devname
, strerror(errno
));
772 ret
= sev_platform_ioctl(s
->sev_fd
, SEV_PLATFORM_STATUS
, &status
,
775 error_report("%s: failed to get platform status ret=%d"
776 "fw_error='%d: %s'", __func__
, ret
, fw_error
,
777 fw_error_to_str(fw_error
));
780 s
->build_id
= status
.build
;
781 s
->api_major
= status
.api_major
;
782 s
->api_minor
= status
.api_minor
;
784 trace_kvm_sev_init();
785 ret
= sev_ioctl(s
->sev_fd
, KVM_SEV_INIT
, NULL
, &fw_error
);
787 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
788 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
792 ret
= sev_launch_start(s
);
794 error_report("%s: failed to create encryption context", __func__
);
798 ram_block_notifier_add(&sev_ram_notifier
);
799 qemu_add_machine_init_done_notifier(&sev_machine_done_notify
);
800 qemu_add_vm_change_state_handler(sev_vm_state_change
, s
);
810 sev_encrypt_data(void *handle
, uint8_t *ptr
, uint64_t len
)
814 /* if SEV is in update state then encrypt the data else do nothing */
815 if (sev_check_state(SEV_STATE_LAUNCH_UPDATE
)) {
816 return sev_launch_update_data(ptr
, len
);
823 sev_register_types(void)
825 type_register_static(&qsev_guest_info
);
828 type_init(sev_register_types
);