]> xenbits.xensource.com Git - people/royger/linux-2.6.18-xen.git/commitdiff
xen/evtchn: Handle VIRQ_TIMER before any other hardirq in event loop.
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 22 Sep 2010 09:25:42 +0000 (10:25 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 22 Sep 2010 09:25:42 +0000 (10:25 +0100)
This avoids any other hardirq handler seeing a very stale jiffies
value immediately after wakeup from a long idle period. The one
observable symptom of this was a USB keyboard, with software keyboard
repeat, which would always repeat a key immediately that it was
pressed. This is due to the key press waking the guest, the key
handler immediately runs, sees an old jiffies value, and then that
jiffies value significantly updated, before the key is unpressed.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
drivers/xen/core/evtchn.c

index 4611d3ced46519e3322a3a832a8482508d6d1931..2024c0843b9b2675a31546df2e02b8ba719e4ec1 100644 (file)
@@ -259,6 +259,20 @@ asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
                /* Clear master flag /before/ clearing selector flag. */
                wmb();
 #endif
+
+               /*
+                * Handle timer interrupts before all others, so that all
+                * hardirq handlers see an up-to-date system time even if we
+                * have just woken from a long idle period.
+                */
+               if ((irq = __get_cpu_var(virq_to_irq)[VIRQ_TIMER]) != -1) {
+                       port = evtchn_from_irq(irq);
+                       l1i = port / BITS_PER_LONG;
+                       l2i = port % BITS_PER_LONG;
+                       if (active_evtchns(cpu, s, l1i) & (1ul<<l2i))
+                               do_IRQ(irq, regs);
+               }
+
                l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
 
                start_l1i = l1i = per_cpu(current_l1i, cpu);