From: Paolo Bonzini <pbonzini@redhat.com> Date: Wed, 23 Jun 2010 14:09:30 -0400 Subject: [virt] xen: handle softirqs at end of event processing Message-id: <1277302172-10673-1-git-send-email-pbonzini@redhat.com> Patchwork-id: 26469 O-Subject: [RHEL5.5 PATCH] xen: make sure that softirqs are handled only at the end of event processing Bugzilla: 564523 RH-Acked-by: Andrew Jones <drjones@redhat.com> Bugzilla: 564523 Upstream status: http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/709 Brew build: https://brewweb.devel.redhat.com/taskinfo?taskID=2540880 Make sure that irq_enter()/irq_exit() wrap the entire event processing loop, rather than each individual event invokation. This makes sure that softirq processing is deferred until the end of event processing, rather than in the middle with interrupts disabled. Patch is identical to upstream except for some context in irq-xen.c files. diff --git a/arch/i386/kernel/irq-xen.c b/arch/i386/kernel/irq-xen.c index 8862ff4..a26c02c 100644 --- a/arch/i386/kernel/irq-xen.c +++ b/arch/i386/kernel/irq-xen.c @@ -87,7 +87,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs) BUG(); } - irq_enter(); #ifdef CONFIG_DEBUG_STACKOVERFLOW /* Debugging check for stack overflow: is there less than 1KB free? */ { @@ -139,8 +138,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs) __do_IRQ(irq, regs); } - irq_exit(); - return 1; } diff --git a/arch/x86_64/kernel/irq-xen.c b/arch/x86_64/kernel/irq-xen.c index aa77e50..1381c43 100644 --- a/arch/x86_64/kernel/irq-xen.c +++ b/arch/x86_64/kernel/irq-xen.c @@ -124,15 +124,10 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs) BUG(); } - exit_idle(); - irq_enter(); - #ifdef CONFIG_DEBUG_STACKOVERFLOW stack_overflow_check(regs); #endif __do_IRQ(irq, regs); - irq_exit(); - return 1; } diff --git a/drivers/xen/core/evtchn.c b/drivers/xen/core/evtchn.c index 323b85f..2a727cb 100644 --- a/drivers/xen/core/evtchn.c +++ b/drivers/xen/core/evtchn.c @@ -221,6 +221,8 @@ asmlinkage void evtchn_do_upcall(struct pt_regs *regs) shared_info_t *s = HYPERVISOR_shared_info; vcpu_info_t *vcpu_info = &s->vcpu_info[cpu]; + exit_idle(); + irq_enter(); do { /* Avoid a callback storm when we reenable delivery. */ @@ -228,7 +230,7 @@ asmlinkage void evtchn_do_upcall(struct pt_regs *regs) /* Nested invocations bail immediately. */ if (unlikely(per_cpu(upcall_count, cpu)++)) - return; + break; #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */ /* Clear master flag /before/ clearing selector flag. */ @@ -268,10 +270,8 @@ asmlinkage void evtchn_do_upcall(struct pt_regs *regs) port = (l1i * BITS_PER_LONG) + l2i; if ((irq = evtchn_to_irq[port]) != -1) do_IRQ(irq, regs); - else { - exit_idle(); + else evtchn_device_upcall(port); - } /* if this is the final port processed, we'll pick up here+1 next time */ per_cpu(last_processed_l1i, cpu) = l1i; @@ -289,6 +289,8 @@ asmlinkage void evtchn_do_upcall(struct pt_regs *regs) count = per_cpu(upcall_count, cpu); per_cpu(upcall_count, cpu) = 0; } while (unlikely(count != 1)); + + irq_exit(); } static int find_unbound_irq(void) diff --git a/include/asm-ia64/hypercall.h b/include/asm-ia64/hypercall.h index 121beb6..f25aa61 100644 --- a/include/asm-ia64/hypercall.h +++ b/include/asm-ia64/hypercall.h @@ -225,11 +225,7 @@ HYPERVISOR_physdev_op(int cmd, void *arg) extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); static inline void exit_idle(void) {} -#define do_IRQ(irq, regs) ({ \ - irq_enter(); \ - __do_IRQ((irq), (regs)); \ - irq_exit(); \ -}) +#define do_IRQ(irq, regs) __do_IRQ((irq), (regs)) #include <linux/err.h> #ifdef CONFIG_XEN