Commit fb9d4325 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: Fix __get_SP()

From: Anton Blanchard <anton@samba.org>

__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.
parent ebcfac4e
...@@ -579,7 +579,7 @@ int do_IRQ(struct pt_regs *regs) ...@@ -579,7 +579,7 @@ int do_IRQ(struct pt_regs *regs)
{ {
long sp; long sp;
sp = (unsigned long)_get_SP() & (THREAD_SIZE-1); sp = __get_SP() & (THREAD_SIZE-1);
if (unlikely(sp < (sizeof(struct thread_info) + 8192))) { if (unlikely(sp < (sizeof(struct thread_info) + 8192))) {
printk("do_IRQ: stack overflow: %ld\n", printk("do_IRQ: stack overflow: %ld\n",
......
...@@ -383,10 +383,6 @@ _GLOBAL(abs) ...@@ -383,10 +383,6 @@ _GLOBAL(abs)
neg r3,r3 neg r3,r3
10: blr 10: blr
_GLOBAL(_get_SP)
mr r3,r1 /* Close enough */
blr
_GLOBAL(_get_PVR) _GLOBAL(_get_PVR)
mfspr r3,PVR mfspr r3,PVR
blr blr
......
...@@ -162,7 +162,7 @@ struct task_struct *__switch_to(struct task_struct *prev, ...@@ -162,7 +162,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
* for that first. * for that first.
*/ */
if ((cur_cpu_spec->cpu_features & CPU_FTR_SLB) && 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 { union {
unsigned long word0; unsigned long word0;
slb_dword0 data; slb_dword0 data;
...@@ -171,7 +171,7 @@ struct task_struct *__switch_to(struct task_struct *prev, ...@@ -171,7 +171,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
esid_data.word0 = 0; esid_data.word0 = 0;
/* class bit is in valid field for slbie instruction */ /* class bit is in valid field for slbie instruction */
esid_data.data.v = 1; 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)); asm volatile("isync; slbie %0; isync" : : "r" (esid_data));
} }
local_irq_restore(flags); local_irq_restore(flags);
...@@ -528,7 +528,7 @@ void show_stack(struct task_struct *p, unsigned long *_sp) ...@@ -528,7 +528,7 @@ void show_stack(struct task_struct *p, unsigned long *_sp)
if (p) { if (p) {
sp = p->thread.ksp; sp = p->thread.ksp;
} else { } else {
sp = (unsigned long)_get_SP(); sp = __get_SP();
p = current; p = current;
} }
} }
...@@ -549,7 +549,7 @@ void show_stack(struct task_struct *p, unsigned long *_sp) ...@@ -549,7 +549,7 @@ void show_stack(struct task_struct *p, unsigned long *_sp)
void dump_stack(void) void dump_stack(void)
{ {
show_stack(current, (unsigned long *)_get_SP()); show_stack(current, (unsigned long *)__get_SP());
} }
EXPORT_SYMBOL(dump_stack); EXPORT_SYMBOL(dump_stack);
......
...@@ -324,7 +324,7 @@ static void make_slbe(unsigned long esid, unsigned long vsid, int large, ...@@ -324,7 +324,7 @@ static void make_slbe(unsigned long esid, unsigned long vsid, int large,
castout_entry = 1; castout_entry = 1;
asm volatile("slbmfee %0,%1" : "=r" (esid_data) : "r" (entry)); asm volatile("slbmfee %0,%1" : "=r" (esid_data) : "r" (entry));
} while (esid_data.data.v && } 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; get_paca()->xStab_data.next_round_robin = castout_entry;
......
...@@ -475,7 +475,8 @@ static inline void set_tb(unsigned int upper, unsigned int lower) ...@@ -475,7 +475,8 @@ static inline void set_tb(unsigned int upper, unsigned int lower)
mttbl(lower); 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; extern int have_of;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment