From: Anton Blanchard <anton@samba.org>

Fix __get_SP()

__get_SP used to be a function call which meant we allocated a stack
frame before calling it. This meant the SP it returned was one frame
below the current function. Lets call that bogusSP (and the real one
SP).

The new dump_stack was being tail call optimised so it remained one 
frame above bogusSP. dump_stack would then store below SP (as the ABI
allows us to) and would stomp over the back link that bogusSP pointed
to (__get_SP had set the back link up so it worked sometimes, just not
all the time).

Fix this by just making __get_SP an inline that returns the current SP.


---

 arch/ppc64/kernel/irq.c       |    2 +-
 arch/ppc64/kernel/misc.S      |    4 ----
 arch/ppc64/kernel/process.c   |    8 ++++----
 arch/ppc64/kernel/stab.c      |    2 +-
 include/asm-ppc64/processor.h |    3 ++-
 5 files changed, 8 insertions(+), 11 deletions(-)

diff -puN arch/ppc64/kernel/irq.c~ppc64-get_SP arch/ppc64/kernel/irq.c
--- 25/arch/ppc64/kernel/irq.c~ppc64-get_SP	2004-02-21 20:58:31.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/irq.c	2004-02-21 20:58:31.000000000 -0800
@@ -579,7 +579,7 @@ int do_IRQ(struct pt_regs *regs)
 	{
 		long sp;
 
-		sp = (unsigned long)_get_SP() & (THREAD_SIZE-1);
+		sp = __get_SP() & (THREAD_SIZE-1);
 
 		if (unlikely(sp < (sizeof(struct thread_info) + 8192))) {
 			printk("do_IRQ: stack overflow: %ld\n",
diff -puN arch/ppc64/kernel/misc.S~ppc64-get_SP arch/ppc64/kernel/misc.S
--- 25/arch/ppc64/kernel/misc.S~ppc64-get_SP	2004-02-21 20:58:31.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/misc.S	2004-02-21 20:58:31.000000000 -0800
@@ -383,10 +383,6 @@ _GLOBAL(abs)
 	neg	r3,r3
 10:	blr
 
-_GLOBAL(_get_SP)
-	mr	r3,r1		/* Close enough */
-	blr
-	
 _GLOBAL(_get_PVR)
 	mfspr	r3,PVR
 	blr
diff -puN arch/ppc64/kernel/process.c~ppc64-get_SP arch/ppc64/kernel/process.c
--- 25/arch/ppc64/kernel/process.c~ppc64-get_SP	2004-02-21 20:58:31.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/process.c	2004-02-21 20:58:31.000000000 -0800
@@ -162,7 +162,7 @@ struct task_struct *__switch_to(struct t
 	 * for that first.
 	 */
 	if ((cur_cpu_spec->cpu_features & CPU_FTR_SLB) &&
-	    GET_ESID((unsigned long)_get_SP()) != GET_ESID(PAGE_OFFSET)) {
+	    GET_ESID(__get_SP()) != GET_ESID(PAGE_OFFSET)) {
 		union {
 			unsigned long word0;
 			slb_dword0 data;
@@ -171,7 +171,7 @@ struct task_struct *__switch_to(struct t
 		esid_data.word0 = 0;
 		/* class bit is in valid field for slbie instruction */
 		esid_data.data.v = 1;
-		esid_data.data.esid = GET_ESID((unsigned long)_get_SP());
+		esid_data.data.esid = GET_ESID(__get_SP());
 		asm volatile("isync; slbie %0; isync" : : "r" (esid_data));
 	}
 	local_irq_restore(flags);
@@ -528,7 +528,7 @@ void show_stack(struct task_struct *p, u
 		if (p) {
 			sp = p->thread.ksp;
 		} else {
-			sp = (unsigned long)_get_SP();
+			sp = __get_SP();
 			p = current;
 		}
 	}
@@ -549,7 +549,7 @@ void show_stack(struct task_struct *p, u
 
 void dump_stack(void)
 {
-	show_stack(current, (unsigned long *)_get_SP());
+	show_stack(current, (unsigned long *)__get_SP());
 }
 
 EXPORT_SYMBOL(dump_stack);
diff -puN arch/ppc64/kernel/stab.c~ppc64-get_SP arch/ppc64/kernel/stab.c
--- 25/arch/ppc64/kernel/stab.c~ppc64-get_SP	2004-02-21 20:58:31.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/stab.c	2004-02-21 20:58:31.000000000 -0800
@@ -324,7 +324,7 @@ static void make_slbe(unsigned long esid
 			castout_entry = 1; 
 		asm volatile("slbmfee  %0,%1" : "=r" (esid_data) : "r" (entry));
 	} while (esid_data.data.v &&
-		 esid_data.data.esid == GET_ESID((unsigned long)_get_SP()));
+		 esid_data.data.esid == GET_ESID(__get_SP()));
 
 	get_paca()->xStab_data.next_round_robin = castout_entry;
 
diff -puN include/asm-ppc64/processor.h~ppc64-get_SP include/asm-ppc64/processor.h
--- 25/include/asm-ppc64/processor.h~ppc64-get_SP	2004-02-21 20:58:31.000000000 -0800
+++ 25-akpm/include/asm-ppc64/processor.h	2004-02-21 20:58:31.000000000 -0800
@@ -475,7 +475,8 @@ static inline void set_tb(unsigned int u
 	mttbl(lower);
 }
 
-extern unsigned long *_get_SP(void);
+#define __get_SP()	({unsigned long sp; \
+			asm volatile("mr %0,1": "=r" (sp)); sp;})
 
 extern int have_of;
 

_