Commit bcf0b088 authored by Kumar Gala's avatar Kumar Gala

[POWERPC] Move to runtime allocated exception stacks

For the additonal exception levels (critical, debug, machine check) on
40x/book-e we were using "static" allocations of the stack in the
associated head.S.

Move to a runtime allocation to make the code a bit easier to read as
we mimic how we handle IRQ stacks.  Its also a bit easier to setup the
stack with a "dummy" thread_info in C code.
Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
Acked-by: default avatarPaul Mackerras <paulus@samba.org>
parent c054065b
...@@ -148,14 +148,14 @@ _ENTRY(crit_r11) ...@@ -148,14 +148,14 @@ _ENTRY(crit_r11)
mfcr r10; /* save CR in r10 for now */\ mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_SRR3; /* check whether user or kernel */\ mfspr r11,SPRN_SRR3; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \ andi. r11,r11,MSR_PR; \
lis r11,critical_stack_top@h; \ lis r11,critirq_ctx@ha; \
ori r11,r11,critical_stack_top@l; \ tophys(r11,r11); \
lwz r11,critirq_ctx@l(r11); \
beq 1f; \ beq 1f; \
/* COMING FROM USER MODE */ \ /* COMING FROM USER MODE */ \
mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
addi r11,r11,THREAD_SIZE; \ 1: addi r11,r11,THREAD_SIZE-INT_FRAME_SIZE; /* Alloc an excpt frm */\
1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
tophys(r11,r11); \ tophys(r11,r11); \
stw r10,_CCR(r11); /* save various registers */\ stw r10,_CCR(r11); /* save various registers */\
stw r12,GPR12(r11); \ stw r12,GPR12(r11); \
...@@ -996,16 +996,6 @@ empty_zero_page: ...@@ -996,16 +996,6 @@ empty_zero_page:
swapper_pg_dir: swapper_pg_dir:
.space PGD_TABLE_SIZE .space PGD_TABLE_SIZE
/* Stack for handling critical exceptions from kernel mode */
.section .bss
.align 12
exception_stack_bottom:
.space 4096
critical_stack_top:
.globl exception_stack_top
exception_stack_top:
/* Room for two PTE pointers, usually the kernel and current user pointers /* Room for two PTE pointers, usually the kernel and current user pointers
* to their respective root page table. * to their respective root page table.
*/ */
......
...@@ -737,15 +737,6 @@ empty_zero_page: ...@@ -737,15 +737,6 @@ empty_zero_page:
swapper_pg_dir: swapper_pg_dir:
.space PGD_TABLE_SIZE .space PGD_TABLE_SIZE
/* Reserved 4k for the critical exception stack & 4k for the machine
* check stack per CPU for kernel mode exceptions */
.section .bss
.align 12
exception_stack_bottom:
.space BOOKE_EXCEPTION_STACK_SIZE
.globl exception_stack_top
exception_stack_top:
/* /*
* Room for two PTE pointers, usually the kernel and current user pointers * Room for two PTE pointers, usually the kernel and current user pointers
* to their respective root page table. * to their respective root page table.
......
...@@ -43,9 +43,7 @@ ...@@ -43,9 +43,7 @@
SAVE_2GPRS(7, r11) SAVE_2GPRS(7, r11)
/* To handle the additional exception priority levels on 40x and Book-E /* To handle the additional exception priority levels on 40x and Book-E
* processors we allocate a 4k stack per additional priority level. The various * processors we allocate a stack per additional priority level.
* head_xxx.S files allocate space (exception_stack_top) for each priority's
* stack times the number of CPUs
* *
* On 40x critical is the only additional level * On 40x critical is the only additional level
* On 44x/e500 we have critical and machine check * On 44x/e500 we have critical and machine check
...@@ -61,36 +59,31 @@ ...@@ -61,36 +59,31 @@
* going to critical or their own debug level we aren't currently * going to critical or their own debug level we aren't currently
* providing configurations that micro-optimize space usage. * providing configurations that micro-optimize space usage.
*/ */
#ifdef CONFIG_44x
#define NUM_EXCEPTION_LVLS 2
#else
#define NUM_EXCEPTION_LVLS 3
#endif
#define BOOKE_EXCEPTION_STACK_SIZE (4096 * NUM_EXCEPTION_LVLS)
/* CRIT_SPRG only used in critical exception handling */ /* CRIT_SPRG only used in critical exception handling */
#define CRIT_SPRG SPRN_SPRG2 #define CRIT_SPRG SPRN_SPRG2
/* MCHECK_SPRG only used in machine check exception handling */ /* MCHECK_SPRG only used in machine check exception handling */
#define MCHECK_SPRG SPRN_SPRG6W #define MCHECK_SPRG SPRN_SPRG6W
#define MCHECK_STACK_TOP (exception_stack_top - 4096) #define MCHECK_STACK_BASE mcheckirq_ctx
#define CRIT_STACK_TOP (exception_stack_top) #define CRIT_STACK_BASE critirq_ctx
/* only on e200 for now */ /* only on e200 for now */
#define DEBUG_STACK_TOP (exception_stack_top - 8192) #define DEBUG_STACK_BASE dbgirq_ctx
#define DEBUG_SPRG SPRN_SPRG6W #define DEBUG_SPRG SPRN_SPRG6W
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
mfspr r8,SPRN_PIR; \ mfspr r8,SPRN_PIR; \
mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \ slwi r8,r8,2; \
neg r8,r8; \ addis r8,r8,level##_STACK_BASE@ha; \
addis r8,r8,level##_STACK_TOP@ha; \ lwz r8,level##_STACK_BASE@l(r8); \
addi r8,r8,level##_STACK_TOP@l addi r8,r8,THREAD_SIZE;
#else #else
#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
lis r8,level##_STACK_TOP@h; \ lis r8,level##_STACK_BASE@ha; \
ori r8,r8,level##_STACK_TOP@l lwz r8,level##_STACK_BASE@l(r8); \
addi r8,r8,THREAD_SIZE;
#endif #endif
/* /*
......
...@@ -1080,15 +1080,6 @@ empty_zero_page: ...@@ -1080,15 +1080,6 @@ empty_zero_page:
swapper_pg_dir: swapper_pg_dir:
.space PGD_TABLE_SIZE .space PGD_TABLE_SIZE
/* Reserved 4k for the critical exception stack & 4k for the machine
* check stack per CPU for kernel mode exceptions */
.section .bss
.align 12
exception_stack_bottom:
.space BOOKE_EXCEPTION_STACK_SIZE * NR_CPUS
.globl exception_stack_top
exception_stack_top:
/* /*
* Room for two PTE pointers, usually the kernel and current user pointers * Room for two PTE pointers, usually the kernel and current user pointers
* to their respective root page table. * to their respective root page table.
......
...@@ -356,9 +356,42 @@ void __init init_IRQ(void) ...@@ -356,9 +356,42 @@ void __init init_IRQ(void)
{ {
if (ppc_md.init_IRQ) if (ppc_md.init_IRQ)
ppc_md.init_IRQ(); ppc_md.init_IRQ();
exc_lvl_ctx_init();
irq_ctx_init(); irq_ctx_init();
} }
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
struct thread_info *critirq_ctx[NR_CPUS] __read_mostly;
struct thread_info *dbgirq_ctx[NR_CPUS] __read_mostly;
struct thread_info *mcheckirq_ctx[NR_CPUS] __read_mostly;
void exc_lvl_ctx_init(void)
{
struct thread_info *tp;
int i;
for_each_possible_cpu(i) {
memset((void *)critirq_ctx[i], 0, THREAD_SIZE);
tp = critirq_ctx[i];
tp->cpu = i;
tp->preempt_count = 0;
#ifdef CONFIG_BOOKE
memset((void *)dbgirq_ctx[i], 0, THREAD_SIZE);
tp = dbgirq_ctx[i];
tp->cpu = i;
tp->preempt_count = 0;
memset((void *)mcheckirq_ctx[i], 0, THREAD_SIZE);
tp = mcheckirq_ctx[i];
tp->cpu = i;
tp->preempt_count = HARDIRQ_OFFSET;
#endif
}
}
#endif
#ifdef CONFIG_IRQSTACKS #ifdef CONFIG_IRQSTACKS
struct thread_info *softirq_ctx[NR_CPUS] __read_mostly; struct thread_info *softirq_ctx[NR_CPUS] __read_mostly;
......
...@@ -248,6 +248,28 @@ static void __init irqstack_early_init(void) ...@@ -248,6 +248,28 @@ static void __init irqstack_early_init(void)
#define irqstack_early_init() #define irqstack_early_init()
#endif #endif
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
static void __init exc_lvl_early_init(void)
{
unsigned int i;
/* interrupt stacks must be in lowmem, we get that for free on ppc32
* as the lmb is limited to lowmem by LMB_REAL_LIMIT */
for_each_possible_cpu(i) {
critirq_ctx[i] = (struct thread_info *)
__va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
#ifdef CONFIG_BOOKE
dbgirq_ctx[i] = (struct thread_info *)
__va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
mcheckirq_ctx[i] = (struct thread_info *)
__va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
#endif
}
}
#else
#define exc_lvl_early_init()
#endif
/* Warning, IO base is not yet inited */ /* Warning, IO base is not yet inited */
void __init setup_arch(char **cmdline_p) void __init setup_arch(char **cmdline_p)
{ {
...@@ -305,6 +327,8 @@ void __init setup_arch(char **cmdline_p) ...@@ -305,6 +327,8 @@ void __init setup_arch(char **cmdline_p)
init_mm.end_data = (unsigned long) _edata; init_mm.end_data = (unsigned long) _edata;
init_mm.brk = klimit; init_mm.brk = klimit;
exc_lvl_early_init();
irqstack_early_init(); irqstack_early_init();
/* set up the bootmem stuff with available memory */ /* set up the bootmem stuff with available memory */
......
...@@ -619,6 +619,19 @@ struct pt_regs; ...@@ -619,6 +619,19 @@ struct pt_regs;
#define __ARCH_HAS_DO_SOFTIRQ #define __ARCH_HAS_DO_SOFTIRQ
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
/*
* Per-cpu stacks for handling critical, debug and machine check
* level interrupts.
*/
extern struct thread_info *critirq_ctx[NR_CPUS];
extern struct thread_info *dbgirq_ctx[NR_CPUS];
extern struct thread_info *mcheckirq_ctx[NR_CPUS];
extern void exc_lvl_ctx_init(void);
#else
#define exc_lvl_ctx_init()
#endif
#ifdef CONFIG_IRQSTACKS #ifdef CONFIG_IRQSTACKS
/* /*
* Per-cpu stacks for handling hard and soft interrupts. * Per-cpu stacks for handling hard and soft interrupts.
......
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