KVM: SVM: Treat exit_code as an unsigned 64-bit value through all of KVM

Fix KVM's long-standing buggy handling of SVM's exit_code as a 32-bit
value.  Per the APM and Xen commit d1bd157fbc ("Big merge the HVM
full-virtualisation abstractions.") (which is arguably more trustworthy
than KVM), offset 0x70 is a single 64-bit value:

  070h 63:0 EXITCODE

Track exit_code as a single u64 to prevent reintroducing bugs where KVM
neglects to correctly set bits 63:32.

Fixes: 6aa8b732ca ("[PATCH] kvm: userspace interface")
Cc: Jim Mattson <jmattson@google.com>
Cc: Yosry Ahmed <yosry.ahmed@linux.dev>
Reviewed-by: Yosry Ahmed <yosry.ahmed@linux.dev>
Link: https://patch.msgid.link/20251230211347.4099600-6-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
master
Sean Christopherson 2025-12-30 13:13:44 -08:00
parent 405fce694b
commit d7507a94a0
11 changed files with 42 additions and 69 deletions

View File

@ -137,8 +137,7 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
u32 int_vector; u32 int_vector;
u32 int_state; u32 int_state;
u8 reserved_3[4]; u8 reserved_3[4];
u32 exit_code; u64 exit_code;
u32 exit_code_hi;
u64 exit_info_1; u64 exit_info_1;
u64 exit_info_2; u64 exit_info_2;
u32 exit_int_info; u32 exit_int_info;

View File

@ -103,38 +103,38 @@
#define SVM_EXIT_VMGEXIT 0x403 #define SVM_EXIT_VMGEXIT 0x403
/* SEV-ES software-defined VMGEXIT events */ /* SEV-ES software-defined VMGEXIT events */
#define SVM_VMGEXIT_MMIO_READ 0x80000001 #define SVM_VMGEXIT_MMIO_READ 0x80000001ull
#define SVM_VMGEXIT_MMIO_WRITE 0x80000002 #define SVM_VMGEXIT_MMIO_WRITE 0x80000002ull
#define SVM_VMGEXIT_NMI_COMPLETE 0x80000003 #define SVM_VMGEXIT_NMI_COMPLETE 0x80000003ull
#define SVM_VMGEXIT_AP_HLT_LOOP 0x80000004 #define SVM_VMGEXIT_AP_HLT_LOOP 0x80000004ull
#define SVM_VMGEXIT_AP_JUMP_TABLE 0x80000005 #define SVM_VMGEXIT_AP_JUMP_TABLE 0x80000005ull
#define SVM_VMGEXIT_SET_AP_JUMP_TABLE 0 #define SVM_VMGEXIT_SET_AP_JUMP_TABLE 0
#define SVM_VMGEXIT_GET_AP_JUMP_TABLE 1 #define SVM_VMGEXIT_GET_AP_JUMP_TABLE 1
#define SVM_VMGEXIT_PSC 0x80000010 #define SVM_VMGEXIT_PSC 0x80000010ull
#define SVM_VMGEXIT_GUEST_REQUEST 0x80000011 #define SVM_VMGEXIT_GUEST_REQUEST 0x80000011ull
#define SVM_VMGEXIT_EXT_GUEST_REQUEST 0x80000012 #define SVM_VMGEXIT_EXT_GUEST_REQUEST 0x80000012ull
#define SVM_VMGEXIT_AP_CREATION 0x80000013 #define SVM_VMGEXIT_AP_CREATION 0x80000013ull
#define SVM_VMGEXIT_AP_CREATE_ON_INIT 0 #define SVM_VMGEXIT_AP_CREATE_ON_INIT 0
#define SVM_VMGEXIT_AP_CREATE 1 #define SVM_VMGEXIT_AP_CREATE 1
#define SVM_VMGEXIT_AP_DESTROY 2 #define SVM_VMGEXIT_AP_DESTROY 2
#define SVM_VMGEXIT_SNP_RUN_VMPL 0x80000018 #define SVM_VMGEXIT_SNP_RUN_VMPL 0x80000018ull
#define SVM_VMGEXIT_SAVIC 0x8000001a #define SVM_VMGEXIT_SAVIC 0x8000001aull
#define SVM_VMGEXIT_SAVIC_REGISTER_GPA 0 #define SVM_VMGEXIT_SAVIC_REGISTER_GPA 0
#define SVM_VMGEXIT_SAVIC_UNREGISTER_GPA 1 #define SVM_VMGEXIT_SAVIC_UNREGISTER_GPA 1
#define SVM_VMGEXIT_SAVIC_SELF_GPA ~0ULL #define SVM_VMGEXIT_SAVIC_SELF_GPA ~0ULL
#define SVM_VMGEXIT_HV_FEATURES 0x8000fffd #define SVM_VMGEXIT_HV_FEATURES 0x8000fffdull
#define SVM_VMGEXIT_TERM_REQUEST 0x8000fffe #define SVM_VMGEXIT_TERM_REQUEST 0x8000fffeull
#define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code) \ #define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code) \
/* SW_EXITINFO1[3:0] */ \ /* SW_EXITINFO1[3:0] */ \
(((((u64)reason_set) & 0xf)) | \ (((((u64)reason_set) & 0xf)) | \
/* SW_EXITINFO1[11:4] */ \ /* SW_EXITINFO1[11:4] */ \
((((u64)reason_code) & 0xff) << 4)) ((((u64)reason_code) & 0xff) << 4))
#define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff #define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffffull
/* Exit code reserved for hypervisor/software use */ /* Exit code reserved for hypervisor/software use */
#define SVM_EXIT_SW 0xf0000000 #define SVM_EXIT_SW 0xf0000000ull
#define SVM_EXIT_ERR -1 #define SVM_EXIT_ERR -1ull
#define SVM_EXIT_REASONS \ #define SVM_EXIT_REASONS \
{ SVM_EXIT_READ_CR0, "read_cr0" }, \ { SVM_EXIT_READ_CR0, "read_cr0" }, \

