diff options
-rw-r--r-- | arch/powerpc/kernel/head_40x.S | 18 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_44x.S | 9 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_booke.h | 29 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_fsl_booke.S | 9 | ||||
-rw-r--r-- | arch/powerpc/kernel/irq.c | 33 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_32.c | 24 | ||||
-rw-r--r-- | include/asm-powerpc/irq.h | 13 |
7 files changed, 85 insertions, 50 deletions
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S index 8552e67e3a8b..f2cf60d38f78 100644 --- a/arch/powerpc/kernel/head_40x.S +++ b/arch/powerpc/kernel/head_40x.S | |||
@@ -148,14 +148,14 @@ _ENTRY(crit_r11) | |||
148 | mfcr r10; /* save CR in r10 for now */\ | 148 | mfcr r10; /* save CR in r10 for now */\ |
149 | mfspr r11,SPRN_SRR3; /* check whether user or kernel */\ | 149 | mfspr r11,SPRN_SRR3; /* check whether user or kernel */\ |
150 | andi. r11,r11,MSR_PR; \ | 150 | andi. r11,r11,MSR_PR; \ |
151 | lis r11,critical_stack_top@h; \ | 151 | lis r11,critirq_ctx@ha; \ |
152 | ori r11,r11,critical_stack_top@l; \ | 152 | tophys(r11,r11); \ |
153 | lwz r11,critirq_ctx@l(r11); \ | ||
153 | beq 1f; \ | 154 | beq 1f; \ |
154 | /* COMING FROM USER MODE */ \ | 155 | /* COMING FROM USER MODE */ \ |
155 | mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ | 156 | mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ |
156 | lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ | 157 | lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ |
157 | addi r11,r11,THREAD_SIZE; \ | 158 | 1: addi r11,r11,THREAD_SIZE-INT_FRAME_SIZE; /* Alloc an excpt frm */\ |
158 | 1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ | ||
159 | tophys(r11,r11); \ | 159 | tophys(r11,r11); \ |
160 | stw r10,_CCR(r11); /* save various registers */\ | 160 | stw r10,_CCR(r11); /* save various registers */\ |
161 | stw r12,GPR12(r11); \ | 161 | stw r12,GPR12(r11); \ |
@@ -996,16 +996,6 @@ empty_zero_page: | |||
996 | swapper_pg_dir: | 996 | swapper_pg_dir: |
997 | .space PGD_TABLE_SIZE | 997 | .space PGD_TABLE_SIZE |
998 | 998 | ||
999 | |||
1000 | /* Stack for handling critical exceptions from kernel mode */ | ||
1001 | .section .bss | ||
1002 | .align 12 | ||
1003 | exception_stack_bottom: | ||
1004 | .space 4096 | ||
1005 | critical_stack_top: | ||
1006 | .globl exception_stack_top | ||
1007 | exception_stack_top: | ||
1008 | |||
1009 | /* Room for two PTE pointers, usually the kernel and current user pointers | 999 | /* Room for two PTE pointers, usually the kernel and current user pointers |
1010 | * to their respective root page table. | 1000 | * to their respective root page table. |
1011 | */ | 1001 | */ |
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index c2b9dc4fce5d..47ea8affad23 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S | |||
@@ -737,15 +737,6 @@ empty_zero_page: | |||
737 | swapper_pg_dir: | 737 | swapper_pg_dir: |
738 | .space PGD_TABLE_SIZE | 738 | .space PGD_TABLE_SIZE |
739 | 739 | ||
740 | /* Reserved 4k for the critical exception stack & 4k for the machine | ||
741 | * check stack per CPU for kernel mode exceptions */ | ||
742 | .section .bss | ||
743 | .align 12 | ||
744 | exception_stack_bottom: | ||
745 | .space BOOKE_EXCEPTION_STACK_SIZE | ||
746 | .globl exception_stack_top | ||
747 | exception_stack_top: | ||
748 | |||
749 | /* | 740 | /* |
750 | * Room for two PTE pointers, usually the kernel and current user pointers | 741 | * Room for two PTE pointers, usually the kernel and current user pointers |
751 | * to their respective root page table. | 742 | * to their respective root page table. |
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h index 721faef87095..9eacf4ca442a 100644 --- a/arch/powerpc/kernel/head_booke.h +++ b/arch/powerpc/kernel/head_booke.h | |||
@@ -43,9 +43,7 @@ | |||
43 | SAVE_2GPRS(7, r11) | 43 | SAVE_2GPRS(7, r11) |
44 | 44 | ||
45 | /* To handle the additional exception priority levels on 40x and Book-E | 45 | /* To handle the additional exception priority levels on 40x and Book-E |
46 | * processors we allocate a 4k stack per additional priority level. The various | 46 | * processors we allocate a stack per additional priority level. |
47 | * head_xxx.S files allocate space (exception_stack_top) for each priority's | ||
48 | * stack times the number of CPUs | ||
49 | * | 47 | * |
50 | * On 40x critical is the only additional level | 48 | * On 40x critical is the only additional level |
51 | * On 44x/e500 we have critical and machine check | 49 | * On 44x/e500 we have critical and machine check |
@@ -61,36 +59,31 @@ | |||
61 | * going to critical or their own debug level we aren't currently | 59 | * going to critical or their own debug level we aren't currently |
62 | * providing configurations that micro-optimize space usage. | 60 | * providing configurations that micro-optimize space usage. |
63 | */ | 61 | */ |
64 | #ifdef CONFIG_44x | ||
65 | #define NUM_EXCEPTION_LVLS 2 | ||
66 | #else | ||
67 | #define NUM_EXCEPTION_LVLS 3 | ||
68 | #endif | ||
69 | #define BOOKE_EXCEPTION_STACK_SIZE (4096 * NUM_EXCEPTION_LVLS) | ||
70 | 62 | ||
71 | /* CRIT_SPRG only used in critical exception handling */ | 63 | /* CRIT_SPRG only used in critical exception handling */ |
72 | #define CRIT_SPRG SPRN_SPRG2 | 64 | #define CRIT_SPRG SPRN_SPRG2 |
73 | /* MCHECK_SPRG only used in machine check exception handling */ | 65 | /* MCHECK_SPRG only used in machine check exception handling */ |
74 | #define MCHECK_SPRG SPRN_SPRG6W | 66 | #define MCHECK_SPRG SPRN_SPRG6W |
75 | 67 | ||
76 | #define MCHECK_STACK_TOP (exception_stack_top - 4096) | 68 | #define MCHECK_STACK_BASE mcheckirq_ctx |
77 | #define CRIT_STACK_TOP (exception_stack_top) | 69 | #define CRIT_STACK_BASE critirq_ctx |
78 | 70 | ||
79 | /* only on e200 for now */ | 71 | /* only on e200 for now */ |
80 | #define DEBUG_STACK_TOP (exception_stack_top - 8192) | 72 | #define DEBUG_STACK_BASE dbgirq_ctx |
81 | #define DEBUG_SPRG SPRN_SPRG6W | 73 | #define DEBUG_SPRG SPRN_SPRG6W |
82 | 74 | ||
83 | #ifdef CONFIG_SMP | 75 | #ifdef CONFIG_SMP |
84 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ | 76 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ |
85 | mfspr r8,SPRN_PIR; \ | 77 | mfspr r8,SPRN_PIR; \ |
86 | mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \ | 78 | slwi r8,r8,2; \ |
87 | neg r8,r8; \ | 79 | addis r8,r8,level##_STACK_BASE@ha; \ |
88 | addis r8,r8,level##_STACK_TOP@ha; \ | 80 | lwz r8,level##_STACK_BASE@l(r8); \ |
89 | addi r8,r8,level##_STACK_TOP@l | 81 | addi r8,r8,THREAD_SIZE; |
90 | #else | 82 | #else |
91 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ | 83 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ |
92 | lis r8,level##_STACK_TOP@h; \ | 84 | lis r8,level##_STACK_BASE@ha; \ |
93 | ori r8,r8,level##_STACK_TOP@l | 85 | lwz r8,level##_STACK_BASE@l(r8); \ |
86 | addi r8,r8,THREAD_SIZE; | ||
94 | #endif | 87 | #endif |
95 | 88 | ||
96 | /* | 89 | /* |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index e581524d85bc..503f86030b6e 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -1080,15 +1080,6 @@ empty_zero_page: | |||
1080 | swapper_pg_dir: | 1080 | swapper_pg_dir: |
1081 | .space PGD_TABLE_SIZE | 1081 | .space PGD_TABLE_SIZE |
1082 | 1082 | ||
1083 | /* Reserved 4k for the critical exception stack & 4k for the machine | ||
1084 | * check stack per CPU for kernel mode exceptions */ | ||
1085 | .section .bss | ||
1086 | .align 12 | ||
1087 | exception_stack_bottom: | ||
1088 | .space BOOKE_EXCEPTION_STACK_SIZE * NR_CPUS | ||
1089 | .globl exception_stack_top | ||
1090 | exception_stack_top: | ||
1091 | |||
1092 | /* | 1083 | /* |
1093 | * Room for two PTE pointers, usually the kernel and current user pointers | 1084 | * Room for two PTE pointers, usually the kernel and current user pointers |
1094 | * to their respective root page table. | 1085 | * to their respective root page table. |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 2f73f705d564..b5199752ac60 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -356,9 +356,42 @@ void __init init_IRQ(void) | |||
356 | { | 356 | { |
357 | if (ppc_md.init_IRQ) | 357 | if (ppc_md.init_IRQ) |
358 | ppc_md.init_IRQ(); | 358 | ppc_md.init_IRQ(); |
359 | |||
360 | exc_lvl_ctx_init(); | ||
361 | |||
359 | irq_ctx_init(); | 362 | irq_ctx_init(); |
360 | } | 363 | } |
361 | 364 | ||
365 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) | ||
366 | struct thread_info *critirq_ctx[NR_CPUS] __read_mostly; | ||
367 | struct thread_info *dbgirq_ctx[NR_CPUS] __read_mostly; | ||
368 | struct thread_info *mcheckirq_ctx[NR_CPUS] __read_mostly; | ||
369 | |||
370 | void exc_lvl_ctx_init(void) | ||
371 | { | ||
372 | struct thread_info *tp; | ||
373 | int i; | ||
374 | |||
375 | for_each_possible_cpu(i) { | ||
376 | memset((void *)critirq_ctx[i], 0, THREAD_SIZE); | ||
377 | tp = critirq_ctx[i]; | ||
378 | tp->cpu = i; | ||
379 | tp->preempt_count = 0; | ||
380 | |||
381 | #ifdef CONFIG_BOOKE | ||
382 | memset((void *)dbgirq_ctx[i], 0, THREAD_SIZE); | ||
383 | tp = dbgirq_ctx[i]; | ||
384 | tp->cpu = i; | ||
385 | tp->preempt_count = 0; | ||
386 | |||
387 | memset((void *)mcheckirq_ctx[i], 0, THREAD_SIZE); | ||
388 | tp = mcheckirq_ctx[i]; | ||
389 | tp->cpu = i; | ||
390 | tp->preempt_count = HARDIRQ_OFFSET; | ||
391 | #endif | ||
392 | } | ||
393 | } | ||
394 | #endif | ||
362 | 395 | ||
363 | #ifdef CONFIG_IRQSTACKS | 396 | #ifdef CONFIG_IRQSTACKS |
364 | struct thread_info *softirq_ctx[NR_CPUS] __read_mostly; | 397 | struct thread_info *softirq_ctx[NR_CPUS] __read_mostly; |
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 5112a4aa801d..bef0be3fd98b 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -248,6 +248,28 @@ static void __init irqstack_early_init(void) | |||
248 | #define irqstack_early_init() | 248 | #define irqstack_early_init() |
249 | #endif | 249 | #endif |
250 | 250 | ||
251 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) | ||
252 | static void __init exc_lvl_early_init(void) | ||
253 | { | ||
254 | unsigned int i; | ||
255 | |||
256 | /* interrupt stacks must be in lowmem, we get that for free on ppc32 | ||
257 | * as the lmb is limited to lowmem by LMB_REAL_LIMIT */ | ||
258 | for_each_possible_cpu(i) { | ||
259 | critirq_ctx[i] = (struct thread_info *) | ||
260 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
261 | #ifdef CONFIG_BOOKE | ||
262 | dbgirq_ctx[i] = (struct thread_info *) | ||
263 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
264 | mcheckirq_ctx[i] = (struct thread_info *) | ||
265 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
266 | #endif | ||
267 | } | ||
268 | } | ||
269 | #else | ||
270 | #define exc_lvl_early_init() | ||
271 | #endif | ||
272 | |||
251 | /* Warning, IO base is not yet inited */ | 273 | /* Warning, IO base is not yet inited */ |
252 | void __init setup_arch(char **cmdline_p) | 274 | void __init setup_arch(char **cmdline_p) |
253 | { | 275 | { |
@@ -305,6 +327,8 @@ void __init setup_arch(char **cmdline_p) | |||
305 | init_mm.end_data = (unsigned long) _edata; | 327 | init_mm.end_data = (unsigned long) _edata; |
306 | init_mm.brk = klimit; | 328 | init_mm.brk = klimit; |
307 | 329 | ||
330 | exc_lvl_early_init(); | ||
331 | |||
308 | irqstack_early_init(); | 332 | irqstack_early_init(); |
309 | 333 | ||
310 | /* set up the bootmem stuff with available memory */ | 334 | /* set up the bootmem stuff with available memory */ |
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index 5089deb8fec3..1ef8e304e0ea 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h | |||
@@ -619,6 +619,19 @@ struct pt_regs; | |||
619 | 619 | ||
620 | #define __ARCH_HAS_DO_SOFTIRQ | 620 | #define __ARCH_HAS_DO_SOFTIRQ |
621 | 621 | ||
622 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) | ||
623 | /* | ||
624 | * Per-cpu stacks for handling critical, debug and machine check | ||
625 | * level interrupts. | ||
626 | */ | ||
627 | extern struct thread_info *critirq_ctx[NR_CPUS]; | ||
628 | extern struct thread_info *dbgirq_ctx[NR_CPUS]; | ||
629 | extern struct thread_info *mcheckirq_ctx[NR_CPUS]; | ||
630 | extern void exc_lvl_ctx_init(void); | ||
631 | #else | ||
632 | #define exc_lvl_ctx_init() | ||
633 | #endif | ||
634 | |||
622 | #ifdef CONFIG_IRQSTACKS | 635 | #ifdef CONFIG_IRQSTACKS |
623 | /* | 636 | /* |
624 | * Per-cpu stacks for handling hard and soft interrupts. | 637 | * Per-cpu stacks for handling hard and soft interrupts. |