aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2013-03-28 10:03:36 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2013-04-02 14:01:21 -0400
commitbee980d9e9642e96351fa3ca9077b853ecf62f57 (patch)
treeacb076bd2f1a40d650dada64943b100b0c579979
parentc26377e62f4e6bfb4d99ef88526047209701a83f (diff)
xen/events: Handle VIRQ_TIMER before any other hardirq in event loop.
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. Reviewed-by: David Vrabel <david.vrabel@citrix.com> Signed-off-by: Keir Fraser <keir.fraser@citrix.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r--drivers/xen/events.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index aa85881d17b2..2647ad8e1f19 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -1316,7 +1316,7 @@ static void __xen_evtchn_do_upcall(void)
1316{ 1316{
1317 int start_word_idx, start_bit_idx; 1317 int start_word_idx, start_bit_idx;
1318 int word_idx, bit_idx; 1318 int word_idx, bit_idx;
1319 int i; 1319 int i, irq;
1320 int cpu = get_cpu(); 1320 int cpu = get_cpu();
1321 struct shared_info *s = HYPERVISOR_shared_info; 1321 struct shared_info *s = HYPERVISOR_shared_info;
1322 struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); 1322 struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
@@ -1324,6 +1324,8 @@ static void __xen_evtchn_do_upcall(void)
1324 1324
1325 do { 1325 do {
1326 xen_ulong_t pending_words; 1326 xen_ulong_t pending_words;
1327 xen_ulong_t pending_bits;
1328 struct irq_desc *desc;
1327 1329
1328 vcpu_info->evtchn_upcall_pending = 0; 1330 vcpu_info->evtchn_upcall_pending = 0;
1329 1331
@@ -1335,6 +1337,17 @@ static void __xen_evtchn_do_upcall(void)
1335 * selector flag. xchg_xen_ulong must contain an 1337 * selector flag. xchg_xen_ulong must contain an
1336 * appropriate barrier. 1338 * appropriate barrier.
1337 */ 1339 */
1340 if ((irq = per_cpu(virq_to_irq, cpu)[VIRQ_TIMER]) != -1) {
1341 int evtchn = evtchn_from_irq(irq);
1342 word_idx = evtchn / BITS_PER_LONG;
1343 pending_bits = evtchn % BITS_PER_LONG;
1344 if (active_evtchns(cpu, s, word_idx) & (1ULL << pending_bits)) {
1345 desc = irq_to_desc(irq);
1346 if (desc)
1347 generic_handle_irq_desc(irq, desc);
1348 }
1349 }
1350
1338 pending_words = xchg_xen_ulong(&vcpu_info->evtchn_pending_sel, 0); 1351 pending_words = xchg_xen_ulong(&vcpu_info->evtchn_pending_sel, 0);
1339 1352
1340 start_word_idx = __this_cpu_read(current_word_idx); 1353 start_word_idx = __this_cpu_read(current_word_idx);
@@ -1343,7 +1356,6 @@ static void __xen_evtchn_do_upcall(void)
1343 word_idx = start_word_idx; 1356 word_idx = start_word_idx;
1344 1357
1345 for (i = 0; pending_words != 0; i++) { 1358 for (i = 0; pending_words != 0; i++) {
1346 xen_ulong_t pending_bits;
1347 xen_ulong_t words; 1359 xen_ulong_t words;
1348 1360
1349 words = MASK_LSBS(pending_words, word_idx); 1361 words = MASK_LSBS(pending_words, word_idx);
@@ -1372,8 +1384,7 @@ static void __xen_evtchn_do_upcall(void)
1372 1384
1373 do { 1385 do {
1374 xen_ulong_t bits; 1386 xen_ulong_t bits;
1375 int port, irq; 1387 int port;
1376 struct irq_desc *desc;
1377 1388
1378 bits = MASK_LSBS(pending_bits, bit_idx); 1389 bits = MASK_LSBS(pending_bits, bit_idx);
1379 1390