mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-11-07 04:09:21 +00:00
KVM: SVM: Move INTR vmexit out of atomic code
The nested SVM code emulates a #vmexit caused by a request to open the irq window right in the request function. This is a bug because the request function runs with preemption and interrupts disabled but the #vmexit emulation might sleep. This can cause a schedule()-while-atomic bug and is fixed with this patch. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
This commit is contained in:
parent
8d23c46624
commit
cd3ff653ae
1 changed files with 25 additions and 1 deletions
|
@ -85,6 +85,9 @@ struct nested_state {
|
|||
/* gpa pointers to the real vectors */
|
||||
u64 vmcb_msrpm;
|
||||
|
||||
/* A VMEXIT is required but not yet emulated */
|
||||
bool exit_required;
|
||||
|
||||
/* cache for intercepts of the guest */
|
||||
u16 intercept_cr_read;
|
||||
u16 intercept_cr_write;
|
||||
|
@ -1379,7 +1382,14 @@ static inline int nested_svm_intr(struct vcpu_svm *svm)
|
|||
|
||||
svm->vmcb->control.exit_code = SVM_EXIT_INTR;
|
||||
|
||||
if (nested_svm_exit_handled(svm)) {
|
||||
if (svm->nested.intercept & 1ULL) {
|
||||
/*
|
||||
* The #vmexit can't be emulated here directly because this
|
||||
* code path runs with irqs and preemtion disabled. A
|
||||
* #vmexit emulation might sleep. Only signal request for
|
||||
* the #vmexit here.
|
||||
*/
|
||||
svm->nested.exit_required = true;
|
||||
nsvm_printk("VMexit -> INTR\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -2340,6 +2350,13 @@ static int handle_exit(struct kvm_vcpu *vcpu)
|
|||
|
||||
trace_kvm_exit(exit_code, svm->vmcb->save.rip);
|
||||
|
||||
if (unlikely(svm->nested.exit_required)) {
|
||||
nested_svm_vmexit(svm);
|
||||
svm->nested.exit_required = false;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (is_nested(svm)) {
|
||||
int vmexit;
|
||||
|
||||
|
@ -2615,6 +2632,13 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
|
|||
u16 gs_selector;
|
||||
u16 ldt_selector;
|
||||
|
||||
/*
|
||||
* A vmexit emulation is required before the vcpu can be executed
|
||||
* again.
|
||||
*/
|
||||
if (unlikely(svm->nested.exit_required))
|
||||
return;
|
||||
|
||||
svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
|
||||
svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
|
||||
svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP];
|
||||
|
|
Loading…
Reference in a new issue