ia64/linux-2.6.18-xen.hg

changeset 710:9750ab8d7faa

Fix IRQ-from-evtchn delivery so that softirq handling does not happen
while IRQ delivery is blocked. We do this by moving irq_enter/irq_exit
outside the mutual-exclusion region in evtchn_do_upcall(). We then
have to remove irq_enter/irq_exit from do_IRQ(), otherwise the
preempt_coutn check in the rcu code will always fail and we hang
during boot.

Thanks to Eduard Guzovsky of Stratus for help with this patch.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Oct 27 10:43:45 2008 +0000 (2008-10-27)
parents 2b1dc4b1b231
children 61eafcbeaeb4
files arch/i386/kernel/irq-xen.c arch/x86_64/kernel/irq-xen.c drivers/xen/core/evtchn.c include/asm-ia64/hypercall.h
line diff
     1.1 --- a/arch/i386/kernel/irq-xen.c	Mon Oct 27 10:32:08 2008 +0000
     1.2 +++ b/arch/i386/kernel/irq-xen.c	Mon Oct 27 10:43:45 2008 +0000
     1.3 @@ -66,7 +66,7 @@ fastcall unsigned int do_IRQ(struct pt_r
     1.4  		BUG();
     1.5  	}
     1.6  
     1.7 -	irq_enter();
     1.8 +	/*irq_enter();*/
     1.9  #ifdef CONFIG_DEBUG_STACKOVERFLOW
    1.10  	/* Debugging check for stack overflow: is there less than 1KB free? */
    1.11  	{
    1.12 @@ -121,7 +121,7 @@ fastcall unsigned int do_IRQ(struct pt_r
    1.13  #endif
    1.14  		__do_IRQ(irq, regs);
    1.15  
    1.16 -	irq_exit();
    1.17 +	/*irq_exit();*/
    1.18  
    1.19  	return 1;
    1.20  }
     2.1 --- a/arch/x86_64/kernel/irq-xen.c	Mon Oct 27 10:32:08 2008 +0000
     2.2 +++ b/arch/x86_64/kernel/irq-xen.c	Mon Oct 27 10:43:45 2008 +0000
     2.3 @@ -124,13 +124,13 @@ asmlinkage unsigned int do_IRQ(struct pt
     2.4  		BUG();
     2.5  	}
     2.6  
     2.7 -	exit_idle();
     2.8 -	irq_enter();
     2.9 +	/*exit_idle();*/
    2.10 +	/*irq_enter();*/
    2.11  #ifdef CONFIG_DEBUG_STACKOVERFLOW
    2.12  	stack_overflow_check(regs);
    2.13  #endif
    2.14  	__do_IRQ(irq, regs);
    2.15 -	irq_exit();
    2.16 +	/*irq_exit();*/
    2.17  
    2.18  	return 1;
    2.19  }
     3.1 --- a/drivers/xen/core/evtchn.c	Mon Oct 27 10:32:08 2008 +0000
     3.2 +++ b/drivers/xen/core/evtchn.c	Mon Oct 27 10:43:45 2008 +0000
     3.3 @@ -246,6 +246,8 @@ asmlinkage void evtchn_do_upcall(struct 
     3.4  	shared_info_t      *s = HYPERVISOR_shared_info;
     3.5  	vcpu_info_t        *vcpu_info = &s->vcpu_info[cpu];
     3.6  
     3.7 +	exit_idle();
     3.8 +	irq_enter();
     3.9  
    3.10  	do {
    3.11  		/* Avoid a callback storm when we reenable delivery. */
    3.12 @@ -253,7 +255,7 @@ asmlinkage void evtchn_do_upcall(struct 
    3.13  
    3.14  		/* Nested invocations bail immediately. */
    3.15  		if (unlikely(per_cpu(upcall_count, cpu)++))
    3.16 -			return;
    3.17 +			break;
    3.18  
    3.19  #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
    3.20  		/* Clear master flag /before/ clearing selector flag. */
    3.21 @@ -293,10 +295,8 @@ asmlinkage void evtchn_do_upcall(struct 
    3.22  				port = (l1i * BITS_PER_LONG) + l2i;
    3.23  				if ((irq = evtchn_to_irq[port]) != -1)
    3.24  					do_IRQ(irq, regs);
    3.25 -				else {
    3.26 -					exit_idle();
    3.27 +				else
    3.28  					evtchn_device_upcall(port);
    3.29 -				}
    3.30  
    3.31  				/* if this is the final port processed, we'll pick up here+1 next time */
    3.32  				per_cpu(last_processed_l1i, cpu) = l1i;
    3.33 @@ -314,6 +314,8 @@ asmlinkage void evtchn_do_upcall(struct 
    3.34  		count = per_cpu(upcall_count, cpu);
    3.35  		per_cpu(upcall_count, cpu) = 0;
    3.36  	} while (unlikely(count != 1));
    3.37 +
    3.38 +	irq_exit();
    3.39  }
    3.40  
    3.41  static int find_unbound_irq(void)
     4.1 --- a/include/asm-ia64/hypercall.h	Mon Oct 27 10:32:08 2008 +0000
     4.2 +++ b/include/asm-ia64/hypercall.h	Mon Oct 27 10:43:45 2008 +0000
     4.3 @@ -237,11 +237,7 @@ xencomm_arch_hypercall_opt_feature(struc
     4.4  
     4.5  extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
     4.6  static inline void exit_idle(void) {}
     4.7 -#define do_IRQ(irq, regs) ({			\
     4.8 -	irq_enter();				\
     4.9 -	__do_IRQ((irq), (regs));		\
    4.10 -	irq_exit();				\
    4.11 -})
    4.12 +#define do_IRQ(irq, regs) __do_IRQ((irq), (regs))
    4.13  
    4.14  #include <linux/err.h>
    4.15  #ifdef HAVE_XEN_PLATFORM_COMPAT_H