lkml.org 
[lkml]   [2009]   [Nov]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 39/42] KVM: SVM: Move INTR vmexit out of atomic code
    Date
    From: Joerg Roedel <joerg.roedel@amd.com>

    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>
    ---
    arch/x86/kvm/svm.c | 26 +++++++++++++++++++++++++-
    1 files changed, 25 insertions(+), 1 deletions(-)

    diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
    index e372854..884bffc 100644
    --- a/arch/x86/kvm/svm.c
    +++ b/arch/x86/kvm/svm.c
    @@ -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];
    --
    1.6.5.2


    \
     
     \ /
      Last update: 2009-11-16 13:55    [W:0.022 / U:31.316 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site