From b16005f3882be8c9ef98c0b96c19535f6f9dcaa2 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 17 Mar 2008 16:37:20 -0700 Subject: [PATCH] --- yaml --- r: 93161 b: refs/heads/master c: 229664bee6126e01f8662976a5fe2e79813b77c8 h: refs/heads/master i: 93159: d5a8cc6dfebebe3e2b134f9399ea6703bb3538e5 v: v3 --- [refs] | 2 +- trunk/arch/x86/xen/events.c | 46 ++++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/[refs] b/[refs] index ce4a79bc9a55..a0ddfa24008d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ee8fa1c67f0b873a324960f0ca9fa1d7e49aa86b +refs/heads/master: 229664bee6126e01f8662976a5fe2e79813b77c8 diff --git a/trunk/arch/x86/xen/events.c b/trunk/arch/x86/xen/events.c index f73b53bd65b7..85bac298b3cb 100644 --- a/trunk/arch/x86/xen/events.c +++ b/trunk/arch/x86/xen/events.c @@ -517,29 +517,43 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) int cpu = get_cpu(); struct shared_info *s = HYPERVISOR_shared_info; struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); - unsigned long pending_words; + static DEFINE_PER_CPU(unsigned, nesting_count); + unsigned count; - vcpu_info->evtchn_upcall_pending = 0; + do { + unsigned long pending_words; - /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ - pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); - while (pending_words != 0) { - unsigned long pending_bits; - int word_idx = __ffs(pending_words); - pending_words &= ~(1UL << word_idx); + vcpu_info->evtchn_upcall_pending = 0; - while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) { - int bit_idx = __ffs(pending_bits); - int port = (word_idx * BITS_PER_LONG) + bit_idx; - int irq = evtchn_to_irq[port]; + if (__get_cpu_var(nesting_count)++) + goto out; - if (irq != -1) { - regs->orig_ax = ~irq; - do_IRQ(regs); + /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ + pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); + while (pending_words != 0) { + unsigned long pending_bits; + int word_idx = __ffs(pending_words); + pending_words &= ~(1UL << word_idx); + + while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) { + int bit_idx = __ffs(pending_bits); + int port = (word_idx * BITS_PER_LONG) + bit_idx; + int irq = evtchn_to_irq[port]; + + if (irq != -1) { + regs->orig_ax = ~irq; + do_IRQ(regs); + } } } - } + BUG_ON(!irqs_disabled()); + + count = __get_cpu_var(nesting_count); + __get_cpu_var(nesting_count) = 0; + } while(count != 1); + +out: put_cpu(); }