lkml.org 
[lkml]   [2009]   [Apr]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 74/88] KVM: x86: fix LAPIC pending count calculation
    2.6.28-stable review patch.  If anyone has any objections, please let us know.

    ------------------


    (cherry picked from b682b814e3cc340f905c14dff87ce8bdba7c5eba)

    Simplify LAPIC TMCCT calculation by using hrtimer provided
    function to query remaining time until expiration.

    Fixes host hang with nested ESX.

    Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
    Signed-off-by: Alexander Graf <agraf@suse.de>
    Signed-off-by: Avi Kivity <avi@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
    ---
    arch/x86/kvm/irq.c | 7 -----
    arch/x86/kvm/irq.h | 1
    arch/x86/kvm/lapic.c | 66 +++++++++++----------------------------------------
    arch/x86/kvm/lapic.h | 2 -
    arch/x86/kvm/svm.c | 1
    arch/x86/kvm/vmx.c | 4 ---
    6 files changed, 16 insertions(+), 65 deletions(-)

    --- a/arch/x86/kvm/irq.c
    +++ b/arch/x86/kvm/irq.c
    @@ -87,13 +87,6 @@ void kvm_inject_pending_timer_irqs(struc
    }
    EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);

    -void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
    -{
    - kvm_apic_timer_intr_post(vcpu, vec);
    - /* TODO: PIT, RTC etc. */
    -}
    -EXPORT_SYMBOL_GPL(kvm_timer_intr_post);
    -
    void __kvm_migrate_timers(struct kvm_vcpu *vcpu)
    {
    __kvm_migrate_apic_timer(vcpu);
    --- a/arch/x86/kvm/irq.h
    +++ b/arch/x86/kvm/irq.h
    @@ -84,7 +84,6 @@ static inline int irqchip_in_kernel(stru

    void kvm_pic_reset(struct kvm_kpic_state *s);

    -void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
    void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
    void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
    void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu);
    --- a/arch/x86/kvm/lapic.c
    +++ b/arch/x86/kvm/lapic.c
    @@ -35,6 +35,12 @@
    #include "kvm_cache_regs.h"
    #include "irq.h"

    +#ifndef CONFIG_X86_64
    +#define mod_64(x, y) ((x) - (y) * div64_u64(x, y))
    +#else
    +#define mod_64(x, y) ((x) % (y))
    +#endif
    +
    #define PRId64 "d"
    #define PRIx64 "llx"
    #define PRIu64 "u"
    @@ -497,52 +503,22 @@ static void apic_send_ipi(struct kvm_lap

    static u32 apic_get_tmcct(struct kvm_lapic *apic)
    {
    - u64 counter_passed;
    - ktime_t passed, now;
    + ktime_t remaining;
    + s64 ns;
    u32 tmcct;

    ASSERT(apic != NULL);

    - now = apic->timer.dev.base->get_time();
    - tmcct = apic_get_reg(apic, APIC_TMICT);
    -
    /* if initial count is 0, current count should also be 0 */
    - if (tmcct == 0)
    + if (apic_get_reg(apic, APIC_TMICT) == 0)
    return 0;

    - if (unlikely(ktime_to_ns(now) <=
    - ktime_to_ns(apic->timer.last_update))) {
    - /* Wrap around */
    - passed = ktime_add(( {
    - (ktime_t) {
    - .tv64 = KTIME_MAX -
    - (apic->timer.last_update).tv64}; }
    - ), now);
    - apic_debug("time elapsed\n");
    - } else
    - passed = ktime_sub(now, apic->timer.last_update);
    -
    - counter_passed = div64_u64(ktime_to_ns(passed),
    - (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
    -
    - if (counter_passed > tmcct) {
    - if (unlikely(!apic_lvtt_period(apic))) {
    - /* one-shot timers stick at 0 until reset */
    - tmcct = 0;
    - } else {
    - /*
    - * periodic timers reset to APIC_TMICT when they
    - * hit 0. The while loop simulates this happening N
    - * times. (counter_passed %= tmcct) would also work,
    - * but might be slower or not work on 32-bit??
    - */
    - while (counter_passed > tmcct)
    - counter_passed -= tmcct;
    - tmcct -= counter_passed;
    - }
    - } else {
    - tmcct -= counter_passed;
    - }
    + remaining = hrtimer_expires_remaining(&apic->timer.dev);
    + if (ktime_to_ns(remaining) < 0)
    + remaining = ktime_set(0, 0);
    +
    + ns = mod_64(ktime_to_ns(remaining), apic->timer.period);
    + tmcct = div64_u64(ns, (APIC_BUS_CYCLE_NS * apic->timer.divide_count));

    return tmcct;
    }
    @@ -639,8 +615,6 @@ static void start_apic_timer(struct kvm_
    {
    ktime_t now = apic->timer.dev.base->get_time();

    - apic->timer.last_update = now;
    -
    apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
    APIC_BUS_CYCLE_NS * apic->timer.divide_count;
    atomic_set(&apic->timer.pending, 0);
    @@ -1068,16 +1042,6 @@ void kvm_inject_apic_timer_irqs(struct k
    }
    }

    -void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
    -{
    - struct kvm_lapic *apic = vcpu->arch.apic;
    -
    - if (apic && apic_lvt_vector(apic, APIC_LVTT) == vec)
    - apic->timer.last_update = ktime_add_ns(
    - apic->timer.last_update,
    - apic->timer.period);
    -}
    -
    int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
    {
    int vector = kvm_apic_has_interrupt(vcpu);
    --- a/arch/x86/kvm/lapic.h
    +++ b/arch/x86/kvm/lapic.h
    @@ -12,7 +12,6 @@ struct kvm_lapic {
    atomic_t pending;
    s64 period; /* unit: ns */
    u32 divide_count;
    - ktime_t last_update;
    struct hrtimer dev;
    } timer;
    struct kvm_vcpu *vcpu;
    @@ -42,7 +41,6 @@ void kvm_set_apic_base(struct kvm_vcpu *
    void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
    int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
    int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
    -void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec);

    void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
    void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
    --- a/arch/x86/kvm/svm.c
    +++ b/arch/x86/kvm/svm.c
    @@ -1612,7 +1612,6 @@ static void svm_intr_assist(struct kvm_v
    /* Okay, we can deliver the interrupt: grab it and update PIC state. */
    intr_vector = kvm_cpu_get_interrupt(vcpu);
    svm_inject_irq(svm, intr_vector);
    - kvm_timer_intr_post(vcpu, intr_vector);
    out:
    update_cr8_intercept(vcpu);
    }
    --- a/arch/x86/kvm/vmx.c
    +++ b/arch/x86/kvm/vmx.c
    @@ -3171,10 +3171,8 @@ static void vmx_intr_assist(struct kvm_v
    else
    enable_irq_window(vcpu);
    }
    - if (vcpu->arch.interrupt.pending) {
    + if (vcpu->arch.interrupt.pending)
    vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
    - kvm_timer_intr_post(vcpu, vcpu->arch.interrupt.nr);
    - }
    }

    /*



    \
     
     \ /
      Last update: 2009-04-30 19:45    [W:0.029 / U:2.228 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site