Skip to content

Commit 7313c69

Browse files
bonzinirkrcmar
authored andcommitted
KVM: nVMX: do not fill vm_exit_intr_error_code in prepare_vmcs12
Do this in the caller of nested_vmx_vmexit instead. nested_vmx_check_exception was doing a vmwrite to the vmcs02's VM_EXIT_INTR_ERROR_CODE field, so that prepare_vmcs12 would move the field to vmcs12->vm_exit_intr_error_code. However that isn't possible on pre-Haswell machines. Moving the vmcs12 write to the callers fixes it. Reported-by: Jim Mattson <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]> [Changed nested_vmx_reflect_vmexit() return type to (int)1 from (bool)1, thanks to [email protected]] Signed-off-by: Radim Krčmář <[email protected]>
1 parent 16f73eb commit 7313c69

File tree

1 file changed

+34
-18
lines changed

1 file changed

+34
-18
lines changed

arch/x86/kvm/vmx.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2442,14 +2442,15 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu)
24422442
return 0;
24432443

24442444
if (vcpu->arch.exception.nested_apf) {
2445-
vmcs_write32(VM_EXIT_INTR_ERROR_CODE, vcpu->arch.exception.error_code);
2445+
vmcs12->vm_exit_intr_error_code = vcpu->arch.exception.error_code;
24462446
nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
24472447
PF_VECTOR | INTR_TYPE_HARD_EXCEPTION |
24482448
INTR_INFO_DELIVER_CODE_MASK | INTR_INFO_VALID_MASK,
24492449
vcpu->arch.apf.nested_apf_token);
24502450
return 1;
24512451
}
24522452

2453+
vmcs12->vm_exit_intr_error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
24532454
nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
24542455
vmcs_read32(VM_EXIT_INTR_INFO),
24552456
vmcs_readl(EXIT_QUALIFICATION));
@@ -2667,7 +2668,7 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
26672668
* reason is that if one of these bits is necessary, it will appear
26682669
* in vmcs01 and prepare_vmcs02, when it bitwise-or's the control
26692670
* fields of vmcs01 and vmcs02, will turn these bits off - and
2670-
* nested_vmx_exit_handled() will not pass related exits to L1.
2671+
* nested_vmx_exit_reflected() will not pass related exits to L1.
26712672
* These rules have exceptions below.
26722673
*/
26732674

@@ -8019,12 +8020,11 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
80198020
* should handle it ourselves in L0 (and then continue L2). Only call this
80208021
* when in is_guest_mode (L2).
80218022
*/
8022-
static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
8023+
static bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
80238024
{
80248025
u32 intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
80258026
struct vcpu_vmx *vmx = to_vmx(vcpu);
80268027
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
8027-
u32 exit_reason = vmx->exit_reason;
80288028

80298029
trace_kvm_nested_vmexit(kvm_rip_read(vcpu), exit_reason,
80308030
vmcs_readl(EXIT_QUALIFICATION),
@@ -8169,6 +8169,29 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
81698169
}
81708170
}
81718171

8172+
static int nested_vmx_reflect_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason)
8173+
{
8174+
u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
8175+
8176+
/*
8177+
* At this point, the exit interruption info in exit_intr_info
8178+
* is only valid for EXCEPTION_NMI exits. For EXTERNAL_INTERRUPT
8179+
* we need to query the in-kernel LAPIC.
8180+
*/
8181+
WARN_ON(exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT);
8182+
if ((exit_intr_info &
8183+
(INTR_INFO_VALID_MASK | INTR_INFO_DELIVER_CODE_MASK)) ==
8184+
(INTR_INFO_VALID_MASK | INTR_INFO_DELIVER_CODE_MASK)) {
8185+
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
8186+
vmcs12->vm_exit_intr_error_code =
8187+
vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
8188+
}
8189+
8190+
nested_vmx_vmexit(vcpu, exit_reason, exit_intr_info,
8191+
vmcs_readl(EXIT_QUALIFICATION));
8192+
return 1;
8193+
}
8194+
81728195
static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
81738196
{
81748197
*info1 = vmcs_readl(EXIT_QUALIFICATION);
@@ -8415,12 +8438,8 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
84158438
if (vmx->emulation_required)
84168439
return handle_invalid_guest_state(vcpu);
84178440

8418-
if (is_guest_mode(vcpu) && nested_vmx_exit_handled(vcpu)) {
8419-
nested_vmx_vmexit(vcpu, exit_reason,
8420-
vmcs_read32(VM_EXIT_INTR_INFO),
8421-
vmcs_readl(EXIT_QUALIFICATION));
8422-
return 1;
8423-
}
8441+
if (is_guest_mode(vcpu) && nested_vmx_exit_reflected(vcpu, exit_reason))
8442+
return nested_vmx_reflect_vmexit(vcpu, exit_reason);
84248443

84258444
if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
84268445
dump_vmcs();
@@ -9509,12 +9528,14 @@ static void vmx_inject_page_fault_nested(struct kvm_vcpu *vcpu,
95099528

95109529
WARN_ON(!is_guest_mode(vcpu));
95119530

9512-
if (nested_vmx_is_page_fault_vmexit(vmcs12, fault->error_code))
9531+
if (nested_vmx_is_page_fault_vmexit(vmcs12, fault->error_code)) {
9532+
vmcs12->vm_exit_intr_error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
95139533
nested_vmx_vmexit(vcpu, to_vmx(vcpu)->exit_reason,
95149534
vmcs_read32(VM_EXIT_INTR_INFO),
95159535
vmcs_readl(EXIT_QUALIFICATION));
9516-
else
9536+
} else {
95179537
kvm_inject_page_fault(vcpu, fault);
9538+
}
95189539
}
95199540

95209541
static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
@@ -10847,13 +10868,8 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
1084710868

1084810869
vmcs12->vm_exit_reason = exit_reason;
1084910870
vmcs12->exit_qualification = exit_qualification;
10850-
1085110871
vmcs12->vm_exit_intr_info = exit_intr_info;
10852-
if ((vmcs12->vm_exit_intr_info &
10853-
(INTR_INFO_VALID_MASK | INTR_INFO_DELIVER_CODE_MASK)) ==
10854-
(INTR_INFO_VALID_MASK | INTR_INFO_DELIVER_CODE_MASK))
10855-
vmcs12->vm_exit_intr_error_code =
10856-
vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
10872+
1085710873
vmcs12->idt_vectoring_info_field = 0;
1085810874
vmcs12->vm_exit_instruction_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
1085910875
vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);

0 commit comments

Comments
 (0)