Skip to content

Commit

Permalink
KVM: Fix mmu_reload() clash with nested vmx event injection
Browse files Browse the repository at this point in the history
Currently the inject_pending_event() call during guest entry happens after
kvm_mmu_reload().  This is for historical reasons - we used to
inject_pending_event() in atomic context, while kvm_mmu_reload() needs task
context.

A problem is that nested vmx can cause the mmu context to be reset, if event
injection is intercepted and causes a #VMEXIT instead (the #VMEXIT resets
CR0/CR3/CR4).  If this happens, we end up with invalid root_hpa, and since
kvm_mmu_reload() has already run, no one will fix it and we end up entering
the guest this way.

Fix by reordering event injection to be before kvm_mmu_reload().  Use
->cancel_injection() to undo if kvm_mmu_reload() fails.

https://bugzilla.kernel.org/show_bug.cgi?id=42980

Reported-by: Luke-Jr <luke-jr+linuxbugs@utopios.org>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
  • Loading branch information
Avi Kivity authored and Marcelo Tosatti committed May 16, 2012
1 parent c142786 commit d8368af
Showing 1 changed file with 6 additions and 4 deletions.
10 changes: 6 additions & 4 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -5279,10 +5279,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
kvm_deliver_pmi(vcpu);
}

r = kvm_mmu_reload(vcpu);
if (unlikely(r))
goto out;

if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
inject_pending_event(vcpu);

Expand All @@ -5298,6 +5294,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
}
}

r = kvm_mmu_reload(vcpu);
if (unlikely(r)) {
kvm_x86_ops->cancel_injection(vcpu);
goto out;
}

preempt_disable();

kvm_x86_ops->prepare_guest_switch(vcpu);
Expand Down

0 comments on commit d8368af

Please sign in to comment.