forked from Minki/linux
[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: Kumar Gala <galak@kernel.crashing.org> Acked-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
c054065bc1
commit
bcf0b08807
@ -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:
|
|||||||
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:
|
|||||||
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 @@
|
|||||||
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 @@
|
|||||||
* 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:
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
#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)
|
|||||||
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;
|
|||||||
|
|
||||||
#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.
|
||||||
|
Loading…
Reference in New Issue
Block a user