
From: Ivan Kokshaysky <ink@jurassic.park.msu.ru>

rth said:

We need a ruling on what the BUG_ON at the beginning of
run_posix_cpu_timers is intending that we check for.

If it is the case that we only care about recursion wrt the timer interrupt
itself, it would be nice if this BUG_ON were removed, or at minimum altered
in some way.  As can be inferred from Ivan's message, the IPL is IPL_TIMER
at this point, so we won't get new timer interrupts.  But it isn't IPL_MAX,
so we *can* get interrupts for other devices.

If we do care about locking out other devices, then of course we have
uncovered a real bug.

I don't like option A because irqs_disabled is used for more than just
timer interrupts.  If we ever want to compare against something other than
IPL_MAX then we need to be given some indication of what interrupt source
we want to be protected from.

Option B is a good workaround for the BUG_ON, provided we add commentary
that says why it's needed.



From: Ivan Kokshaysky <ink@jurassic.park.msu.ru>

As usual, the reason of this breakage is quite silly: in do_entIF, we are
checking for PS == 0 to see whether it was a kernel BUG() or userspace
trap.  It works, unless BUG() happens in interrupt - PS is not 0 in kernel
mode due to non-zero IPL, and the things get messed up horribly then.

In this particular case it was BUG_ON(!irqs_disabled()) triggered in
run_posix_cpu_timers(), so we ended up shooting "current" with the bursts
of one SIGTRAP and three SIGILLs on every timer tick.  ;-)

As for that BUG_ON itself - I see two ways to fix it:
a) loose irqs_disabled() definition -
   -#define irqs_disabled() (getipl() == IPL_MAX)
   +#define irqs_disabled() (getipl() >= IPL_TIMER)
b) simply add local_irq_disable() before update_process_times() call
   in smp_percpu_timer_interrupt().

Not sure which is better.

Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 arch/alpha/kernel/traps.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

diff -puN arch/alpha/kernel/traps.c~alpha-smp-fix arch/alpha/kernel/traps.c
--- devel/arch/alpha/kernel/traps.c~alpha-smp-fix	2005-06-30 22:32:53.000000000 -0700
+++ devel-akpm/arch/alpha/kernel/traps.c	2005-06-30 22:32:53.000000000 -0700
@@ -240,7 +240,7 @@ do_entIF(unsigned long type, struct pt_r
 	siginfo_t info;
 	int signo, code;
 
-	if (regs->ps == 0) {
+	if ((regs->ps & ~IPL_MAX) == 0) {
 		if (type == 1) {
 			const unsigned int *data
 			  = (const unsigned int *) regs->pc;
_
