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 "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
;
138 * The RAM device presents a memory region that should be treated
139 * as IO region and should not be pinned.
141 mr
= memory_region_from_host(host
, &offset
);
142 if (mr
&& memory_region_is_ram_device(mr
)) {
146 range
.addr
= (__u64
)(unsigned long)host
;
149 trace_kvm_memcrypt_register_region(host
, size
);
150 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_REG_REGION
, &range
);
152 error_report("%s: failed to register region (%p+%#zx) error '%s'",
153 __func__
, host
, size
, strerror(errno
));
159 sev_ram_block_removed(RAMBlockNotifier
*n
, void *host
, size_t size
)
162 struct kvm_enc_region range
;
164 range
.addr
= (__u64
)(unsigned long)host
;
167 trace_kvm_memcrypt_unregister_region(host
, size
);
168 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_UNREG_REGION
, &range
);
170 error_report("%s: failed to unregister region (%p+%#zx)",
171 __func__
, host
, size
);
175 static struct RAMBlockNotifier sev_ram_notifier
= {
176 .ram_block_added
= sev_ram_block_added
,
177 .ram_block_removed
= sev_ram_block_removed
,
181 qsev_guest_finalize(Object
*obj
)
186 qsev_guest_get_session_file(Object
*obj
, Error
**errp
)
188 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
190 return s
->session_file
? g_strdup(s
->session_file
) : NULL
;
194 qsev_guest_set_session_file(Object
*obj
, const char *value
, Error
**errp
)
196 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
198 s
->session_file
= g_strdup(value
);
202 qsev_guest_get_dh_cert_file(Object
*obj
, Error
**errp
)
204 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
206 return g_strdup(s
->dh_cert_file
);
210 qsev_guest_set_dh_cert_file(Object
*obj
, const char *value
, Error
**errp
)
212 QSevGuestInfo
*s
= QSEV_GUEST_INFO(obj
);
214 s
->dh_cert_file
= g_strdup(value
);
218 qsev_guest_get_sev_device(Object
*obj
, Error
**errp
)
220 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
222 return g_strdup(sev
->sev_device
);
226 qsev_guest_set_sev_device(Object
*obj
, const char *value
, Error
**errp
)
228 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
230 sev
->sev_device
= g_strdup(value
);
234 qsev_guest_class_init(ObjectClass
*oc
, void *data
)
236 object_class_property_add_str(oc
, "sev-device",
237 qsev_guest_get_sev_device
,
238 qsev_guest_set_sev_device
,
240 object_class_property_set_description(oc
, "sev-device",
241 "SEV device to use", NULL
);
242 object_class_property_add_str(oc
, "dh-cert-file",
243 qsev_guest_get_dh_cert_file
,
244 qsev_guest_set_dh_cert_file
,
246 object_class_property_set_description(oc
, "dh-cert-file",
247 "guest owners DH certificate (encoded with base64)", NULL
);
248 object_class_property_add_str(oc
, "session-file",
249 qsev_guest_get_session_file
,
250 qsev_guest_set_session_file
,
252 object_class_property_set_description(oc
, "session-file",
253 "guest owners session parameters (encoded with base64)", NULL
);
257 qsev_guest_set_handle(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_policy(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
);
279 qsev_guest_set_cbitpos(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
->cbitpos
= value
;
290 qsev_guest_set_reduced_phys_bits(Object
*obj
, Visitor
*v
, const char *name
,
291 void *opaque
, Error
**errp
)
293 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
296 visit_type_uint32(v
, name
, &value
, errp
);
297 sev
->reduced_phys_bits
= value
;
301 qsev_guest_get_policy(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_handle(Object
*obj
, Visitor
*v
, const char *name
,
313 void *opaque
, Error
**errp
)
316 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
319 visit_type_uint32(v
, name
, &value
, errp
);
323 qsev_guest_get_cbitpos(Object
*obj
, Visitor
*v
, const char *name
,
324 void *opaque
, Error
**errp
)
327 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
329 value
= sev
->cbitpos
;
330 visit_type_uint32(v
, name
, &value
, errp
);
334 qsev_guest_get_reduced_phys_bits(Object
*obj
, Visitor
*v
, const char *name
,
335 void *opaque
, Error
**errp
)
338 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
340 value
= sev
->reduced_phys_bits
;
341 visit_type_uint32(v
, name
, &value
, errp
);
345 qsev_guest_init(Object
*obj
)
347 QSevGuestInfo
*sev
= QSEV_GUEST_INFO(obj
);
349 sev
->sev_device
= g_strdup(DEFAULT_SEV_DEVICE
);
350 sev
->policy
= DEFAULT_GUEST_POLICY
;
351 object_property_add(obj
, "policy", "uint32", qsev_guest_get_policy
,
352 qsev_guest_set_policy
, NULL
, NULL
, NULL
);
353 object_property_add(obj
, "handle", "uint32", qsev_guest_get_handle
,
354 qsev_guest_set_handle
, NULL
, NULL
, NULL
);
355 object_property_add(obj
, "cbitpos", "uint32", qsev_guest_get_cbitpos
,
356 qsev_guest_set_cbitpos
, NULL
, NULL
, NULL
);
357 object_property_add(obj
, "reduced-phys-bits", "uint32",
358 qsev_guest_get_reduced_phys_bits
,
359 qsev_guest_set_reduced_phys_bits
, NULL
, NULL
, NULL
);
363 static const TypeInfo qsev_guest_info
= {
364 .parent
= TYPE_OBJECT
,
365 .name
= TYPE_QSEV_GUEST_INFO
,
366 .instance_size
= sizeof(QSevGuestInfo
),
367 .instance_finalize
= qsev_guest_finalize
,
368 .class_size
= sizeof(QSevGuestInfoClass
),
369 .class_init
= qsev_guest_class_init
,
370 .instance_init
= qsev_guest_init
,
371 .interfaces
= (InterfaceInfo
[]) {
372 { TYPE_USER_CREATABLE
},
377 static QSevGuestInfo
*
378 lookup_sev_guest_info(const char *id
)
383 obj
= object_resolve_path_component(object_get_objects_root(), id
);
388 info
= (QSevGuestInfo
*)
389 object_dynamic_cast(obj
, TYPE_QSEV_GUEST_INFO
);
400 return sev_state
? true : false;
404 sev_get_me_mask(void)
406 return sev_state
? sev_state
->me_mask
: ~0;
410 sev_get_cbit_position(void)
412 return sev_state
? sev_state
->cbitpos
: 0;
416 sev_get_reduced_phys_bits(void)
418 return sev_state
? sev_state
->reduced_phys_bits
: 0;
426 info
= g_new0(SevInfo
, 1);
427 info
->enabled
= sev_state
? true : false;
430 info
->api_major
= sev_state
->api_major
;
431 info
->api_minor
= sev_state
->api_minor
;
432 info
->build_id
= sev_state
->build_id
;
433 info
->policy
= sev_state
->policy
;
434 info
->state
= sev_state
->state
;
435 info
->handle
= sev_state
->handle
;
442 sev_get_pdh_info(int fd
, guchar
**pdh
, size_t *pdh_len
, guchar
**cert_chain
,
443 size_t *cert_chain_len
)
445 guchar
*pdh_data
= NULL
;
446 guchar
*cert_chain_data
= NULL
;
447 struct sev_user_data_pdh_cert_export export
= {};
450 /* query the certificate length */
451 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
453 if (err
!= SEV_RET_INVALID_LEN
) {
454 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
455 r
, err
, fw_error_to_str(err
));
460 pdh_data
= g_new(guchar
, export
.pdh_cert_len
);
461 cert_chain_data
= g_new(guchar
, export
.cert_chain_len
);
462 export
.pdh_cert_address
= (unsigned long)pdh_data
;
463 export
.cert_chain_address
= (unsigned long)cert_chain_data
;
465 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
467 error_report("failed to export PDH cert ret=%d fw_err=%d (%s)",
468 r
, err
, fw_error_to_str(err
));
473 *pdh_len
= export
.pdh_cert_len
;
474 *cert_chain
= cert_chain_data
;
475 *cert_chain_len
= export
.cert_chain_len
;
480 g_free(cert_chain_data
);
485 sev_get_capabilities(void)
487 SevCapability
*cap
= NULL
;
488 guchar
*pdh_data
= NULL
;
489 guchar
*cert_chain_data
= NULL
;
490 size_t pdh_len
= 0, cert_chain_len
= 0;
494 fd
= open(DEFAULT_SEV_DEVICE
, O_RDWR
);
496 error_report("%s: Failed to open %s '%s'", __func__
,
497 DEFAULT_SEV_DEVICE
, strerror(errno
));
501 if (sev_get_pdh_info(fd
, &pdh_data
, &pdh_len
,
502 &cert_chain_data
, &cert_chain_len
)) {
506 cap
= g_new0(SevCapability
, 1);
507 cap
->pdh
= g_base64_encode(pdh_data
, pdh_len
);
508 cap
->cert_chain
= g_base64_encode(cert_chain_data
, cert_chain_len
);
510 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
511 cap
->cbitpos
= ebx
& 0x3f;
514 * When SEV feature is enabled, we loose one bit in guest physical
517 cap
->reduced_phys_bits
= 1;
521 g_free(cert_chain_data
);
527 sev_read_file_base64(const char *filename
, guchar
**data
, gsize
*len
)
531 GError
*error
= NULL
;
533 if (!g_file_get_contents(filename
, &base64
, &sz
, &error
)) {
534 error_report("failed to read '%s' (%s)", filename
, error
->message
);
538 *data
= g_base64_decode(base64
, len
);
543 sev_launch_start(SEVState
*s
)
548 QSevGuestInfo
*sev
= s
->sev_info
;
549 struct kvm_sev_launch_start
*start
;
550 guchar
*session
= NULL
, *dh_cert
= NULL
;
552 start
= g_new0(struct kvm_sev_launch_start
, 1);
554 start
->handle
= object_property_get_int(OBJECT(sev
), "handle",
556 start
->policy
= object_property_get_int(OBJECT(sev
), "policy",
558 if (sev
->session_file
) {
559 if (sev_read_file_base64(sev
->session_file
, &session
, &sz
) < 0) {
562 start
->session_uaddr
= (unsigned long)session
;
563 start
->session_len
= sz
;
566 if (sev
->dh_cert_file
) {
567 if (sev_read_file_base64(sev
->dh_cert_file
, &dh_cert
, &sz
) < 0) {
570 start
->dh_uaddr
= (unsigned long)dh_cert
;
574 trace_kvm_sev_launch_start(start
->policy
, session
, dh_cert
);
575 rc
= sev_ioctl(s
->sev_fd
, KVM_SEV_LAUNCH_START
, start
, &fw_error
);
577 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
578 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
582 object_property_set_int(OBJECT(sev
), start
->handle
, "handle",
584 sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE
);
585 s
->handle
= start
->handle
;
586 s
->policy
= start
->policy
;
597 sev_launch_update_data(uint8_t *addr
, uint64_t len
)
600 struct kvm_sev_launch_update_data update
;
606 update
.uaddr
= (__u64
)(unsigned long)addr
;
608 trace_kvm_sev_launch_update_data(addr
, len
);
609 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_UPDATE_DATA
,
612 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
613 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
620 sev_launch_get_measure(Notifier
*notifier
, void *unused
)
624 SEVState
*s
= sev_state
;
625 struct kvm_sev_launch_measure
*measurement
;
627 if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE
)) {
631 measurement
= g_new0(struct kvm_sev_launch_measure
, 1);
633 /* query the measurement blob length */
634 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
635 measurement
, &error
);
636 if (!measurement
->len
) {
637 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
638 __func__
, ret
, error
, fw_error_to_str(errno
));
639 goto free_measurement
;
642 data
= g_new0(guchar
, measurement
->len
);
643 measurement
->uaddr
= (unsigned long)data
;
645 /* get the measurement blob */
646 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
647 measurement
, &error
);
649 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
650 __func__
, ret
, error
, fw_error_to_str(errno
));
654 sev_set_guest_state(SEV_STATE_LAUNCH_SECRET
);
656 /* encode the measurement value and emit the event */
657 s
->measurement
= g_base64_encode(data
, measurement
->len
);
658 trace_kvm_sev_launch_measurement(s
->measurement
);
667 sev_get_launch_measurement(void)
670 sev_state
->state
>= SEV_STATE_LAUNCH_SECRET
) {
671 return g_strdup(sev_state
->measurement
);
677 static Notifier sev_machine_done_notify
= {
678 .notify
= sev_launch_get_measure
,
682 sev_launch_finish(SEVState
*s
)
685 Error
*local_err
= NULL
;
687 trace_kvm_sev_launch_finish();
688 ret
= sev_ioctl(sev_state
->sev_fd
, KVM_SEV_LAUNCH_FINISH
, 0, &error
);
690 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
691 __func__
, ret
, error
, fw_error_to_str(error
));
695 sev_set_guest_state(SEV_STATE_RUNNING
);
697 /* add migration blocker */
698 error_setg(&sev_mig_blocker
,
699 "SEV: Migration is not implemented");
700 ret
= migrate_add_blocker(sev_mig_blocker
, &local_err
);
702 error_report_err(local_err
);
703 error_free(sev_mig_blocker
);
709 sev_vm_state_change(void *opaque
, int running
, RunState state
)
711 SEVState
*s
= opaque
;
714 if (!sev_check_state(SEV_STATE_RUNNING
)) {
715 sev_launch_finish(s
);
721 sev_guest_init(const char *id
)
727 uint32_t host_cbitpos
;
728 struct sev_user_data_status status
= {};
730 sev_state
= s
= g_new0(SEVState
, 1);
731 s
->sev_info
= lookup_sev_guest_info(id
);
733 error_report("%s: '%s' is not a valid '%s' object",
734 __func__
, id
, TYPE_QSEV_GUEST_INFO
);
738 s
->state
= SEV_STATE_UNINIT
;
740 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
741 host_cbitpos
= ebx
& 0x3f;
743 s
->cbitpos
= object_property_get_int(OBJECT(s
->sev_info
), "cbitpos", NULL
);
744 if (host_cbitpos
!= s
->cbitpos
) {
745 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
746 __func__
, host_cbitpos
, s
->cbitpos
);
750 s
->reduced_phys_bits
= object_property_get_int(OBJECT(s
->sev_info
),
751 "reduced-phys-bits", NULL
);
752 if (s
->reduced_phys_bits
< 1) {
753 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
754 "' requested '%d'", __func__
, s
->reduced_phys_bits
);
758 s
->me_mask
= ~(1UL << s
->cbitpos
);
760 devname
= object_property_get_str(OBJECT(s
->sev_info
), "sev-device", NULL
);
761 s
->sev_fd
= open(devname
, O_RDWR
);
763 error_report("%s: Failed to open %s '%s'", __func__
,
764 devname
, strerror(errno
));
771 ret
= sev_platform_ioctl(s
->sev_fd
, SEV_PLATFORM_STATUS
, &status
,
774 error_report("%s: failed to get platform status ret=%d"
775 "fw_error='%d: %s'", __func__
, ret
, fw_error
,
776 fw_error_to_str(fw_error
));
779 s
->build_id
= status
.build
;
780 s
->api_major
= status
.api_major
;
781 s
->api_minor
= status
.api_minor
;
783 trace_kvm_sev_init();
784 ret
= sev_ioctl(s
->sev_fd
, KVM_SEV_INIT
, NULL
, &fw_error
);
786 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
787 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
791 ret
= sev_launch_start(s
);
793 error_report("%s: failed to create encryption context", __func__
);
797 ram_block_notifier_add(&sev_ram_notifier
);
798 qemu_add_machine_init_done_notifier(&sev_machine_done_notify
);
799 qemu_add_vm_change_state_handler(sev_vm_state_change
, s
);
809 sev_encrypt_data(void *handle
, uint8_t *ptr
, uint64_t len
)
813 /* if SEV is in update state then encrypt the data else do nothing */
814 if (sev_check_state(SEV_STATE_LAUNCH_UPDATE
)) {
815 return sev_launch_update_data(ptr
, len
);
822 sev_register_types(void)
824 type_register_static(&qsev_guest_info
);
827 type_init(sev_register_types
);