diff options
author | Liran Alon <liran.alon@oracle.com> | 2017-11-05 09:07:43 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-11-17 07:20:21 -0500 |
commit | 917dc6068bc12a2dafffcf0e9d405ddb1b8780cb (patch) | |
tree | 972686a72e84b17b4cb6f46b238e8466756a2765 | |
parent | b200dded0a6974a3b69599832b2203483920ab25 (diff) |
KVM: nVMX: Fix vmx_check_nested_events() return value in case an event was reinjected to L2
vmx_check_nested_events() should return -EBUSY only in case there is a
pending L1 event which requires a VMExit from L2 to L1 but such a
VMExit is currently blocked. Such VMExits are blocked either
because nested_run_pending=1 or an event was reinjected to L2.
vmx_check_nested_events() should return 0 in case there are no
pending L1 events which requires a VMExit from L2 to L1 or if
a VMExit from L2 to L1 was done internally.
However, upstream commit which introduced blocking in case an event was
reinjected to L2 (commit acc9ab601327 ("KVM: nVMX: Fix pending events
injection")) contains a bug: It returns -EBUSY even if there are no
pending L1 events which requires VMExit from L2 to L1.
This commit fix this issue.
Fixes: acc9ab601327 ("KVM: nVMX: Fix pending events injection")
Signed-off-by: Liran Alon <liran.alon@oracle.com>
Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
-rw-r--r-- | arch/x86/kvm/vmx.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 10474d26a000..be4724b5d434 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -11105,13 +11105,12 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr) | |||
11105 | { | 11105 | { |
11106 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 11106 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
11107 | unsigned long exit_qual; | 11107 | unsigned long exit_qual; |
11108 | 11108 | bool block_nested_events = | |
11109 | if (kvm_event_needs_reinjection(vcpu)) | 11109 | vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu); |
11110 | return -EBUSY; | ||
11111 | 11110 | ||
11112 | if (vcpu->arch.exception.pending && | 11111 | if (vcpu->arch.exception.pending && |
11113 | nested_vmx_check_exception(vcpu, &exit_qual)) { | 11112 | nested_vmx_check_exception(vcpu, &exit_qual)) { |
11114 | if (vmx->nested.nested_run_pending) | 11113 | if (block_nested_events) |
11115 | return -EBUSY; | 11114 | return -EBUSY; |
11116 | nested_vmx_inject_exception_vmexit(vcpu, exit_qual); | 11115 | nested_vmx_inject_exception_vmexit(vcpu, exit_qual); |
11117 | vcpu->arch.exception.pending = false; | 11116 | vcpu->arch.exception.pending = false; |
@@ -11120,14 +11119,14 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr) | |||
11120 | 11119 | ||
11121 | if (nested_cpu_has_preemption_timer(get_vmcs12(vcpu)) && | 11120 | if (nested_cpu_has_preemption_timer(get_vmcs12(vcpu)) && |
11122 | vmx->nested.preemption_timer_expired) { | 11121 | vmx->nested.preemption_timer_expired) { |
11123 | if (vmx->nested.nested_run_pending) | 11122 | if (block_nested_events) |
11124 | return -EBUSY; | 11123 | return -EBUSY; |
11125 | nested_vmx_vmexit(vcpu, EXIT_REASON_PREEMPTION_TIMER, 0, 0); | 11124 | nested_vmx_vmexit(vcpu, EXIT_REASON_PREEMPTION_TIMER, 0, 0); |
11126 | return 0; | 11125 | return 0; |
11127 | } | 11126 | } |
11128 | 11127 | ||
11129 | if (vcpu->arch.nmi_pending && nested_exit_on_nmi(vcpu)) { | 11128 | if (vcpu->arch.nmi_pending && nested_exit_on_nmi(vcpu)) { |
11130 | if (vmx->nested.nested_run_pending) | 11129 | if (block_nested_events) |
11131 | return -EBUSY; | 11130 | return -EBUSY; |
11132 | nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI, | 11131 | nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI, |
11133 | NMI_VECTOR | INTR_TYPE_NMI_INTR | | 11132 | NMI_VECTOR | INTR_TYPE_NMI_INTR | |
@@ -11143,7 +11142,7 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr) | |||
11143 | 11142 | ||
11144 | if ((kvm_cpu_has_interrupt(vcpu) || external_intr) && | 11143 | if ((kvm_cpu_has_interrupt(vcpu) || external_intr) && |
11145 | nested_exit_on_intr(vcpu)) { | 11144 | nested_exit_on_intr(vcpu)) { |
11146 | if (vmx->nested.nested_run_pending) | 11145 | if (block_nested_events) |
11147 | return -EBUSY; | 11146 | return -EBUSY; |
11148 | nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, 0, 0); | 11147 | nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, 0, 0); |
11149 | return 0; | 11148 | return 0; |