lkml.org 
[lkml]   [2009]   [Nov]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 12/35] KVM: x86: Fix guest single-stepping while interruptible
    Date
    From: Jan Kiszka <jan.kiszka@web.de>

    Commit 705c5323 opened the doors of hell by unconditionally injecting
    single-step flags as long as guest_debug signaled this. This doesn't
    work when the guest branches into some interrupt or exception handler
    and triggers a vmexit with flag reloading.

    Fix it by saving cs:rip when user space requests single-stepping and
    restricting the trace flag injection to this guest code position.

    Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
    ---
    arch/x86/include/asm/kvm_host.h | 4 +++
    arch/x86/kvm/x86.c | 47 +++++++++++++++++++++++---------------
    2 files changed, 32 insertions(+), 19 deletions(-)

    diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
    index 36f3b53..2536fbd 100644
    --- a/arch/x86/include/asm/kvm_host.h
    +++ b/arch/x86/include/asm/kvm_host.h
    @@ -371,6 +371,10 @@ struct kvm_vcpu_arch {
    u64 mcg_status;
    u64 mcg_ctl;
    u64 *mce_banks;
    +
    + /* used for guest single stepping over the given code position */
    + u16 singlestep_cs;
    + unsigned long singlestep_rip;
    };

    struct kvm_mem_alias {
    diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
    index bb842db..13f30aa 100644
    --- a/arch/x86/kvm/x86.c
    +++ b/arch/x86/kvm/x86.c
    @@ -235,25 +235,6 @@ bool kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl)
    }
    EXPORT_SYMBOL_GPL(kvm_require_cpl);

    -unsigned long kvm_get_rflags(struct kvm_vcpu *vcpu)
    -{
    - unsigned long rflags;
    -
    - rflags = kvm_x86_ops->get_rflags(vcpu);
    - if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
    - rflags &= ~(unsigned long)(X86_EFLAGS_TF | X86_EFLAGS_RF);
    - return rflags;
    -}
    -EXPORT_SYMBOL_GPL(kvm_get_rflags);
    -
    -void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
    -{
    - if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
    - rflags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
    - kvm_x86_ops->set_rflags(vcpu, rflags);
    -}
    -EXPORT_SYMBOL_GPL(kvm_set_rflags);
    -
    /*
    * Load the pae pdptrs. Return true is they are all valid.
    */
    @@ -4565,6 +4546,12 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
    vcpu->arch.switch_db_regs = (vcpu->arch.dr7 & DR7_BP_EN_MASK);
    }

    + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
    + vcpu->arch.singlestep_cs =
    + get_segment_selector(vcpu, VCPU_SREG_CS);
    + vcpu->arch.singlestep_rip = kvm_rip_read(vcpu);
    + }
    +
    /*
    * Trigger an rflags update that will inject or remove the trace
    * flags.
    @@ -5031,6 +5018,28 @@ int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu)
    return kvm_x86_ops->interrupt_allowed(vcpu);
    }

    +unsigned long kvm_get_rflags(struct kvm_vcpu *vcpu)
    +{
    + unsigned long rflags;
    +
    + rflags = kvm_x86_ops->get_rflags(vcpu);
    + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
    + rflags &= ~(unsigned long)(X86_EFLAGS_TF | X86_EFLAGS_RF);
    + return rflags;
    +}
    +EXPORT_SYMBOL_GPL(kvm_get_rflags);
    +
    +void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
    +{
    + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP &&
    + vcpu->arch.singlestep_cs ==
    + get_segment_selector(vcpu, VCPU_SREG_CS) &&
    + vcpu->arch.singlestep_rip == kvm_rip_read(vcpu))
    + rflags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
    + kvm_x86_ops->set_rflags(vcpu, rflags);
    +}
    +EXPORT_SYMBOL_GPL(kvm_set_rflags);
    +
    EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_exit);
    EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_inj_virq);
    EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_page_fault);
    --
    1.6.5.2


    \
     
     \ /
      Last update: 2009-11-19 14:47    [W:4.109 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site