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 "qemu/uuid.h"
26 #include "sysemu/kvm.h"
28 #include "sysemu/sysemu.h"
29 #include "sysemu/runstate.h"
31 #include "migration/blocker.h"
32 #include "qom/object.h"
33 #include "exec/address-spaces.h"
34 #include "monitor/monitor.h"
35 #include "exec/confidential-guest-support.h"
36 #include "hw/i386/pc.h"
38 #define TYPE_SEV_GUEST "sev-guest"
39 OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState
, SEV_GUEST
)
45 * The SevGuestState object is used for creating and managing a SEV
49 * -object sev-guest,id=sev0 \
50 * -machine ...,memory-encryption=sev0
52 struct SevGuestState
{
53 ConfidentialGuestSupport parent_obj
;
55 /* configuration parameters */
61 uint32_t reduced_phys_bits
;
75 bool reset_data_valid
;
78 #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
79 #define DEFAULT_SEV_DEVICE "/dev/sev"
81 #define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
82 typedef struct __attribute__((__packed__
)) SevInfoBlock
{
83 /* SEV-ES Reset Vector Address */
87 static SevGuestState
*sev_guest
;
88 static Error
*sev_mig_blocker
;
90 static const char *const sev_fw_errlist
[] = {
92 "Platform state is invalid",
93 "Guest state is invalid",
94 "Platform configuration is invalid",
96 "Platform is already owned",
97 "Certificate is invalid",
98 "Policy is not allowed",
99 "Guest is not active",
103 "Asid is already owned",
105 "WBINVD is required",
106 "DF_FLUSH is required",
107 "Guest handle is invalid",
112 "Feature not supported",
116 #define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
119 sev_ioctl(int fd
, int cmd
, void *data
, int *error
)
122 struct kvm_sev_cmd input
;
124 memset(&input
, 0x0, sizeof(input
));
128 input
.data
= (__u64
)(unsigned long)data
;
130 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_OP
, &input
);
133 *error
= input
.error
;
140 sev_platform_ioctl(int fd
, int cmd
, void *data
, int *error
)
143 struct sev_issue_cmd arg
;
146 arg
.data
= (unsigned long)data
;
147 r
= ioctl(fd
, SEV_ISSUE_CMD
, &arg
);
156 fw_error_to_str(int code
)
158 if (code
< 0 || code
>= SEV_FW_MAX_ERROR
) {
159 return "unknown error";
162 return sev_fw_errlist
[code
];
166 sev_check_state(const SevGuestState
*sev
, SevState state
)
169 return sev
->state
== state
? true : false;
173 sev_set_guest_state(SevGuestState
*sev
, SevState new_state
)
175 assert(new_state
< SEV_STATE__MAX
);
178 trace_kvm_sev_change_state(SevState_str(sev
->state
),
179 SevState_str(new_state
));
180 sev
->state
= new_state
;
184 sev_ram_block_added(RAMBlockNotifier
*n
, void *host
, size_t size
)
187 struct kvm_enc_region range
;
192 * The RAM device presents a memory region that should be treated
193 * as IO region and should not be pinned.
195 mr
= memory_region_from_host(host
, &offset
);
196 if (mr
&& memory_region_is_ram_device(mr
)) {
200 range
.addr
= (__u64
)(unsigned long)host
;
203 trace_kvm_memcrypt_register_region(host
, size
);
204 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_REG_REGION
, &range
);
206 error_report("%s: failed to register region (%p+%#zx) error '%s'",
207 __func__
, host
, size
, strerror(errno
));
213 sev_ram_block_removed(RAMBlockNotifier
*n
, void *host
, size_t size
)
216 struct kvm_enc_region range
;
221 * The RAM device presents a memory region that should be treated
222 * as IO region and should not have been pinned.
224 mr
= memory_region_from_host(host
, &offset
);
225 if (mr
&& memory_region_is_ram_device(mr
)) {
229 range
.addr
= (__u64
)(unsigned long)host
;
232 trace_kvm_memcrypt_unregister_region(host
, size
);
233 r
= kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_UNREG_REGION
, &range
);
235 error_report("%s: failed to unregister region (%p+%#zx)",
236 __func__
, host
, size
);
240 static struct RAMBlockNotifier sev_ram_notifier
= {
241 .ram_block_added
= sev_ram_block_added
,
242 .ram_block_removed
= sev_ram_block_removed
,
246 sev_guest_finalize(Object
*obj
)
251 sev_guest_get_session_file(Object
*obj
, Error
**errp
)
253 SevGuestState
*s
= SEV_GUEST(obj
);
255 return s
->session_file
? g_strdup(s
->session_file
) : NULL
;
259 sev_guest_set_session_file(Object
*obj
, const char *value
, Error
**errp
)
261 SevGuestState
*s
= SEV_GUEST(obj
);
263 s
->session_file
= g_strdup(value
);
267 sev_guest_get_dh_cert_file(Object
*obj
, Error
**errp
)
269 SevGuestState
*s
= SEV_GUEST(obj
);
271 return g_strdup(s
->dh_cert_file
);
275 sev_guest_set_dh_cert_file(Object
*obj
, const char *value
, Error
**errp
)
277 SevGuestState
*s
= SEV_GUEST(obj
);
279 s
->dh_cert_file
= g_strdup(value
);
283 sev_guest_get_sev_device(Object
*obj
, Error
**errp
)
285 SevGuestState
*sev
= SEV_GUEST(obj
);
287 return g_strdup(sev
->sev_device
);
291 sev_guest_set_sev_device(Object
*obj
, const char *value
, Error
**errp
)
293 SevGuestState
*sev
= SEV_GUEST(obj
);
295 sev
->sev_device
= g_strdup(value
);
299 sev_guest_class_init(ObjectClass
*oc
, void *data
)
301 object_class_property_add_str(oc
, "sev-device",
302 sev_guest_get_sev_device
,
303 sev_guest_set_sev_device
);
304 object_class_property_set_description(oc
, "sev-device",
305 "SEV device to use");
306 object_class_property_add_str(oc
, "dh-cert-file",
307 sev_guest_get_dh_cert_file
,
308 sev_guest_set_dh_cert_file
);
309 object_class_property_set_description(oc
, "dh-cert-file",
310 "guest owners DH certificate (encoded with base64)");
311 object_class_property_add_str(oc
, "session-file",
312 sev_guest_get_session_file
,
313 sev_guest_set_session_file
);
314 object_class_property_set_description(oc
, "session-file",
315 "guest owners session parameters (encoded with base64)");
319 sev_guest_instance_init(Object
*obj
)
321 SevGuestState
*sev
= SEV_GUEST(obj
);
323 sev
->sev_device
= g_strdup(DEFAULT_SEV_DEVICE
);
324 sev
->policy
= DEFAULT_GUEST_POLICY
;
325 object_property_add_uint32_ptr(obj
, "policy", &sev
->policy
,
326 OBJ_PROP_FLAG_READWRITE
);
327 object_property_add_uint32_ptr(obj
, "handle", &sev
->handle
,
328 OBJ_PROP_FLAG_READWRITE
);
329 object_property_add_uint32_ptr(obj
, "cbitpos", &sev
->cbitpos
,
330 OBJ_PROP_FLAG_READWRITE
);
331 object_property_add_uint32_ptr(obj
, "reduced-phys-bits",
332 &sev
->reduced_phys_bits
,
333 OBJ_PROP_FLAG_READWRITE
);
337 static const TypeInfo sev_guest_info
= {
338 .parent
= TYPE_CONFIDENTIAL_GUEST_SUPPORT
,
339 .name
= TYPE_SEV_GUEST
,
340 .instance_size
= sizeof(SevGuestState
),
341 .instance_finalize
= sev_guest_finalize
,
342 .class_init
= sev_guest_class_init
,
343 .instance_init
= sev_guest_instance_init
,
344 .interfaces
= (InterfaceInfo
[]) {
345 { TYPE_USER_CREATABLE
},
359 return sev_enabled() && (sev_guest
->policy
& SEV_POLICY_ES
);
363 sev_get_me_mask(void)
365 return sev_guest
? sev_guest
->me_mask
: ~0;
369 sev_get_cbit_position(void)
371 return sev_guest
? sev_guest
->cbitpos
: 0;
375 sev_get_reduced_phys_bits(void)
377 return sev_guest
? sev_guest
->reduced_phys_bits
: 0;
385 info
= g_new0(SevInfo
, 1);
386 info
->enabled
= sev_enabled();
389 info
->api_major
= sev_guest
->api_major
;
390 info
->api_minor
= sev_guest
->api_minor
;
391 info
->build_id
= sev_guest
->build_id
;
392 info
->policy
= sev_guest
->policy
;
393 info
->state
= sev_guest
->state
;
394 info
->handle
= sev_guest
->handle
;
401 sev_get_pdh_info(int fd
, guchar
**pdh
, size_t *pdh_len
, guchar
**cert_chain
,
402 size_t *cert_chain_len
, Error
**errp
)
404 guchar
*pdh_data
= NULL
;
405 guchar
*cert_chain_data
= NULL
;
406 struct sev_user_data_pdh_cert_export export
= {};
409 /* query the certificate length */
410 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
412 if (err
!= SEV_RET_INVALID_LEN
) {
413 error_setg(errp
, "failed to export PDH cert ret=%d fw_err=%d (%s)",
414 r
, err
, fw_error_to_str(err
));
419 pdh_data
= g_new(guchar
, export
.pdh_cert_len
);
420 cert_chain_data
= g_new(guchar
, export
.cert_chain_len
);
421 export
.pdh_cert_address
= (unsigned long)pdh_data
;
422 export
.cert_chain_address
= (unsigned long)cert_chain_data
;
424 r
= sev_platform_ioctl(fd
, SEV_PDH_CERT_EXPORT
, &export
, &err
);
426 error_setg(errp
, "failed to export PDH cert ret=%d fw_err=%d (%s)",
427 r
, err
, fw_error_to_str(err
));
432 *pdh_len
= export
.pdh_cert_len
;
433 *cert_chain
= cert_chain_data
;
434 *cert_chain_len
= export
.cert_chain_len
;
439 g_free(cert_chain_data
);
444 sev_get_capabilities(Error
**errp
)
446 SevCapability
*cap
= NULL
;
447 guchar
*pdh_data
= NULL
;
448 guchar
*cert_chain_data
= NULL
;
449 size_t pdh_len
= 0, cert_chain_len
= 0;
453 if (!kvm_enabled()) {
454 error_setg(errp
, "KVM not enabled");
457 if (kvm_vm_ioctl(kvm_state
, KVM_MEMORY_ENCRYPT_OP
, NULL
) < 0) {
458 error_setg(errp
, "SEV is not enabled in KVM");
462 fd
= open(DEFAULT_SEV_DEVICE
, O_RDWR
);
464 error_setg_errno(errp
, errno
, "Failed to open %s",
469 if (sev_get_pdh_info(fd
, &pdh_data
, &pdh_len
,
470 &cert_chain_data
, &cert_chain_len
, errp
)) {
474 cap
= g_new0(SevCapability
, 1);
475 cap
->pdh
= g_base64_encode(pdh_data
, pdh_len
);
476 cap
->cert_chain
= g_base64_encode(cert_chain_data
, cert_chain_len
);
478 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
479 cap
->cbitpos
= ebx
& 0x3f;
482 * When SEV feature is enabled, we loose one bit in guest physical
485 cap
->reduced_phys_bits
= 1;
489 g_free(cert_chain_data
);
495 sev_read_file_base64(const char *filename
, guchar
**data
, gsize
*len
)
499 GError
*error
= NULL
;
501 if (!g_file_get_contents(filename
, &base64
, &sz
, &error
)) {
502 error_report("failed to read '%s' (%s)", filename
, error
->message
);
507 *data
= g_base64_decode(base64
, len
);
512 sev_launch_start(SevGuestState
*sev
)
517 struct kvm_sev_launch_start
*start
;
518 guchar
*session
= NULL
, *dh_cert
= NULL
;
520 start
= g_new0(struct kvm_sev_launch_start
, 1);
522 start
->handle
= sev
->handle
;
523 start
->policy
= sev
->policy
;
524 if (sev
->session_file
) {
525 if (sev_read_file_base64(sev
->session_file
, &session
, &sz
) < 0) {
528 start
->session_uaddr
= (unsigned long)session
;
529 start
->session_len
= sz
;
532 if (sev
->dh_cert_file
) {
533 if (sev_read_file_base64(sev
->dh_cert_file
, &dh_cert
, &sz
) < 0) {
536 start
->dh_uaddr
= (unsigned long)dh_cert
;
540 trace_kvm_sev_launch_start(start
->policy
, session
, dh_cert
);
541 rc
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_START
, start
, &fw_error
);
543 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
544 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
548 sev_set_guest_state(sev
, SEV_STATE_LAUNCH_UPDATE
);
549 sev
->handle
= start
->handle
;
560 sev_launch_update_data(SevGuestState
*sev
, uint8_t *addr
, uint64_t len
)
563 struct kvm_sev_launch_update_data update
;
569 update
.uaddr
= (__u64
)(unsigned long)addr
;
571 trace_kvm_sev_launch_update_data(addr
, len
);
572 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_UPDATE_DATA
,
575 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
576 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
583 sev_launch_update_vmsa(SevGuestState
*sev
)
587 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_UPDATE_VMSA
, NULL
, &fw_error
);
589 error_report("%s: LAUNCH_UPDATE_VMSA ret=%d fw_error=%d '%s'",
590 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
597 sev_launch_get_measure(Notifier
*notifier
, void *unused
)
599 SevGuestState
*sev
= sev_guest
;
602 struct kvm_sev_launch_measure
*measurement
;
604 if (!sev_check_state(sev
, SEV_STATE_LAUNCH_UPDATE
)) {
608 if (sev_es_enabled()) {
609 /* measure all the VM save areas before getting launch_measure */
610 ret
= sev_launch_update_vmsa(sev
);
616 measurement
= g_new0(struct kvm_sev_launch_measure
, 1);
618 /* query the measurement blob length */
619 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
620 measurement
, &error
);
621 if (!measurement
->len
) {
622 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
623 __func__
, ret
, error
, fw_error_to_str(errno
));
624 goto free_measurement
;
627 data
= g_new0(guchar
, measurement
->len
);
628 measurement
->uaddr
= (unsigned long)data
;
630 /* get the measurement blob */
631 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_MEASURE
,
632 measurement
, &error
);
634 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
635 __func__
, ret
, error
, fw_error_to_str(errno
));
639 sev_set_guest_state(sev
, SEV_STATE_LAUNCH_SECRET
);
641 /* encode the measurement value and emit the event */
642 sev
->measurement
= g_base64_encode(data
, measurement
->len
);
643 trace_kvm_sev_launch_measurement(sev
->measurement
);
652 sev_get_launch_measurement(void)
655 sev_guest
->state
>= SEV_STATE_LAUNCH_SECRET
) {
656 return g_strdup(sev_guest
->measurement
);
662 static Notifier sev_machine_done_notify
= {
663 .notify
= sev_launch_get_measure
,
667 sev_launch_finish(SevGuestState
*sev
)
670 Error
*local_err
= NULL
;
672 trace_kvm_sev_launch_finish();
673 ret
= sev_ioctl(sev
->sev_fd
, KVM_SEV_LAUNCH_FINISH
, 0, &error
);
675 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
676 __func__
, ret
, error
, fw_error_to_str(error
));
680 sev_set_guest_state(sev
, SEV_STATE_RUNNING
);
682 /* add migration blocker */
683 error_setg(&sev_mig_blocker
,
684 "SEV: Migration is not implemented");
685 ret
= migrate_add_blocker(sev_mig_blocker
, &local_err
);
687 error_report_err(local_err
);
688 error_free(sev_mig_blocker
);
694 sev_vm_state_change(void *opaque
, int running
, RunState state
)
696 SevGuestState
*sev
= opaque
;
699 if (!sev_check_state(sev
, SEV_STATE_RUNNING
)) {
700 sev_launch_finish(sev
);
705 int sev_kvm_init(ConfidentialGuestSupport
*cgs
, Error
**errp
)
708 = (SevGuestState
*)object_dynamic_cast(OBJECT(cgs
), TYPE_SEV_GUEST
);
710 int ret
, fw_error
, cmd
;
712 uint32_t host_cbitpos
;
713 struct sev_user_data_status status
= {};
719 ret
= ram_block_discard_disable(true);
721 error_report("%s: cannot disable RAM discard", __func__
);
726 sev
->state
= SEV_STATE_UNINIT
;
728 host_cpuid(0x8000001F, 0, NULL
, &ebx
, NULL
, NULL
);
729 host_cbitpos
= ebx
& 0x3f;
731 if (host_cbitpos
!= sev
->cbitpos
) {
732 error_setg(errp
, "%s: cbitpos check failed, host '%d' requested '%d'",
733 __func__
, host_cbitpos
, sev
->cbitpos
);
737 if (sev
->reduced_phys_bits
< 1) {
738 error_setg(errp
, "%s: reduced_phys_bits check failed, it should be >=1,"
739 " requested '%d'", __func__
, sev
->reduced_phys_bits
);
743 sev
->me_mask
= ~(1UL << sev
->cbitpos
);
745 devname
= object_property_get_str(OBJECT(sev
), "sev-device", NULL
);
746 sev
->sev_fd
= open(devname
, O_RDWR
);
747 if (sev
->sev_fd
< 0) {
748 error_setg(errp
, "%s: Failed to open %s '%s'", __func__
,
749 devname
, strerror(errno
));
755 ret
= sev_platform_ioctl(sev
->sev_fd
, SEV_PLATFORM_STATUS
, &status
,
758 error_setg(errp
, "%s: failed to get platform status ret=%d "
759 "fw_error='%d: %s'", __func__
, ret
, fw_error
,
760 fw_error_to_str(fw_error
));
763 sev
->build_id
= status
.build
;
764 sev
->api_major
= status
.api_major
;
765 sev
->api_minor
= status
.api_minor
;
767 if (sev_es_enabled()) {
768 if (!kvm_kernel_irqchip_allowed()) {
769 error_report("%s: SEV-ES guests require in-kernel irqchip support",
774 if (!(status
.flags
& SEV_STATUS_FLAGS_CONFIG_ES
)) {
775 error_report("%s: guest policy requires SEV-ES, but "
776 "host SEV-ES support unavailable",
780 cmd
= KVM_SEV_ES_INIT
;
785 trace_kvm_sev_init();
786 ret
= sev_ioctl(sev
->sev_fd
, cmd
, NULL
, &fw_error
);
788 error_setg(errp
, "%s: failed to initialize ret=%d fw_error=%d '%s'",
789 __func__
, ret
, fw_error
, fw_error_to_str(fw_error
));
793 ret
= sev_launch_start(sev
);
795 error_setg(errp
, "%s: failed to create encryption context", __func__
);
799 ram_block_notifier_add(&sev_ram_notifier
);
800 qemu_add_machine_init_done_notifier(&sev_machine_done_notify
);
801 qemu_add_vm_change_state_handler(sev_vm_state_change
, sev
);
808 ram_block_discard_disable(false);
813 sev_encrypt_flash(uint8_t *ptr
, uint64_t len
, Error
**errp
)
819 /* if SEV is in update state then encrypt the data else do nothing */
820 if (sev_check_state(sev_guest
, SEV_STATE_LAUNCH_UPDATE
)) {
821 int ret
= sev_launch_update_data(sev_guest
, ptr
, len
);
823 error_setg(errp
, "failed to encrypt pflash rom");
831 int sev_inject_launch_secret(const char *packet_hdr
, const char *secret
,
832 uint64_t gpa
, Error
**errp
)
834 struct kvm_sev_launch_secret input
;
835 g_autofree guchar
*data
= NULL
, *hdr
= NULL
;
838 gsize hdr_sz
= 0, data_sz
= 0;
839 MemoryRegion
*mr
= NULL
;
842 error_setg(errp
, "SEV: SEV not enabled.");
846 /* secret can be injected only in this state */
847 if (!sev_check_state(sev_guest
, SEV_STATE_LAUNCH_SECRET
)) {
848 error_setg(errp
, "SEV: Not in correct state. (LSECRET) %x",
853 hdr
= g_base64_decode(packet_hdr
, &hdr_sz
);
854 if (!hdr
|| !hdr_sz
) {
855 error_setg(errp
, "SEV: Failed to decode sequence header");
859 data
= g_base64_decode(secret
, &data_sz
);
860 if (!data
|| !data_sz
) {
861 error_setg(errp
, "SEV: Failed to decode data");
865 hva
= gpa2hva(&mr
, gpa
, data_sz
, errp
);
867 error_prepend(errp
, "SEV: Failed to calculate guest address: ");
871 input
.hdr_uaddr
= (uint64_t)(unsigned long)hdr
;
872 input
.hdr_len
= hdr_sz
;
874 input
.trans_uaddr
= (uint64_t)(unsigned long)data
;
875 input
.trans_len
= data_sz
;
877 input
.guest_uaddr
= (uint64_t)(unsigned long)hva
;
878 input
.guest_len
= data_sz
;
880 trace_kvm_sev_launch_secret(gpa
, input
.guest_uaddr
,
881 input
.trans_uaddr
, input
.trans_len
);
883 ret
= sev_ioctl(sev_guest
->sev_fd
, KVM_SEV_LAUNCH_SECRET
,
886 error_setg(errp
, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
887 ret
, error
, fw_error_to_str(error
));
895 sev_es_parse_reset_block(SevInfoBlock
*info
, uint32_t *addr
)
897 if (!info
->reset_addr
) {
898 error_report("SEV-ES reset address is zero");
902 *addr
= info
->reset_addr
;
908 sev_es_find_reset_vector(void *flash_ptr
, uint64_t flash_size
,
911 QemuUUID info_guid
, *guid
;
917 * Initialize the address to zero. An address of zero with a successful
918 * return code indicates that SEV-ES is not active.
923 * Extract the AP reset vector for SEV-ES guests by locating the SEV GUID.
924 * The SEV GUID is located on its own (original implementation) or within
925 * the Firmware GUID Table (new implementation), either of which are
926 * located 32 bytes from the end of the flash.
928 * Check the Firmware GUID Table first.
930 if (pc_system_ovmf_table_find(SEV_INFO_BLOCK_GUID
, &data
, NULL
)) {
931 return sev_es_parse_reset_block((SevInfoBlock
*)data
, addr
);
935 * SEV info block not found in the Firmware GUID Table (or there isn't
936 * a Firmware GUID Table), fall back to the original implementation.
938 data
= flash_ptr
+ flash_size
- 0x20;
940 qemu_uuid_parse(SEV_INFO_BLOCK_GUID
, &info_guid
);
941 info_guid
= qemu_uuid_bswap(info_guid
); /* GUIDs are LE */
943 guid
= (QemuUUID
*)(data
- sizeof(info_guid
));
944 if (!qemu_uuid_is_equal(guid
, &info_guid
)) {
945 error_report("SEV information block/Firmware GUID Table block not found in pflash rom");
949 len
= (uint16_t *)((uint8_t *)guid
- sizeof(*len
));
950 info
= (SevInfoBlock
*)(data
- le16_to_cpu(*len
));
952 return sev_es_parse_reset_block(info
, addr
);
955 void sev_es_set_reset_vector(CPUState
*cpu
)
960 /* Only update if we have valid reset information */
961 if (!sev_guest
|| !sev_guest
->reset_data_valid
) {
965 /* Do not update the BSP reset state */
966 if (cpu
->cpu_index
== 0) {
973 cpu_x86_load_seg_cache(env
, R_CS
, 0xf000, sev_guest
->reset_cs
, 0xffff,
974 DESC_P_MASK
| DESC_S_MASK
| DESC_CS_MASK
|
975 DESC_R_MASK
| DESC_A_MASK
);
977 env
->eip
= sev_guest
->reset_ip
;
980 int sev_es_save_reset_vector(void *flash_ptr
, uint64_t flash_size
)
986 if (!sev_es_enabled()) {
991 ret
= sev_es_find_reset_vector(flash_ptr
, flash_size
,
998 sev_guest
->reset_cs
= addr
& 0xffff0000;
999 sev_guest
->reset_ip
= addr
& 0x0000ffff;
1000 sev_guest
->reset_data_valid
= true;
1003 sev_es_set_reset_vector(cpu
);
1011 sev_register_types(void)
1013 type_register_static(&sev_guest_info
);
1016 type_init(sev_register_types
);