]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
more .26 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Mon, 18 Aug 2008 17:19:33 +0000 (10:19 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 18 Aug 2008 17:19:33 +0000 (10:19 -0700)
queue-2.6.26/0001-sparc64-Fix-end-of-stack-checking-in-save_stack_tra.patch [new file with mode: 0644]
queue-2.6.26/0002-sparc64-Fix-recursion-in-stack-overflow-detection-h.patch [new file with mode: 0644]
queue-2.6.26/0004-sparc64-Make-global-reg-dumping-even-more-useful.patch [new file with mode: 0644]
queue-2.6.26/0005-sparc64-Implement-IRQ-stacks.patch [new file with mode: 0644]
queue-2.6.26/0006-sparc64-Handle-stack-trace-attempts-before-irqstack.patch [new file with mode: 0644]
queue-2.6.26/series

diff --git a/queue-2.6.26/0001-sparc64-Fix-end-of-stack-checking-in-save_stack_tra.patch b/queue-2.6.26/0001-sparc64-Fix-end-of-stack-checking-in-save_stack_tra.patch
new file mode 100644 (file)
index 0000000..4d4d8e4
--- /dev/null
@@ -0,0 +1,43 @@
+From f2c77753e729813bfc9df9c82c54598c830ea32a Mon Sep 17 00:00:00 2001
+From: David S. Miller <davem@davemloft.net>
+Date: Sun, 17 Aug 2008 20:34:14 -0700
+Subject: sparc64: Fix end-of-stack checking in save_stack_trace().
+Message-Id: <20080817.212911.193702300.davem@davemloft.net>
+
+From: David S. Miller <davem@davemloft.net>
+
+[ Upstream commit 433c5f706856689be25928a99636e724fb3ea7cf ]
+
+Bug reported by Alexander Beregalov.
+
+Before we dereference the stack frame or try to peek at the
+pt_regs magic value, make sure the entire object is within
+the kernel stack bounds.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sparc64/kernel/stacktrace.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/sparc64/kernel/stacktrace.c
++++ b/arch/sparc64/kernel/stacktrace.c
+@@ -25,13 +25,15 @@ void save_stack_trace(struct stack_trace
+               /* Bogus frame pointer? */
+               if (fp < (thread_base + sizeof(struct thread_info)) ||
+-                  fp >= (thread_base + THREAD_SIZE))
++                  fp > (thread_base + THREAD_SIZE - sizeof(struct sparc_stackf)))
+                       break;
+               sf = (struct sparc_stackf *) fp;
+               regs = (struct pt_regs *) (sf + 1);
+-              if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
++              if (((unsigned long)regs <=
++                   (thread_base + THREAD_SIZE - sizeof(*regs))) &&
++                  (regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
+                       if (!(regs->tstate & TSTATE_PRIV))
+                               break;
+                       pc = regs->tpc;
diff --git a/queue-2.6.26/0002-sparc64-Fix-recursion-in-stack-overflow-detection-h.patch b/queue-2.6.26/0002-sparc64-Fix-recursion-in-stack-overflow-detection-h.patch
new file mode 100644 (file)
index 0000000..5494718
--- /dev/null
@@ -0,0 +1,51 @@
+From 21a4e03e0292dac8e0777d1ab89df9539bb21a69 Mon Sep 17 00:00:00 2001
+From: David S. Miller <davem@davemloft.net>
+Date: Sun, 17 Aug 2008 20:39:08 -0700
+Subject: sparc64: Fix recursion in stack overflow detection handling.
+Message-Id: <20080817.212911.193702300.davem@davemloft.net>
+
+[ Upstream commit c7498081a6f5d96c9f3243b6b5e020352903bfd2 ]
+
+The calls down into prom_printf() when we detect an overflowed stack
+can recurse again since the overflow stack will be "below" the current
+kernel stack limit.
+
+Prevent this by just returning straight if we are on the stack
+overflow safe stack already.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sparc64/lib/mcount.S |   17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+--- a/arch/sparc64/lib/mcount.S
++++ b/arch/sparc64/lib/mcount.S
+@@ -45,12 +45,23 @@ _mcount:
+       sub             %g3, STACK_BIAS, %g3
+       cmp             %sp, %g3
+       bg,pt           %xcc, 1f
+-       sethi          %hi(panicstring), %g3
++       nop
++      /* If we are already on ovstack, don't hop onto it
++       * again, we are already trying to output the stack overflow
++       * message.
++       */
+       sethi           %hi(ovstack), %g7               ! cant move to panic stack fast enough
+        or             %g7, %lo(ovstack), %g7
+-      add             %g7, OVSTACKSIZE, %g7
++      add             %g7, OVSTACKSIZE, %g3
++      sub             %g3, STACK_BIAS + 192, %g3
+       sub             %g7, STACK_BIAS, %g7
+-      mov             %g7, %sp
++      cmp             %sp, %g7
++      blu,pn          %xcc, 2f
++       cmp            %sp, %g3
++      bleu,pn         %xcc, 1f
++       nop
++2:    mov             %g3, %sp
++      sethi           %hi(panicstring), %g3
+       call            prom_printf
+        or             %g3, %lo(panicstring), %o0
+       call            prom_halt
diff --git a/queue-2.6.26/0004-sparc64-Make-global-reg-dumping-even-more-useful.patch b/queue-2.6.26/0004-sparc64-Make-global-reg-dumping-even-more-useful.patch
new file mode 100644 (file)
index 0000000..636e0f9
--- /dev/null
@@ -0,0 +1,133 @@
+From 0ccf42444a924bcbca8e11683b5a9b8f1e274c5b Mon Sep 17 00:00:00 2001
+From: David S. Miller <davem@davemloft.net>
+Date: Sun, 17 Aug 2008 20:47:13 -0700
+Subject: sparc64: Make global reg dumping even more useful.
+Message-Id: <20080817.212911.193702300.davem@davemloft.net>
+
+From: David S. Miller <davem@davemloft.net>
+
+[ Upstream commit 5afe27380bc42454254c9c83c045240249c15e35 ]
+
+Record one more level of stack frame program counter.
+
+Particularly when lockdep and all sorts of spinlock debugging is
+enabled, figuring out the caller of spin_lock() is difficult when the
+cpu is stuck on the lock.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sparc64/kernel/process.c |   35 +++++++++++++++++++++++++++++------
+ arch/sparc64/mm/ultra.S       |    7 +++++++
+ include/asm-sparc64/ptrace.h  |    8 ++++----
+ 3 files changed, 40 insertions(+), 10 deletions(-)
+
+--- a/arch/sparc64/kernel/process.c
++++ b/arch/sparc64/kernel/process.c
+@@ -305,6 +305,19 @@ void show_regs(struct pt_regs *regs)
+ struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
+ static DEFINE_SPINLOCK(global_reg_snapshot_lock);
++static bool kstack_valid(struct thread_info *tp, struct reg_window *rw)
++{
++      unsigned long thread_base, fp;
++
++      thread_base = (unsigned long) tp;
++      fp = (unsigned long) rw;
++
++      if (fp < (thread_base + sizeof(struct thread_info)) ||
++          fp >= (thread_base + THREAD_SIZE))
++              return false;
++      return true;
++}
++
+ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
+                             int this_cpu)
+ {
+@@ -316,14 +329,22 @@ static void __global_reg_self(struct thr
+       global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7];
+       if (regs->tstate & TSTATE_PRIV) {
++              struct thread_info *tp = current_thread_info();
+               struct reg_window *rw;
+               rw = (struct reg_window *)
+                       (regs->u_regs[UREG_FP] + STACK_BIAS);
+-              global_reg_snapshot[this_cpu].i7 = rw->ins[7];
+-      } else
++              if (kstack_valid(tp, rw)) {
++                      global_reg_snapshot[this_cpu].i7 = rw->ins[7];
++                      rw = (struct reg_window *)
++                              (rw->ins[6] + STACK_BIAS);
++                      if (kstack_valid(tp, rw))
++                              global_reg_snapshot[this_cpu].rpc = rw->ins[7];
++              }
++      } else {
+               global_reg_snapshot[this_cpu].i7 = 0;
+-
++              global_reg_snapshot[this_cpu].rpc = 0;
++      }
+       global_reg_snapshot[this_cpu].thread = tp;
+ }
+@@ -384,12 +405,14 @@ static void sysrq_handle_globreg(int key
+                       sprint_symbol(buffer, gp->o7);
+                       printk("O7[%s] ", buffer);
+                       sprint_symbol(buffer, gp->i7);
+-                      printk("I7[%s]\n", buffer);
++                      printk("I7[%s] ", buffer);
++                      sprint_symbol(buffer, gp->rpc);
++                      printk("RPC[%s]\n", buffer);
+               } else
+ #endif
+               {
+-                      printk("             TPC[%lx] O7[%lx] I7[%lx]\n",
+-                             gp->tpc, gp->o7, gp->i7);
++                      printk("             TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n",
++                             gp->tpc, gp->o7, gp->i7, gp->rpc);
+               }
+       }
+--- a/arch/sparc64/mm/ultra.S
++++ b/arch/sparc64/mm/ultra.S
+@@ -531,6 +531,13 @@ xcall_fetch_glob_regs:
+       stx             %g7, [%g1 + GR_SNAP_TNPC]
+       stx             %o7, [%g1 + GR_SNAP_O7]
+       stx             %i7, [%g1 + GR_SNAP_I7]
++      /* Don't try this at home kids... */
++      rdpr            %cwp, %g2
++      sub             %g2, 1, %g7
++      wrpr            %g7, %cwp
++      mov             %i7, %g7
++      wrpr            %g2, %cwp
++      stx             %g7, [%g1 + GR_SNAP_RPC]
+       sethi           %hi(trap_block), %g7
+       or              %g7, %lo(trap_block), %g7
+       sllx            %g2, TRAP_BLOCK_SZ_SHIFT, %g2
+--- a/include/asm-sparc64/ptrace.h
++++ b/include/asm-sparc64/ptrace.h
+@@ -134,9 +134,9 @@ struct global_reg_snapshot {
+       unsigned long           tnpc;
+       unsigned long           o7;
+       unsigned long           i7;
++      unsigned long           rpc;
+       struct thread_info      *thread;
+       unsigned long           pad1;
+-      unsigned long           pad2;
+ };
+ #define __ARCH_WANT_COMPAT_SYS_PTRACE
+@@ -314,9 +314,9 @@ extern void __show_regs(struct pt_regs *
+ #define GR_SNAP_TNPC  0x10
+ #define GR_SNAP_O7    0x18
+ #define GR_SNAP_I7    0x20
+-#define GR_SNAP_THREAD        0x28
+-#define GR_SNAP_PAD1  0x30
+-#define GR_SNAP_PAD2  0x38
++#define GR_SNAP_RPC   0x28
++#define GR_SNAP_THREAD        0x30
++#define GR_SNAP_PAD1  0x38
+ #endif  /*  __KERNEL__  */
diff --git a/queue-2.6.26/0005-sparc64-Implement-IRQ-stacks.patch b/queue-2.6.26/0005-sparc64-Implement-IRQ-stacks.patch
new file mode 100644 (file)
index 0000000..1edb0be
--- /dev/null
@@ -0,0 +1,366 @@
+From 2a979104ae529490f11e65339372c2f11f9f5a45 Mon Sep 17 00:00:00 2001
+From: David S. Miller <davem@davemloft.net>
+Date: Sun, 17 Aug 2008 20:49:47 -0700
+Subject: sparc64: Implement IRQ stacks.
+Message-Id: <20080817.212911.193702300.davem@davemloft.net>
+
+From: David S. Miller <davem@davemloft.net>
+
+[ Upstream commit 4f70f7a91bffdcc39f088748dc678953eb9a3fbd ]
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sparc64/kernel/irq.c        |   52 ++++++++++++++++++++++++++++++++++
+ arch/sparc64/kernel/kstack.h     |   58 +++++++++++++++++++++++++++++++++++++++
+ arch/sparc64/kernel/process.c    |   27 ++++--------------
+ arch/sparc64/kernel/stacktrace.c |   10 ++----
+ arch/sparc64/kernel/traps.c      |    7 ++--
+ arch/sparc64/lib/mcount.S        |   22 ++++++++++++++
+ arch/sparc64/mm/init.c           |   11 +++++++
+ include/asm-sparc64/irq.h        |    4 ++
+ 8 files changed, 161 insertions(+), 30 deletions(-)
+
+--- a/arch/sparc64/kernel/irq.c
++++ b/arch/sparc64/kernel/irq.c
+@@ -682,10 +682,32 @@ void ack_bad_irq(unsigned int virt_irq)
+              ino, virt_irq);
+ }
++void *hardirq_stack[NR_CPUS];
++void *softirq_stack[NR_CPUS];
++
++static __attribute__((always_inline)) void *set_hardirq_stack(void)
++{
++      void *orig_sp, *sp = hardirq_stack[smp_processor_id()];
++
++      __asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp));
++      if (orig_sp < sp ||
++          orig_sp > (sp + THREAD_SIZE)) {
++              sp += THREAD_SIZE - 192 - STACK_BIAS;
++              __asm__ __volatile__("mov %0, %%sp" : : "r" (sp));
++      }
++
++      return orig_sp;
++}
++static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp)
++{
++      __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp));
++}
++
+ void handler_irq(int irq, struct pt_regs *regs)
+ {
+       unsigned long pstate, bucket_pa;
+       struct pt_regs *old_regs;
++      void *orig_sp;
+       clear_softint(1 << irq);
+@@ -703,6 +725,8 @@ void handler_irq(int irq, struct pt_regs
+                              "i" (PSTATE_IE)
+                            : "memory");
++      orig_sp = set_hardirq_stack();
++
+       while (bucket_pa) {
+               struct irq_desc *desc;
+               unsigned long next_pa;
+@@ -719,10 +743,38 @@ void handler_irq(int irq, struct pt_regs
+               bucket_pa = next_pa;
+       }
++      restore_hardirq_stack(orig_sp);
++
+       irq_exit();
+       set_irq_regs(old_regs);
+ }
++void do_softirq(void)
++{
++      unsigned long flags;
++
++      if (in_interrupt())
++              return;
++
++      local_irq_save(flags);
++
++      if (local_softirq_pending()) {
++              void *orig_sp, *sp = softirq_stack[smp_processor_id()];
++
++              sp += THREAD_SIZE - 192 - STACK_BIAS;
++
++              __asm__ __volatile__("mov %%sp, %0\n\t"
++                                   "mov %1, %%sp"
++                                   : "=&r" (orig_sp)
++                                   : "r" (sp));
++              __do_softirq();
++              __asm__ __volatile__("mov %0, %%sp"
++                                   : : "r" (orig_sp));
++      }
++
++      local_irq_restore(flags);
++}
++
+ #ifdef CONFIG_HOTPLUG_CPU
+ void fixup_irqs(void)
+ {
+--- /dev/null
++++ b/arch/sparc64/kernel/kstack.h
+@@ -0,0 +1,58 @@
++#ifndef _KSTACK_H
++#define _KSTACK_H
++
++#include <linux/thread_info.h>
++#include <linux/sched.h>
++#include <asm/ptrace.h>
++#include <asm/irq.h>
++
++/* SP must be STACK_BIAS adjusted already.  */
++static inline bool kstack_valid(struct thread_info *tp, unsigned long sp)
++{
++      unsigned long base = (unsigned long) tp;
++
++      if (sp >= (base + sizeof(struct thread_info)) &&
++          sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
++              return true;
++
++      base = (unsigned long) hardirq_stack[tp->cpu];
++      if (sp >= base &&
++          sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
++              return true;
++      base = (unsigned long) softirq_stack[tp->cpu];
++      if (sp >= base &&
++          sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
++              return true;
++
++      return false;
++}
++
++/* Does "regs" point to a valid pt_regs trap frame?  */
++static inline bool kstack_is_trap_frame(struct thread_info *tp, struct pt_regs *regs)
++{
++      unsigned long base = (unsigned long) tp;
++      unsigned long addr = (unsigned long) regs;
++
++      if (addr >= base &&
++          addr <= (base + THREAD_SIZE - sizeof(*regs)))
++              goto check_magic;
++
++      base = (unsigned long) hardirq_stack[tp->cpu];
++      if (addr >= base &&
++          addr <= (base + THREAD_SIZE - sizeof(*regs)))
++              goto check_magic;
++      base = (unsigned long) softirq_stack[tp->cpu];
++      if (addr >= base &&
++          addr <= (base + THREAD_SIZE - sizeof(*regs)))
++              goto check_magic;
++
++      return false;
++
++check_magic:
++      if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC)
++              return true;
++      return false;
++
++}
++
++#endif /* _KSTACK_H */
+--- a/arch/sparc64/kernel/process.c
++++ b/arch/sparc64/kernel/process.c
+@@ -55,6 +55,8 @@
+ /* #define VERBOSE_SHOWREGS */
++#include "kstack.h"
++
+ static void sparc64_yield(int cpu)
+ {
+       if (tlb_type != hypervisor)
+@@ -305,19 +307,6 @@ void show_regs(struct pt_regs *regs)
+ struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
+ static DEFINE_SPINLOCK(global_reg_snapshot_lock);
+-static bool kstack_valid(struct thread_info *tp, struct reg_window *rw)
+-{
+-      unsigned long thread_base, fp;
+-
+-      thread_base = (unsigned long) tp;
+-      fp = (unsigned long) rw;
+-
+-      if (fp < (thread_base + sizeof(struct thread_info)) ||
+-          fp >= (thread_base + THREAD_SIZE))
+-              return false;
+-      return true;
+-}
+-
+ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
+                             int this_cpu)
+ {
+@@ -334,11 +323,11 @@ static void __global_reg_self(struct thr
+               rw = (struct reg_window *)
+                       (regs->u_regs[UREG_FP] + STACK_BIAS);
+-              if (kstack_valid(tp, rw)) {
++              if (kstack_valid(tp, (unsigned long) rw)) {
+                       global_reg_snapshot[this_cpu].i7 = rw->ins[7];
+                       rw = (struct reg_window *)
+                               (rw->ins[6] + STACK_BIAS);
+-                      if (kstack_valid(tp, rw))
++                      if (kstack_valid(tp, (unsigned long) rw))
+                               global_reg_snapshot[this_cpu].rpc = rw->ins[7];
+               }
+       } else {
+@@ -899,7 +888,7 @@ out:
+ unsigned long get_wchan(struct task_struct *task)
+ {
+       unsigned long pc, fp, bias = 0;
+-      unsigned long thread_info_base;
++      struct thread_info *tp;
+       struct reg_window *rw;
+         unsigned long ret = 0;
+       int count = 0; 
+@@ -908,14 +897,12 @@ unsigned long get_wchan(struct task_stru
+             task->state == TASK_RUNNING)
+               goto out;
+-      thread_info_base = (unsigned long) task_stack_page(task);
++      tp = task_thread_info(task);
+       bias = STACK_BIAS;
+       fp = task_thread_info(task)->ksp + bias;
+       do {
+-              /* Bogus frame pointer? */
+-              if (fp < (thread_info_base + sizeof(struct thread_info)) ||
+-                  fp >= (thread_info_base + THREAD_SIZE))
++              if (!kstack_valid(tp, fp))
+                       break;
+               rw = (struct reg_window *) fp;
+               pc = rw->ins[7];
+--- a/arch/sparc64/kernel/stacktrace.c
++++ b/arch/sparc64/kernel/stacktrace.c
+@@ -4,6 +4,8 @@
+ #include <asm/ptrace.h>
+ #include <asm/stacktrace.h>
++#include "kstack.h"
++
+ void save_stack_trace(struct stack_trace *trace)
+ {
+       unsigned long ksp, fp, thread_base;
+@@ -23,17 +25,13 @@ void save_stack_trace(struct stack_trace
+               struct pt_regs *regs;
+               unsigned long pc;
+-              /* Bogus frame pointer? */
+-              if (fp < (thread_base + sizeof(struct thread_info)) ||
+-                  fp > (thread_base + THREAD_SIZE - sizeof(struct sparc_stackf)))
++              if (!kstack_valid(tp, fp))
+                       break;
+               sf = (struct sparc_stackf *) fp;
+               regs = (struct pt_regs *) (sf + 1);
+-              if (((unsigned long)regs <=
+-                   (thread_base + THREAD_SIZE - sizeof(*regs))) &&
+-                  (regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
++              if (kstack_is_trap_frame(tp, regs)) {
+                       if (!(regs->tstate & TSTATE_PRIV))
+                               break;
+                       pc = regs->tpc;
+--- a/arch/sparc64/kernel/traps.c
++++ b/arch/sparc64/kernel/traps.c
+@@ -43,6 +43,7 @@
+ #include <asm/prom.h>
+ #include "entry.h"
++#include "kstack.h"
+ /* When an irrecoverable trap occurs at tl > 0, the trap entry
+  * code logs the trap state registers at every level in the trap
+@@ -2120,14 +2121,12 @@ void show_stack(struct task_struct *tsk,
+               struct pt_regs *regs;
+               unsigned long pc;
+-              /* Bogus frame pointer? */
+-              if (fp < (thread_base + sizeof(struct thread_info)) ||
+-                  fp >= (thread_base + THREAD_SIZE))
++              if (!kstack_valid(tp, fp))
+                       break;
+               sf = (struct sparc_stackf *) fp;
+               regs = (struct pt_regs *) (sf + 1);
+-              if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
++              if (kstack_is_trap_frame(tp, regs)) {
+                       if (!(regs->tstate & TSTATE_PRIV))
+                               break;
+                       pc = regs->tpc;
+--- a/arch/sparc64/lib/mcount.S
++++ b/arch/sparc64/lib/mcount.S
+@@ -46,6 +46,28 @@ _mcount:
+       cmp             %sp, %g3
+       bg,pt           %xcc, 1f
+        nop
++      lduh            [%g6 + TI_CPU], %g1
++      sethi           %hi(hardirq_stack), %g3
++      or              %g3, %lo(hardirq_stack), %g3
++      sllx            %g1, 3, %g1
++      ldx             [%g3 + %g1], %g7
++      sub             %g7, STACK_BIAS, %g7
++      cmp             %sp, %g7
++      bleu,pt         %xcc, 2f
++       sethi          %hi(THREAD_SIZE), %g3
++      add             %g7, %g3, %g7
++      cmp             %sp, %g7
++      blu,pn          %xcc, 1f
++2:     sethi          %hi(softirq_stack), %g3
++      or              %g3, %lo(softirq_stack), %g3
++      ldx             [%g3 + %g1], %g7
++      cmp             %sp, %g7
++      bleu,pt         %xcc, 2f
++       sethi          %hi(THREAD_SIZE), %g3
++      add             %g7, %g3, %g7
++      cmp             %sp, %g7
++      blu,pn          %xcc, 1f
++       nop
+       /* If we are already on ovstack, don't hop onto it
+        * again, we are already trying to output the stack overflow
+        * message.
+--- a/arch/sparc64/mm/init.c
++++ b/arch/sparc64/mm/init.c
+@@ -49,6 +49,7 @@
+ #include <asm/sstate.h>
+ #include <asm/mdesc.h>
+ #include <asm/cpudata.h>
++#include <asm/irq.h>
+ #define MAX_PHYS_ADDRESS      (1UL << 42UL)
+ #define KPTE_BITMAP_CHUNK_SZ  (256UL * 1024UL * 1024UL)
+@@ -1817,6 +1818,16 @@ void __init paging_init(void)
+       if (tlb_type == hypervisor)
+               sun4v_mdesc_init();
++      /* Once the OF device tree and MDESC have been setup, we know
++       * the list of possible cpus.  Therefore we can allocate the
++       * IRQ stacks.
++       */
++      for_each_possible_cpu(i) {
++              /* XXX Use node local allocations... XXX */
++              softirq_stack[i] = __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
++              hardirq_stack[i] = __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
++      }
++
+       /* Setup bootmem... */
+       last_valid_pfn = end_pfn = bootmem_init(phys_base);
+--- a/include/asm-sparc64/irq.h
++++ b/include/asm-sparc64/irq.h
+@@ -90,4 +90,8 @@ static inline unsigned long get_softint(
+       return retval;
+ }
++extern void *hardirq_stack[NR_CPUS];
++extern void *softirq_stack[NR_CPUS];
++#define __ARCH_HAS_DO_SOFTIRQ
++
+ #endif
diff --git a/queue-2.6.26/0006-sparc64-Handle-stack-trace-attempts-before-irqstack.patch b/queue-2.6.26/0006-sparc64-Handle-stack-trace-attempts-before-irqstack.patch
new file mode 100644 (file)
index 0000000..43558dc
--- /dev/null
@@ -0,0 +1,98 @@
+From 9e1f24c58509c815741a8c9f081191be862959c1 Mon Sep 17 00:00:00 2001
+From: David S. Miller <davem@davemloft.net>
+Date: Sun, 17 Aug 2008 20:51:12 -0700
+Subject: sparc64: Handle stack trace attempts before irqstacks are setup.
+Message-Id: <20080817.212911.193702300.davem@davemloft.net>
+
+From: David S. Miller <davem@davemloft.net>
+
+[ Upstream commit 6f63e781eaf6a741fc65f773017154b20ed4ce3b ]
+
+Things like lockdep can try to do stack backtraces before
+the irqstack blocks have been setup.  So don't try to match
+their ranges so early on.
+
+Also, remove unused variable in save_stack_trace().
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sparc64/kernel/kstack.h     |   38 ++++++++++++++++++++------------------
+ arch/sparc64/kernel/stacktrace.c |    3 +--
+ 2 files changed, 21 insertions(+), 20 deletions(-)
+
+--- a/arch/sparc64/kernel/kstack.h
++++ b/arch/sparc64/kernel/kstack.h
+@@ -15,15 +15,16 @@ static inline bool kstack_valid(struct t
+           sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
+               return true;
+-      base = (unsigned long) hardirq_stack[tp->cpu];
+-      if (sp >= base &&
+-          sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
+-              return true;
+-      base = (unsigned long) softirq_stack[tp->cpu];
+-      if (sp >= base &&
+-          sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
+-              return true;
+-
++      if (hardirq_stack[tp->cpu]) {
++              base = (unsigned long) hardirq_stack[tp->cpu];
++              if (sp >= base &&
++                  sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
++                      return true;
++              base = (unsigned long) softirq_stack[tp->cpu];
++              if (sp >= base &&
++                  sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
++                      return true;
++      }
+       return false;
+ }
+@@ -37,15 +38,16 @@ static inline bool kstack_is_trap_frame(
+           addr <= (base + THREAD_SIZE - sizeof(*regs)))
+               goto check_magic;
+-      base = (unsigned long) hardirq_stack[tp->cpu];
+-      if (addr >= base &&
+-          addr <= (base + THREAD_SIZE - sizeof(*regs)))
+-              goto check_magic;
+-      base = (unsigned long) softirq_stack[tp->cpu];
+-      if (addr >= base &&
+-          addr <= (base + THREAD_SIZE - sizeof(*regs)))
+-              goto check_magic;
+-
++      if (hardirq_stack[tp->cpu]) {
++              base = (unsigned long) hardirq_stack[tp->cpu];
++              if (addr >= base &&
++                  addr <= (base + THREAD_SIZE - sizeof(*regs)))
++                      goto check_magic;
++              base = (unsigned long) softirq_stack[tp->cpu];
++              if (addr >= base &&
++                  addr <= (base + THREAD_SIZE - sizeof(*regs)))
++                      goto check_magic;
++      }
+       return false;
+ check_magic:
+--- a/arch/sparc64/kernel/stacktrace.c
++++ b/arch/sparc64/kernel/stacktrace.c
+@@ -8,8 +8,8 @@
+ void save_stack_trace(struct stack_trace *trace)
+ {
+-      unsigned long ksp, fp, thread_base;
+       struct thread_info *tp = task_thread_info(current);
++      unsigned long ksp, fp;
+       stack_trace_flush();
+@@ -19,7 +19,6 @@ void save_stack_trace(struct stack_trace
+       );
+       fp = ksp + STACK_BIAS;
+-      thread_base = (unsigned long) tp;
+       do {
+               struct sparc_stackf *sf;
+               struct pt_regs *regs;
index 5e7f161114d79abbdd189d3deacf6e04c1bd263c..bd2f53cacbd26ae992a46bb7598b5dfe8360c2c8 100644 (file)
@@ -44,3 +44,8 @@ cifs-fix-compiler-warning-on-64-bit.patch
 radeon-misc-corrections.patch
 cs5520-add-enablebits-checking.patch
 rtl8187-fix-lockups-due-to-concurrent-access-to-config-routine.patch
+0001-sparc64-Fix-end-of-stack-checking-in-save_stack_tra.patch
+0002-sparc64-Fix-recursion-in-stack-overflow-detection-h.patch
+0004-sparc64-Make-global-reg-dumping-even-more-useful.patch
+0005-sparc64-Implement-IRQ-stacks.patch
+0006-sparc64-Handle-stack-trace-attempts-before-irqstack.patch