View File

@ -11,7 +11,6 @@ void svm_hv_inject_synthetic_vmexit_post_tlb_flush(struct kvm_vcpu *vcpu)
struct vcpu_svm *svm = to_svm(vcpu); struct vcpu_svm *svm = to_svm(vcpu);
svm->vmcb->control.exit_code = HV_SVM_EXITCODE_ENL; svm->vmcb->control.exit_code = HV_SVM_EXITCODE_ENL;
svm->vmcb->control.exit_code_hi = 0;
svm->vmcb->control.exit_info_1 = HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH; svm->vmcb->control.exit_info_1 = HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH;
svm->vmcb->control.exit_info_2 = 0; svm->vmcb->control.exit_info_2 = 0;
nested_svm_vmexit(svm); nested_svm_vmexit(svm);

View File

@ -45,7 +45,6 @@ static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu,
* correctly fill in the high bits of exit_info_1. * correctly fill in the high bits of exit_info_1.
*/ */
vmcb->control.exit_code = SVM_EXIT_NPF; vmcb->control.exit_code = SVM_EXIT_NPF;
vmcb->control.exit_code_hi = 0;
vmcb->control.exit_info_1 = (1ULL << 32); vmcb->control.exit_info_1 = (1ULL << 32);
vmcb->control.exit_info_2 = fault->address; vmcb->control.exit_info_2 = fault->address;
} }
@ -441,7 +440,6 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcpu *vcpu,
to->int_vector = from->int_vector; to->int_vector = from->int_vector;
to->int_state = from->int_state; to->int_state = from->int_state;
to->exit_code = from->exit_code; to->exit_code = from->exit_code;
to->exit_code_hi = from->exit_code_hi;
to->exit_info_1 = from->exit_info_1; to->exit_info_1 = from->exit_info_1;
to->exit_info_2 = from->exit_info_2; to->exit_info_2 = from->exit_info_2;
to->exit_int_info = from->exit_int_info; to->exit_int_info = from->exit_int_info;
@ -747,8 +745,8 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm,
enter_guest_mode(vcpu); enter_guest_mode(vcpu);
/* /*
* Filled at exit: exit_code, exit_code_hi, exit_info_1, exit_info_2, * Filled at exit: exit_code, exit_info_1, exit_info_2, exit_int_info,
* exit_int_info, exit_int_info_err, next_rip, insn_len, insn_bytes. * exit_int_info_err, next_rip, insn_len, insn_bytes.
*/ */
if (guest_cpu_cap_has(vcpu, X86_FEATURE_VGIF) && if (guest_cpu_cap_has(vcpu, X86_FEATURE_VGIF) &&
@ -1018,7 +1016,6 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu)
if (!nested_vmcb_check_save(vcpu) || if (!nested_vmcb_check_save(vcpu) ||
!nested_vmcb_check_controls(vcpu)) { !nested_vmcb_check_controls(vcpu)) {
vmcb12->control.exit_code = SVM_EXIT_ERR; vmcb12->control.exit_code = SVM_EXIT_ERR;
vmcb12->control.exit_code_hi = -1u;
vmcb12->control.exit_info_1 = 0; vmcb12->control.exit_info_1 = 0;
vmcb12->control.exit_info_2 = 0; vmcb12->control.exit_info_2 = 0;
goto out; goto out;
@ -1051,7 +1048,6 @@ out_exit_err:
svm->soft_int_injected = false; svm->soft_int_injected = false;
svm->vmcb->control.exit_code = SVM_EXIT_ERR; svm->vmcb->control.exit_code = SVM_EXIT_ERR;
svm->vmcb->control.exit_code_hi = -1u;
svm->vmcb->control.exit_info_1 = 0; svm->vmcb->control.exit_info_1 = 0;
svm->vmcb->control.exit_info_2 = 0; svm->vmcb->control.exit_info_2 = 0;
@ -1163,7 +1159,6 @@ int nested_svm_vmexit(struct vcpu_svm *svm)
vmcb12->control.int_state = vmcb02->control.int_state; vmcb12->control.int_state = vmcb02->control.int_state;
vmcb12->control.exit_code = vmcb02->control.exit_code; vmcb12->control.exit_code = vmcb02->control.exit_code;
vmcb12->control.exit_code_hi = vmcb02->control.exit_code_hi;
vmcb12->control.exit_info_1 = vmcb02->control.exit_info_1; vmcb12->control.exit_info_1 = vmcb02->control.exit_info_1;
vmcb12->control.exit_info_2 = vmcb02->control.exit_info_2; vmcb12->control.exit_info_2 = vmcb02->control.exit_info_2;
@ -1460,7 +1455,7 @@ static int nested_svm_intercept_ioio(struct vcpu_svm *svm)
static int nested_svm_intercept(struct vcpu_svm *svm) static int nested_svm_intercept(struct vcpu_svm *svm)
{ {
u32 exit_code = svm->vmcb->control.exit_code; u64 exit_code = svm->vmcb->control.exit_code;
int vmexit = NESTED_EXIT_HOST; int vmexit = NESTED_EXIT_HOST;
if (svm_is_vmrun_failure(exit_code)) if (svm_is_vmrun_failure(exit_code))
@ -1532,7 +1527,6 @@ static void nested_svm_inject_exception_vmexit(struct kvm_vcpu *vcpu)
struct vmcb *vmcb = svm->vmcb; struct vmcb *vmcb = svm->vmcb;
vmcb->control.exit_code = SVM_EXIT_EXCP_BASE + ex->vector; vmcb->control.exit_code = SVM_EXIT_EXCP_BASE + ex->vector;
vmcb->control.exit_code_hi = 0;
if (ex->has_error_code) if (ex->has_error_code)
vmcb->control.exit_info_1 = ex->error_code; vmcb->control.exit_info_1 = ex->error_code;
@ -1708,7 +1702,6 @@ static void nested_copy_vmcb_cache_to_control(struct vmcb_control_area *dst,
dst->int_vector = from->int_vector; dst->int_vector = from->int_vector;
dst->int_state = from->int_state; dst->int_state = from->int_state;
dst->exit_code = from->exit_code; dst->exit_code = from->exit_code;
dst->exit_code_hi = from->exit_code_hi;
dst->exit_info_1 = from->exit_info_1; dst->exit_info_1 = from->exit_info_1;
dst->exit_info_2 = from->exit_info_2; dst->exit_info_2 = from->exit_info_2;
dst->exit_int_info = from->exit_int_info; dst->exit_int_info = from->exit_int_info;

View File

@ -3270,11 +3270,6 @@ skip_vmsa_free:
kvfree(svm->sev_es.ghcb_sa); kvfree(svm->sev_es.ghcb_sa);
} }
static u64 kvm_get_cached_sw_exit_code(struct vmcb_control_area *control)
{
return (((u64)control->exit_code_hi) << 32) | control->exit_code;
}
static void dump_ghcb(struct vcpu_svm *svm) static void dump_ghcb(struct vcpu_svm *svm)
{ {
struct vmcb_control_area *control = &svm->vmcb->control; struct vmcb_control_area *control = &svm->vmcb->control;
@ -3296,7 +3291,7 @@ static void dump_ghcb(struct vcpu_svm *svm)
*/ */
pr_err("GHCB (GPA=%016llx) snapshot:\n", svm->vmcb->control.ghcb_gpa); pr_err("GHCB (GPA=%016llx) snapshot:\n", svm->vmcb->control.ghcb_gpa);
pr_err("%-20s%016llx is_valid: %u\n", "sw_exit_code", pr_err("%-20s%016llx is_valid: %u\n", "sw_exit_code",
kvm_get_cached_sw_exit_code(control), kvm_ghcb_sw_exit_code_is_valid(svm)); control->exit_code, kvm_ghcb_sw_exit_code_is_valid(svm));
pr_err("%-20s%016llx is_valid: %u\n", "sw_exit_info_1", pr_err("%-20s%016llx is_valid: %u\n", "sw_exit_info_1",
control->exit_info_1, kvm_ghcb_sw_exit_info_1_is_valid(svm)); control->exit_info_1, kvm_ghcb_sw_exit_info_1_is_valid(svm));
pr_err("%-20s%016llx is_valid: %u\n", "sw_exit_info_2", pr_err("%-20s%016llx is_valid: %u\n", "sw_exit_info_2",
@ -3330,7 +3325,6 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm)
struct vmcb_control_area *control = &svm->vmcb->control; struct vmcb_control_area *control = &svm->vmcb->control;
struct kvm_vcpu *vcpu = &svm->vcpu; struct kvm_vcpu *vcpu = &svm->vcpu;
struct ghcb *ghcb = svm->sev_es.ghcb; struct ghcb *ghcb = svm->sev_es.ghcb;
u64 exit_code;
/* /*
* The GHCB protocol so far allows for the following data * The GHCB protocol so far allows for the following data
@ -3364,9 +3358,7 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm)
__kvm_emulate_msr_write(vcpu, MSR_IA32_XSS, kvm_ghcb_get_xss(svm)); __kvm_emulate_msr_write(vcpu, MSR_IA32_XSS, kvm_ghcb_get_xss(svm));
/* Copy the GHCB exit information into the VMCB fields */ /* Copy the GHCB exit information into the VMCB fields */
exit_code = kvm_ghcb_get_sw_exit_code(svm); control->exit_code = kvm_ghcb_get_sw_exit_code(svm);
control->exit_code = lower_32_bits(exit_code);
control->exit_code_hi = upper_32_bits(exit_code);
control->exit_info_1 = kvm_ghcb_get_sw_exit_info_1(svm); control->exit_info_1 = kvm_ghcb_get_sw_exit_info_1(svm);
control->exit_info_2 = kvm_ghcb_get_sw_exit_info_2(svm); control->exit_info_2 = kvm_ghcb_get_sw_exit_info_2(svm);
svm->sev_es.sw_scratch = kvm_ghcb_get_sw_scratch_if_valid(svm); svm->sev_es.sw_scratch = kvm_ghcb_get_sw_scratch_if_valid(svm);
@ -3379,15 +3371,8 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
{ {
struct vmcb_control_area *control = &svm->vmcb->control; struct vmcb_control_area *control = &svm->vmcb->control;
struct kvm_vcpu *vcpu = &svm->vcpu; struct kvm_vcpu *vcpu = &svm->vcpu;
u64 exit_code;
u64 reason; u64 reason;
/*
* Retrieve the exit code now even though it may not be marked valid
* as it could help with debugging.
*/
exit_code = kvm_get_cached_sw_exit_code(control);
/* Only GHCB Usage code 0 is supported */ /* Only GHCB Usage code 0 is supported */
if (svm->sev_es.ghcb->ghcb_usage) { if (svm->sev_es.ghcb->ghcb_usage) {
reason = GHCB_ERR_INVALID_USAGE; reason = GHCB_ERR_INVALID_USAGE;
@ -3401,7 +3386,7 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
!kvm_ghcb_sw_exit_info_2_is_valid(svm)) !kvm_ghcb_sw_exit_info_2_is_valid(svm))
goto vmgexit_err; goto vmgexit_err;
switch (exit_code) { switch (control->exit_code) {
case SVM_EXIT_READ_DR7: case SVM_EXIT_READ_DR7:
break; break;
case SVM_EXIT_WRITE_DR7: case SVM_EXIT_WRITE_DR7:
@ -3502,15 +3487,19 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
return 0; return 0;
vmgexit_err: vmgexit_err:
/*
* Print the exit code even though it may not be marked valid as it
* could help with debugging.
*/
if (reason == GHCB_ERR_INVALID_USAGE) { if (reason == GHCB_ERR_INVALID_USAGE) {
vcpu_unimpl(vcpu, "vmgexit: ghcb usage %#x is not valid\n", vcpu_unimpl(vcpu, "vmgexit: ghcb usage %#x is not valid\n",
svm->sev_es.ghcb->ghcb_usage); svm->sev_es.ghcb->ghcb_usage);
} else if (reason == GHCB_ERR_INVALID_EVENT) { } else if (reason == GHCB_ERR_INVALID_EVENT) {
vcpu_unimpl(vcpu, "vmgexit: exit code %#llx is not valid\n", vcpu_unimpl(vcpu, "vmgexit: exit code %#llx is not valid\n",
exit_code); control->exit_code);
} else { } else {
vcpu_unimpl(vcpu, "vmgexit: exit code %#llx input is not valid\n", vcpu_unimpl(vcpu, "vmgexit: exit code %#llx input is not valid\n",
exit_code); control->exit_code);
dump_ghcb(svm); dump_ghcb(svm);
} }
@ -4349,7 +4338,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
{ {
struct vcpu_svm *svm = to_svm(vcpu); struct vcpu_svm *svm = to_svm(vcpu);
struct vmcb_control_area *control = &svm->vmcb->control; struct vmcb_control_area *control = &svm->vmcb->control;
u64 ghcb_gpa, exit_code; u64 ghcb_gpa;
int ret; int ret;
/* Validate the GHCB */ /* Validate the GHCB */
@ -4391,8 +4380,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
svm_vmgexit_success(svm, 0); svm_vmgexit_success(svm, 0);
exit_code = kvm_get_cached_sw_exit_code(control); switch (control->exit_code) {
switch (exit_code) {
case SVM_VMGEXIT_MMIO_READ: case SVM_VMGEXIT_MMIO_READ:
ret = setup_vmgexit_scratch(svm, true, control->exit_info_2); ret = setup_vmgexit_scratch(svm, true, control->exit_info_2);
if (ret) if (ret)
@ -4484,7 +4472,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
ret = -EINVAL; ret = -EINVAL;
break; break;
default: default:
ret = svm_invoke_exit_handler(vcpu, exit_code); ret = svm_invoke_exit_handler(vcpu, control->exit_code);
} }
return ret; return ret;

View File

@ -2466,7 +2466,6 @@ static bool check_selective_cr0_intercepted(struct kvm_vcpu *vcpu,
if (cr0 ^ val) { if (cr0 ^ val) {
svm->vmcb->control.exit_code = SVM_EXIT_CR0_SEL_WRITE; svm->vmcb->control.exit_code = SVM_EXIT_CR0_SEL_WRITE;
svm->vmcb->control.exit_code_hi = 0;
ret = (nested_svm_exit_handled(svm) == NESTED_EXIT_DONE); ret = (nested_svm_exit_handled(svm) == NESTED_EXIT_DONE);
} }
@ -3299,7 +3298,7 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
pr_err("%-20s%08x\n", "int_ctl:", control->int_ctl); pr_err("%-20s%08x\n", "int_ctl:", control->int_ctl);
pr_err("%-20s%08x\n", "int_vector:", control->int_vector); pr_err("%-20s%08x\n", "int_vector:", control->int_vector);
pr_err("%-20s%08x\n", "int_state:", control->int_state); pr_err("%-20s%08x\n", "int_state:", control->int_state);
pr_err("%-20s%08x\n", "exit_code:", control->exit_code); pr_err("%-20s%016llx\n", "exit_code:", control->exit_code);
pr_err("%-20s%016llx\n", "exit_info1:", control->exit_info_1); pr_err("%-20s%016llx\n", "exit_info1:", control->exit_info_1);
pr_err("%-20s%016llx\n", "exit_info2:", control->exit_info_2); pr_err("%-20s%016llx\n", "exit_info2:", control->exit_info_2);
pr_err("%-20s%08x\n", "exit_int_info:", control->exit_int_info); pr_err("%-20s%08x\n", "exit_int_info:", control->exit_int_info);
@ -3549,7 +3548,6 @@ static int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
{ {
struct vcpu_svm *svm = to_svm(vcpu); struct vcpu_svm *svm = to_svm(vcpu);
struct kvm_run *kvm_run = vcpu->run; struct kvm_run *kvm_run = vcpu->run;
u32 exit_code = svm->vmcb->control.exit_code;
/* SEV-ES guests must use the CR write traps to track CR registers. */ /* SEV-ES guests must use the CR write traps to track CR registers. */
if (!sev_es_guest(vcpu->kvm)) { if (!sev_es_guest(vcpu->kvm)) {
@ -3585,7 +3583,7 @@ static int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
if (exit_fastpath != EXIT_FASTPATH_NONE) if (exit_fastpath != EXIT_FASTPATH_NONE)
return 1; return 1;
return svm_invoke_exit_handler(vcpu, exit_code); return svm_invoke_exit_handler(vcpu, svm->vmcb->control.exit_code);
} }
static int pre_svm_run(struct kvm_vcpu *vcpu) static int pre_svm_run(struct kvm_vcpu *vcpu)
@ -4670,7 +4668,6 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,
if (static_cpu_has(X86_FEATURE_NRIPS)) if (static_cpu_has(X86_FEATURE_NRIPS))
vmcb->control.next_rip = info->next_rip; vmcb->control.next_rip = info->next_rip;
vmcb->control.exit_code = icpt_info.exit_code; vmcb->control.exit_code = icpt_info.exit_code;
vmcb->control.exit_code_hi = 0;
vmexit = nested_svm_exit_handled(svm); vmexit = nested_svm_exit_handled(svm);
ret = (vmexit == NESTED_EXIT_DONE) ? X86EMUL_INTERCEPTED ret = (vmexit == NESTED_EXIT_DONE) ? X86EMUL_INTERCEPTED

View File

@ -160,8 +160,7 @@ struct vmcb_ctrl_area_cached {
u32 int_ctl; u32 int_ctl;
u32 int_vector; u32 int_vector;
u32 int_state; u32 int_state;
u32 exit_code; u64 exit_code;
u32 exit_code_hi;
u64 exit_info_1; u64 exit_info_1;
u64 exit_info_2; u64 exit_info_2;
u32 exit_int_info; u32 exit_int_info;
@ -787,7 +786,6 @@ int nested_svm_vmexit(struct vcpu_svm *svm);
static inline int nested_svm_simple_vmexit(struct vcpu_svm *svm, u32 exit_code) static inline int nested_svm_simple_vmexit(struct vcpu_svm *svm, u32 exit_code)
{ {
svm->vmcb->control.exit_code = exit_code; svm->vmcb->control.exit_code = exit_code;
svm->vmcb->control.exit_code_hi = 0;
svm->vmcb->control.exit_info_1 = 0; svm->vmcb->control.exit_info_1 = 0;
svm->vmcb->control.exit_info_2 = 0; svm->vmcb->control.exit_info_2 = 0;
return nested_svm_vmexit(svm); return nested_svm_vmexit(svm);

View File

@ -383,10 +383,10 @@ TRACE_EVENT(kvm_apic,
#define kvm_print_exit_reason(exit_reason, isa) \ #define kvm_print_exit_reason(exit_reason, isa) \
(isa == KVM_ISA_VMX) ? \ (isa == KVM_ISA_VMX) ? \
__print_symbolic(exit_reason & 0xffff, VMX_EXIT_REASONS) : \ __print_symbolic(exit_reason & 0xffff, VMX_EXIT_REASONS) : \
__print_symbolic(exit_reason, SVM_EXIT_REASONS), \ __print_symbolic_u64(exit_reason, SVM_EXIT_REASONS), \
(isa == KVM_ISA_VMX && exit_reason & ~0xffff) ? " " : "", \ (isa == KVM_ISA_VMX && exit_reason & ~0xffff) ? " " : "", \
(isa == KVM_ISA_VMX) ? \ (isa == KVM_ISA_VMX) ? \
__print_flags(exit_reason & ~0xffff, " ", VMX_EXIT_REASON_FLAGS) : "" __print_flags_u64(exit_reason & ~0xffff, " ", VMX_EXIT_REASON_FLAGS) : ""
#define TRACE_EVENT_KVM_EXIT(name) \ #define TRACE_EVENT_KVM_EXIT(name) \
TRACE_EVENT(name, \ TRACE_EVENT(name, \
@ -781,7 +781,7 @@ TRACE_EVENT_KVM_EXIT(kvm_nested_vmexit);
* Tracepoint for #VMEXIT reinjected to the guest * Tracepoint for #VMEXIT reinjected to the guest
*/ */
TRACE_EVENT(kvm_nested_vmexit_inject, TRACE_EVENT(kvm_nested_vmexit_inject,
TP_PROTO(__u32 exit_code, TP_PROTO(__u64 exit_code,
__u64 exit_info1, __u64 exit_info2, __u64 exit_info1, __u64 exit_info2,
__u32 exit_int_info, __u32 exit_int_info_err, __u32 isa), __u32 exit_int_info, __u32 exit_int_info_err, __u32 isa),
TP_ARGS(exit_code, exit_info1, exit_info2, TP_ARGS(exit_code, exit_info1, exit_info2,

View File

@ -281,7 +281,7 @@ struct hv_vmcb_enlightenments {
#define HV_VMCB_NESTED_ENLIGHTENMENTS 31 #define HV_VMCB_NESTED_ENLIGHTENMENTS 31
/* Synthetic VM-Exit */ /* Synthetic VM-Exit */
#define HV_SVM_EXITCODE_ENL 0xf0000000 #define HV_SVM_EXITCODE_ENL 0xf0000000ull
#define HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH (1) #define HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH (1)
/* VM_PARTITION_ASSIST_PAGE */ /* VM_PARTITION_ASSIST_PAGE */

View File

@ -92,8 +92,7 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
u32 int_vector; u32 int_vector;
u32 int_state; u32 int_state;
u8 reserved_3[4]; u8 reserved_3[4];
u32 exit_code; u64 exit_code;
u32 exit_code_hi;
u64 exit_info_1; u64 exit_info_1;
u64 exit_info_2; u64 exit_info_2;
u32 exit_int_info; u32 exit_int_info;

View File

@ -103,7 +103,7 @@ static void l1_guest_code(struct svm_test_data *svm, uint64_t is_nmi, uint64_t i
run_guest(vmcb, svm->vmcb_gpa); run_guest(vmcb, svm->vmcb_gpa);
__GUEST_ASSERT(vmcb->control.exit_code == SVM_EXIT_VMMCALL, __GUEST_ASSERT(vmcb->control.exit_code == SVM_EXIT_VMMCALL,
"Expected VMMCAL #VMEXIT, got '0x%x', info1 = '0x%lx, info2 = '0x%lx'", "Expected VMMCAL #VMEXIT, got '0x%lx', info1 = '0x%lx, info2 = '0x%lx'",
vmcb->control.exit_code, vmcb->control.exit_code,
vmcb->control.exit_info_1, vmcb->control.exit_info_2); vmcb->control.exit_info_1, vmcb->control.exit_info_2);
@ -133,7 +133,7 @@ static void l1_guest_code(struct svm_test_data *svm, uint64_t is_nmi, uint64_t i
run_guest(vmcb, svm->vmcb_gpa); run_guest(vmcb, svm->vmcb_gpa);
__GUEST_ASSERT(vmcb->control.exit_code == SVM_EXIT_HLT, __GUEST_ASSERT(vmcb->control.exit_code == SVM_EXIT_HLT,
"Expected HLT #VMEXIT, got '0x%x', info1 = '0x%lx, info2 = '0x%lx'", "Expected HLT #VMEXIT, got '0x%lx', info1 = '0x%lx, info2 = '0x%lx'",
vmcb->control.exit_code, vmcb->control.exit_code,
vmcb->control.exit_info_1, vmcb->control.exit_info_2); vmcb->control.exit_info_1, vmcb->control.exit_info_2);