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"
32 #include "exec/address-spaces.h"
33 #include "monitor/monitor.h"
34 #include "exec/confidential-guest-support.h"
36 #define TYPE_SEV_GUEST "sev-guest"
37 OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState
, SEV_GUEST
)
43 * The SevGuestState object is used for creating and managing a SEV
47 * -object sev-guest,id=sev0 \
48 * -machine ...,memory-encryption=sev0
50 struct SevGuestState
{
51 ConfidentialGuestSupport parent_obj
;
53 /* configuration parameters */
59 uint32_t reduced_phys_bits
;
72 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
73 #define DEFAULT_SEV_DEVICE "/dev/sev"
75 static SevGuestState
*sev_guest
;
76 static Error
*sev_mig_blocker
;
78 static const char *const sev_fw_errlist
[] = {
80 "Platform state is invalid",
81 "Guest state is invalid",
82 "Platform configuration is invalid",
84 "Platform is already owned",
85 "Certificate is invalid",
86 "Policy is not allowed",
87 "Guest is not active",
91 "Asid is already owned",
94 "DF_FLUSH is required",
95 "Guest handle is invalid",
100 "Feature not supported",
104 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
107 sev_ioctl(int fd
, int cmd
, void *data
, int *error
)
110 struct kvm_sev_cmd input
;
112 memset(&input
, 0x0, sizeof(input
));
116 input
.data
= (__u64
)(unsigned long)data
;
118 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_OP
, &input
);
121 *error
= input
.error
;
128 sev_platform_ioctl(int fd
, int cmd
, void *data
, int *error
)
131 struct sev_issue_cmd arg
;
134 arg
.data
= (unsigned long)data
;
135 r
= ioctl(fd
, SEV_ISSUE_CMD
, &arg
);
144 fw_error_to_str(int code
)
146 if (code
< 0 || code
>= SEV_FW_MAX_ERROR
) {
147 return "unknown error";
150 return sev_fw_errlist
[code
];
154 sev_check_state(const SevGuestState
*sev
, SevState state
)
157 return sev
->state
== state
? true : false;
161 sev_set_guest_state(SevGuestState
*sev
, SevState new_state
)
163 assert(new_state
< SEV_STATE__MAX
);
166 trace_kvm_sev_change_state(SevState_str(sev
->state
),
167 SevState_str(new_state
));
168 sev
->state
= new_state
;
172 sev_ram_block_added(RAMBlockNotifier
*n
, void *host
, size_t size
)
175 struct kvm_enc_region range
;
180 * The RAM device presents a memory region that should be treated
181 * as IO region and should not be pinned.
183 mr
= memory_region_from_host(host
, &offset
);
184 if (mr
&& memory_region_is_ram_device(mr
)) {
188 range
.addr
= (__u64
)(unsigned long)host
;
191 trace_kvm_memcrypt_register_region(host
, size
);
192 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_REG_REGION
, &range
);
194 error_report("%s: failed to register region (%p+%#zx) error '%s'",
195 __func__
, host
, size
, strerror(errno
));
201 sev_ram_block_removed(RAMBlockNotifier
*n
, void *host
, size_t size
)
204 struct kvm_enc_region range
;
209 * The RAM device presents a memory region that should be treated
210 * as IO region and should not have been pinned.
212 mr
= memory_region_from_host(host
, &offset
);
213 if (mr
&& memory_region_is_ram_device(mr
)) {
217 range
.addr
= (__u64
)(unsigned long)host
;
220 trace_kvm_memcrypt_unregister_region(host
, size
);
221 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_UNREG_REGION
, &range
);
223 error_report("%s: failed to unregister region (%p+%#zx)",
224 __func__
, host
, size
);
228 static struct RAMBlockNotifier sev_ram_notifier
= {
229 .ram_block_added
= sev_ram_block_added
,
230 .ram_block_removed
= sev_ram_block_removed
,
234 sev_guest_finalize(Object
*obj
)
239 sev_guest_get_session_file(Object
*obj
, Error
**errp
)
241 SevGuestState
*s
= SEV_GUEST(obj
);
243 return s
->session_file
? g_strdup(s
->session_file
) : NULL
;
247 sev_guest_set_session_file(Object
*obj
, const char *value
, Error
**errp
)
249 SevGuestState
*s
= SEV_GUEST(obj
);
251 s
->session_file
= g_strdup(value
);
255 sev_guest_get_dh_cert_file(Object
*obj
, Error
**errp
)
257 SevGuestState
*s
= SEV_GUEST(obj
);
259 return g_strdup(s
->dh_cert_file
);
263 sev_guest_set_dh_cert_file(Object
*obj
, const char *value
, Error
**errp
)
265 SevGuestState
*s
= SEV_GUEST(obj
);
267 s
->dh_cert_file
= g_strdup(value
);
271 sev_guest_get_sev_device(Object
*obj
, Error
**errp
)
273 SevGuestState
*sev
= SEV_GUEST(obj
);
275 return g_strdup(sev
->sev_device
);
279 sev_guest_set_sev_device(Object
*obj
, const char *value
, Error
**errp
)
281 SevGuestState
*sev
= SEV_GUEST(obj
);
283 sev
->sev_device
= g_strdup(value
);
287 sev_guest_class_init(ObjectClass
*oc
, void *data
)
289 object_class_property_add_str(oc
, "sev-device",
290 sev_guest_get_sev_device
,
291 sev_guest_set_sev_device
);
292 object_class_property_set_description(oc
, "sev-device",
293 "SEV device to use");
294 object_class_property_add_str(oc
, "dh-cert-file",
295 sev_guest_get_dh_cert_file
,
296 sev_guest_set_dh_cert_file
);
297 object_class_property_set_description(oc
, "dh-cert-file",
298 "guest owners DH certificate (encoded with base64)");
299 object_class_property_add_str(oc
, "session-file",
300 sev_guest_get_session_file
,
301 sev_guest_set_session_file
);
302 object_class_property_set_description(oc
, "session-file",
303 "guest owners session parameters (encoded with base64)");
307 sev_guest_instance_init(Object
*obj
)
309 SevGuestState
*sev
= SEV_GUEST(obj
);
311 sev
->sev_device
= g_strdup(DEFAULT_SEV_DEVICE
);
312 sev
->policy
= DEFAULT_GUEST_POLICY
;
313 object_property_add_uint32_ptr(obj
, "policy", &sev
->policy
,
314 OBJ_PROP_FLAG_READWRITE
);
315 object_property_add_uint32_ptr(obj
, "handle", &sev
->handle
,
316 OBJ_PROP_FLAG_READWRITE
);
317 object_property_add_uint32_ptr(obj
, "cbitpos", &sev
->cbitpos
,
318 OBJ_PROP_FLAG_READWRITE
);
319 object_property_add_uint32_ptr(obj
, "reduced-phys-bits",
320 &sev
->reduced_phys_bits
,
321 OBJ_PROP_FLAG_READWRITE
);
325 static const TypeInfo sev_guest_info
= {
326 .parent
= TYPE_CONFIDENTIAL_GUEST_SUPPORT
,
327 .name
= TYPE_SEV_GUEST
,
328 .instance_size
= sizeof(SevGuestState
),
329 .instance_finalize
= sev_guest_finalize
,
330 .class_init
= sev_guest_class_init
,
331 .instance_init
= sev_guest_instance_init
,
332 .interfaces
= (InterfaceInfo
[]) {
333 { TYPE_USER_CREATABLE
},
345 sev_get_me_mask(void)
347 return sev_guest
? sev_guest
->me_mask
: ~0;
351 sev_get_cbit_position(void)
353 return sev_guest
? sev_guest
->cbitpos
: 0;
357 sev_get_reduced_phys_bits(void)
359 return sev_guest
? sev_guest
->reduced_phys_bits
: 0;
367 info
= g_new0(SevInfo
, 1);
368 info
->enabled
= sev_enabled();
371 info
->api_major
= sev_guest
->api_major
;
372 info
->api_minor
= sev_guest
->api_minor
;
373 info
->build_id
= sev_guest
->build_id
;
374 info
->policy
= sev_guest
->policy
;
375 info
->state
= sev_guest
->state
;
376 info
->handle
= sev_guest
->handle
;
383 sev_get_pdh_info(int fd
, guchar
**pdh
, size_t *pdh_len
, guchar
**cert_chain
,
384 size_t *cert_chain_len
, Error
**errp
)
386 guchar
*pdh_data
= NULL
;
387 guchar
*cert_chain_data
= NULL
;
388 struct sev_user_data_pdh_cert_export export
= {};
391 /* query the certificate length */
392 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
394 if (err
!= SEV_RET_INVALID_LEN
) {
395 error_setg(errp
, "failed to export PDH cert ret=%d fw_err=%d (%s)",
396 r
, err
, fw_error_to_str(err
));
401 pdh_data
= g_new(guchar
, export
.pdh_cert_len
);
402 cert_chain_data
= g_new(guchar
, export
.cert_chain_len
);
403 export
.pdh_cert_address
= (unsigned long)pdh_data
;
404 export
.cert_chain_address
= (unsigned long)cert_chain_data
;
406 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
408 error_setg(errp
, "failed to export PDH cert ret=%d fw_err=%d (%s)",
409 r
, err
, fw_error_to_str(err
));
414 *pdh_len
= export
.pdh_cert_len
;
415 *cert_chain
= cert_chain_data
;
416 *cert_chain_len
= export
.cert_chain_len
;
421 g_free(cert_chain_data
);
426 sev_get_capabilities(Error
**errp
)
428 SevCapability
*cap
= NULL
;
429 guchar
*pdh_data
= NULL
;
430 guchar
*cert_chain_data
= NULL
;
431 size_t pdh_len
= 0, cert_chain_len
= 0;
435 if (!kvm_enabled()) {
436 error_setg(errp
, "KVM not enabled");
439 if (kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_OP
, NULL
) < 0) {
440 error_setg(errp
, "SEV is not enabled in KVM");
444 fd
= open(DEFAULT_SEV_DEVICE
, O_RDWR
);
446 error_setg_errno(errp
, errno
, "Failed to open %s",
451 if (sev_get_pdh_info(fd
, &pdh_data
, &pdh_len
,
452 &cert_chain_data
, &cert_chain_len
, errp
)) {
456 cap
= g_new0(SevCapability
, 1);
457 cap
->pdh
= g_base64_encode(pdh_data
, pdh_len
);
458 cap
->cert_chain
= g_base64_encode(cert_chain_data
, cert_chain_len
);
460 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
461 cap
->cbitpos
= ebx
& 0x3f;
464 * When SEV feature is enabled, we loose one bit in guest physical
467 cap
->reduced_phys_bits
= 1;
471 g_free(cert_chain_data
);
477 sev_read_file_base64(const char *filename
, guchar
**data
, gsize
*len
)
481 GError
*error
= NULL
;
483 if (!g_file_get_contents(filename
, &base64
, &sz
, &error
)) {
484 error_report("failed to read '%s' (%s)", filename
, error
->message
);
489 *data
= g_base64_decode(base64
, len
);
494 sev_launch_start(SevGuestState
*sev
)
499 struct kvm_sev_launch_start
*start
;
500 guchar
*session
= NULL
, *dh_cert
= NULL
;
502 start
= g_new0(struct kvm_sev_launch_start
, 1);
504 start
->handle
= sev
->handle
;
505 start
->policy
= sev
->policy
;
506 if (sev
->session_file
) {
507 if (sev_read_file_base64(sev
->session_file
, &session
, &sz
) < 0) {
510 start
->session_uaddr
= (unsigned long)session
;
511 start
->session_len
= sz
;
514 if (sev
->dh_cert_file
) {
515 if (sev_read_file_base64(sev
->dh_cert_file
, &dh_cert
, &sz
) < 0) {
518 start
->dh_uaddr
= (unsigned long)dh_cert
;
522 trace_kvm_sev_launch_start(start
->policy
, session
, dh_cert
);
523 rc
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_START
, start
, &fw_error
);
525 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
526 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
530 sev_set_guest_state(sev
, SEV_STATE_LAUNCH_UPDATE
);
531 sev
->handle
= start
->handle
;
542 sev_launch_update_data(SevGuestState
*sev
, uint8_t *addr
, uint64_t len
)
545 struct kvm_sev_launch_update_data update
;
551 update
.uaddr
= (__u64
)(unsigned long)addr
;
553 trace_kvm_sev_launch_update_data(addr
, len
);
554 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_UPDATE_DATA
,
557 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
558 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
565 sev_launch_get_measure(Notifier
*notifier
, void *unused
)
567 SevGuestState
*sev
= sev_guest
;
570 struct kvm_sev_launch_measure
*measurement
;
572 if (!sev_check_state(sev
, SEV_STATE_LAUNCH_UPDATE
)) {
576 measurement
= g_new0(struct kvm_sev_launch_measure
, 1);
578 /* query the measurement blob length */
579 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
580 measurement
, &error
);
581 if (!measurement
->len
) {
582 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
583 __func__
, ret
, error
, fw_error_to_str(errno
));
584 goto free_measurement
;
587 data
= g_new0(guchar
, measurement
->len
);
588 measurement
->uaddr
= (unsigned long)data
;
590 /* get the measurement blob */
591 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
592 measurement
, &error
);
594 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
595 __func__
, ret
, error
, fw_error_to_str(errno
));
599 sev_set_guest_state(sev
, SEV_STATE_LAUNCH_SECRET
);
601 /* encode the measurement value and emit the event */
602 sev
->measurement
= g_base64_encode(data
, measurement
->len
);
603 trace_kvm_sev_launch_measurement(sev
->measurement
);
612 sev_get_launch_measurement(void)
615 sev_guest
->state
>= SEV_STATE_LAUNCH_SECRET
) {
616 return g_strdup(sev_guest
->measurement
);
622 static Notifier sev_machine_done_notify
= {
623 .notify
= sev_launch_get_measure
,
627 sev_launch_finish(SevGuestState
*sev
)
630 Error
*local_err
= NULL
;
632 trace_kvm_sev_launch_finish();
633 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_FINISH
, 0, &error
);
635 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
636 __func__
, ret
, error
, fw_error_to_str(error
));
640 sev_set_guest_state(sev
, SEV_STATE_RUNNING
);
642 /* add migration blocker */
643 error_setg(&sev_mig_blocker
,
644 "SEV: Migration is not implemented");
645 ret
= migrate_add_blocker(sev_mig_blocker
, &local_err
);
647 error_report_err(local_err
);
648 error_free(sev_mig_blocker
);
654 sev_vm_state_change(void *opaque
, int running
, RunState state
)
656 SevGuestState
*sev
= opaque
;
659 if (!sev_check_state(sev
, SEV_STATE_RUNNING
)) {
660 sev_launch_finish(sev
);
665 int sev_kvm_init(ConfidentialGuestSupport
*cgs
)
667 SevGuestState
*sev
= SEV_GUEST(cgs
);
671 uint32_t host_cbitpos
;
672 struct sev_user_data_status status
= {};
674 ret
= ram_block_discard_disable(true);
676 error_report("%s: cannot disable RAM discard", __func__
);
681 sev
->state
= SEV_STATE_UNINIT
;
683 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
684 host_cbitpos
= ebx
& 0x3f;
686 if (host_cbitpos
!= sev
->cbitpos
) {
687 error_report("%s: cbitpos check failed, host '%d' requested '%d'",
688 __func__
, host_cbitpos
, sev
->cbitpos
);
692 if (sev
->reduced_phys_bits
< 1) {
693 error_report("%s: reduced_phys_bits check failed, it should be >=1,"
694 " requested '%d'", __func__
, sev
->reduced_phys_bits
);
698 sev
->me_mask
= ~(1UL << sev
->cbitpos
);
700 devname
= object_property_get_str(OBJECT(sev
), "sev-device", NULL
);
701 sev
->sev_fd
= open(devname
, O_RDWR
);
702 if (sev
->sev_fd
< 0) {
703 error_report("%s: Failed to open %s '%s'", __func__
,
704 devname
, strerror(errno
));
707 if (sev
->sev_fd
< 0) {
711 ret
= sev_platform_ioctl(sev
->sev_fd
, SEV_PLATFORM_STATUS
, &status
,
714 error_report("%s: failed to get platform status ret=%d "
715 "fw_error='%d: %s'", __func__
, ret
, fw_error
,
716 fw_error_to_str(fw_error
));
719 sev
->build_id
= status
.build
;
720 sev
->api_major
= status
.api_major
;
721 sev
->api_minor
= status
.api_minor
;
723 trace_kvm_sev_init();
724 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_INIT
, NULL
, &fw_error
);
726 error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
727 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
731 ret
= sev_launch_start(sev
);
733 error_report("%s: failed to create encryption context", __func__
);
737 ram_block_notifier_add(&sev_ram_notifier
);
738 qemu_add_machine_init_done_notifier(&sev_machine_done_notify
);
739 qemu_add_vm_change_state_handler(sev_vm_state_change
, sev
);
744 ram_block_discard_disable(false);
749 sev_encrypt_flash(uint8_t *ptr
, uint64_t len
, Error
**errp
)
755 /* if SEV is in update state then encrypt the data else do nothing */
756 if (sev_check_state(sev_guest
, SEV_STATE_LAUNCH_UPDATE
)) {
757 int ret
= sev_launch_update_data(sev_guest
, ptr
, len
);
759 error_setg(errp
, "failed to encrypt pflash rom");
767 int sev_inject_launch_secret(const char *packet_hdr
, const char *secret
,
768 uint64_t gpa
, Error
**errp
)
770 struct kvm_sev_launch_secret input
;
771 g_autofree guchar
*data
= NULL
, *hdr
= NULL
;
774 gsize hdr_sz
= 0, data_sz
= 0;
775 MemoryRegion
*mr
= NULL
;
778 error_setg(errp
, "SEV: SEV not enabled.");
782 /* secret can be injected only in this state */
783 if (!sev_check_state(sev_guest
, SEV_STATE_LAUNCH_SECRET
)) {
784 error_setg(errp
, "SEV: Not in correct state. (LSECRET) %x",
789 hdr
= g_base64_decode(packet_hdr
, &hdr_sz
);
790 if (!hdr
|| !hdr_sz
) {
791 error_setg(errp
, "SEV: Failed to decode sequence header");
795 data
= g_base64_decode(secret
, &data_sz
);
796 if (!data
|| !data_sz
) {
797 error_setg(errp
, "SEV: Failed to decode data");
801 hva
= gpa2hva(&mr
, gpa
, data_sz
, errp
);
803 error_prepend(errp
, "SEV: Failed to calculate guest address: ");
807 input
.hdr_uaddr
= (uint64_t)(unsigned long)hdr
;
808 input
.hdr_len
= hdr_sz
;
810 input
.trans_uaddr
= (uint64_t)(unsigned long)data
;
811 input
.trans_len
= data_sz
;
813 input
.guest_uaddr
= (uint64_t)(unsigned long)hva
;
814 input
.guest_len
= data_sz
;
816 trace_kvm_sev_launch_secret(gpa
, input
.guest_uaddr
,
817 input
.trans_uaddr
, input
.trans_len
);
819 ret
= sev_ioctl(sev_guest
->sev_fd
, KVM_SEV_LAUNCH_SECRET
,
822 error_setg(errp
, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
823 ret
, error
, fw_error_to_str(error
));
831 sev_register_types(void)
833 type_register_static(&sev_guest_info
);
836 type_init(sev_register_types
);