Sophie

Sophie

distrib > CentOS > 5 > i386 > by-pkgid > ea32411352494358b8d75a78402a4713 > files > 4999

kernel-2.6.18-238.19.1.el5.centos.plus.src.rpm

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