diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-05-31 17:22:32 -0400 |
---|---|---|
committer | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-05-31 17:22:32 -0400 |
commit | ccea7a19e54349d4f40778304e1bb88da83d39e7 (patch) | |
tree | dd42dbff31b2dff8b226f1b61eff4b958fca5496 /arch/arm/kernel/entry-armv.S | |
parent | 49f680ea7bac5c679fb6374a326a164a3fba07cc (diff) |
[PATCH] ARM SMP: Fix vector entry
The current vector entry system does not allow for SMP. In
order to work around this, we need to eliminate our reliance
on the fixed save areas, which breaks the way we enable
alignment traps. This patch changes the way we handle the
save areas such that we can have one per CPU.
Signed-off-by: Russell King <rmk@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel/entry-armv.S')
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 172 |
1 files changed, 89 insertions, 83 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index cfb5cf5e48fc..78cf84cdc2ae 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -53,46 +53,62 @@ | |||
53 | /* | 53 | /* |
54 | * Invalid mode handlers | 54 | * Invalid mode handlers |
55 | */ | 55 | */ |
56 | .macro inv_entry, sym, reason | 56 | .macro inv_entry, reason |
57 | sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go | 57 | sub sp, sp, #S_FRAME_SIZE |
58 | stmia sp, {r0 - lr} @ Save XXX r0 - lr | 58 | stmib sp, {r1 - lr} |
59 | ldr r4, .LC\sym | ||
60 | mov r1, #\reason | 59 | mov r1, #\reason |
61 | .endm | 60 | .endm |
62 | 61 | ||
63 | __pabt_invalid: | 62 | __pabt_invalid: |
64 | inv_entry abt, BAD_PREFETCH | 63 | inv_entry BAD_PREFETCH |
65 | b 1f | 64 | b common_invalid |
66 | 65 | ||
67 | __dabt_invalid: | 66 | __dabt_invalid: |
68 | inv_entry abt, BAD_DATA | 67 | inv_entry BAD_DATA |
69 | b 1f | 68 | b common_invalid |
70 | 69 | ||
71 | __irq_invalid: | 70 | __irq_invalid: |
72 | inv_entry irq, BAD_IRQ | 71 | inv_entry BAD_IRQ |
73 | b 1f | 72 | b common_invalid |
74 | 73 | ||
75 | __und_invalid: | 74 | __und_invalid: |
76 | inv_entry und, BAD_UNDEFINSTR | 75 | inv_entry BAD_UNDEFINSTR |
76 | |||
77 | @ | ||
78 | @ XXX fall through to common_invalid | ||
79 | @ | ||
80 | |||
81 | @ | ||
82 | @ common_invalid - generic code for failed exception (re-entrant version of handlers) | ||
83 | @ | ||
84 | common_invalid: | ||
85 | zero_fp | ||
86 | |||
87 | ldmia r0, {r4 - r6} | ||
88 | add r0, sp, #S_PC @ here for interlock avoidance | ||
89 | mov r7, #-1 @ "" "" "" "" | ||
90 | str r4, [sp] @ save preserved r0 | ||
91 | stmia r0, {r5 - r7} @ lr_<exception>, | ||
92 | @ cpsr_<exception>, "old_r0" | ||
77 | 93 | ||
78 | 1: zero_fp | ||
79 | ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0 | ||
80 | add r4, sp, #S_PC | ||
81 | stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0 | ||
82 | mov r0, sp | 94 | mov r0, sp |
83 | and r2, r6, #31 @ int mode | 95 | and r2, r6, #0x1f |
84 | b bad_mode | 96 | b bad_mode |
85 | 97 | ||
86 | /* | 98 | /* |
87 | * SVC mode handlers | 99 | * SVC mode handlers |
88 | */ | 100 | */ |
89 | .macro svc_entry, sym | 101 | .macro svc_entry |
90 | sub sp, sp, #S_FRAME_SIZE | 102 | sub sp, sp, #S_FRAME_SIZE |
91 | stmia sp, {r0 - r12} @ save r0 - r12 | 103 | stmib sp, {r1 - r12} |
92 | ldr r2, .LC\sym | 104 | |
93 | add r0, sp, #S_FRAME_SIZE | 105 | ldmia r0, {r1 - r3} |
94 | ldmia r2, {r2 - r4} @ get pc, cpsr | 106 | add r5, sp, #S_SP @ here for interlock avoidance |
95 | add r5, sp, #S_SP | 107 | mov r4, #-1 @ "" "" "" "" |
108 | add r0, sp, #S_FRAME_SIZE @ "" "" "" "" | ||
109 | str r1, [sp] @ save the "real" r0 copied | ||
110 | @ from the exception stack | ||
111 | |||
96 | mov r1, lr | 112 | mov r1, lr |
97 | 113 | ||
98 | @ | 114 | @ |
@@ -109,7 +125,7 @@ __und_invalid: | |||
109 | 125 | ||
110 | .align 5 | 126 | .align 5 |
111 | __dabt_svc: | 127 | __dabt_svc: |
112 | svc_entry abt | 128 | svc_entry |
113 | 129 | ||
114 | @ | 130 | @ |
115 | @ get ready to re-enable interrupts if appropriate | 131 | @ get ready to re-enable interrupts if appropriate |
@@ -156,13 +172,15 @@ __dabt_svc: | |||
156 | 172 | ||
157 | .align 5 | 173 | .align 5 |
158 | __irq_svc: | 174 | __irq_svc: |
159 | svc_entry irq | 175 | svc_entry |
176 | |||
160 | #ifdef CONFIG_PREEMPT | 177 | #ifdef CONFIG_PREEMPT |
161 | get_thread_info tsk | 178 | get_thread_info tsk |
162 | ldr r8, [tsk, #TI_PREEMPT] @ get preempt count | 179 | ldr r8, [tsk, #TI_PREEMPT] @ get preempt count |
163 | add r7, r8, #1 @ increment it | 180 | add r7, r8, #1 @ increment it |
164 | str r7, [tsk, #TI_PREEMPT] | 181 | str r7, [tsk, #TI_PREEMPT] |
165 | #endif | 182 | #endif |
183 | |||
166 | irq_handler | 184 | irq_handler |
167 | #ifdef CONFIG_PREEMPT | 185 | #ifdef CONFIG_PREEMPT |
168 | ldr r0, [tsk, #TI_FLAGS] @ get flags | 186 | ldr r0, [tsk, #TI_FLAGS] @ get flags |
@@ -200,7 +218,7 @@ svc_preempt: | |||
200 | 218 | ||
201 | .align 5 | 219 | .align 5 |
202 | __und_svc: | 220 | __und_svc: |
203 | svc_entry und | 221 | svc_entry |
204 | 222 | ||
205 | @ | 223 | @ |
206 | @ call emulation code, which returns using r9 if it has emulated | 224 | @ call emulation code, which returns using r9 if it has emulated |
@@ -230,7 +248,7 @@ __und_svc: | |||
230 | 248 | ||
231 | .align 5 | 249 | .align 5 |
232 | __pabt_svc: | 250 | __pabt_svc: |
233 | svc_entry abt | 251 | svc_entry |
234 | 252 | ||
235 | @ | 253 | @ |
236 | @ re-enable interrupts if appropriate | 254 | @ re-enable interrupts if appropriate |
@@ -263,12 +281,6 @@ __pabt_svc: | |||
263 | ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr | 281 | ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr |
264 | 282 | ||
265 | .align 5 | 283 | .align 5 |
266 | .LCirq: | ||
267 | .word __temp_irq | ||
268 | .LCund: | ||
269 | .word __temp_und | ||
270 | .LCabt: | ||
271 | .word __temp_abt | ||
272 | .LCcralign: | 284 | .LCcralign: |
273 | .word cr_alignment | 285 | .word cr_alignment |
274 | #ifdef MULTI_ABORT | 286 | #ifdef MULTI_ABORT |
@@ -285,12 +297,16 @@ __pabt_svc: | |||
285 | /* | 297 | /* |
286 | * User mode handlers | 298 | * User mode handlers |
287 | */ | 299 | */ |
288 | .macro usr_entry, sym | 300 | .macro usr_entry |
289 | sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go | 301 | sub sp, sp, #S_FRAME_SIZE |
290 | stmia sp, {r0 - r12} @ save r0 - r12 | 302 | stmib sp, {r1 - r12} |
291 | ldr r7, .LC\sym | 303 | |
292 | add r5, sp, #S_PC | 304 | ldmia r0, {r1 - r3} |
293 | ldmia r7, {r2 - r4} @ Get USR pc, cpsr | 305 | add r0, sp, #S_PC @ here for interlock avoidance |
306 | mov r4, #-1 @ "" "" "" "" | ||
307 | |||
308 | str r1, [sp] @ save the "real" r0 copied | ||
309 | @ from the exception stack | ||
294 | 310 | ||
295 | #if __LINUX_ARM_ARCH__ < 6 | 311 | #if __LINUX_ARM_ARCH__ < 6 |
296 | @ make sure our user space atomic helper is aborted | 312 | @ make sure our user space atomic helper is aborted |
@@ -307,8 +323,8 @@ __pabt_svc: | |||
307 | @ | 323 | @ |
308 | @ Also, separately save sp_usr and lr_usr | 324 | @ Also, separately save sp_usr and lr_usr |
309 | @ | 325 | @ |
310 | stmia r5, {r2 - r4} | 326 | stmia r0, {r2 - r4} |
311 | stmdb r5, {sp, lr}^ | 327 | stmdb r0, {sp, lr}^ |
312 | 328 | ||
313 | @ | 329 | @ |
314 | @ Enable the alignment trap while in kernel mode | 330 | @ Enable the alignment trap while in kernel mode |
@@ -323,7 +339,7 @@ __pabt_svc: | |||
323 | 339 | ||
324 | .align 5 | 340 | .align 5 |
325 | __dabt_usr: | 341 | __dabt_usr: |
326 | usr_entry abt | 342 | usr_entry |
327 | 343 | ||
328 | @ | 344 | @ |
329 | @ Call the processor-specific abort handler: | 345 | @ Call the processor-specific abort handler: |
@@ -352,7 +368,7 @@ __dabt_usr: | |||
352 | 368 | ||
353 | .align 5 | 369 | .align 5 |
354 | __irq_usr: | 370 | __irq_usr: |
355 | usr_entry irq | 371 | usr_entry |
356 | 372 | ||
357 | get_thread_info tsk | 373 | get_thread_info tsk |
358 | #ifdef CONFIG_PREEMPT | 374 | #ifdef CONFIG_PREEMPT |
@@ -360,6 +376,7 @@ __irq_usr: | |||
360 | add r7, r8, #1 @ increment it | 376 | add r7, r8, #1 @ increment it |
361 | str r7, [tsk, #TI_PREEMPT] | 377 | str r7, [tsk, #TI_PREEMPT] |
362 | #endif | 378 | #endif |
379 | |||
363 | irq_handler | 380 | irq_handler |
364 | #ifdef CONFIG_PREEMPT | 381 | #ifdef CONFIG_PREEMPT |
365 | ldr r0, [tsk, #TI_PREEMPT] | 382 | ldr r0, [tsk, #TI_PREEMPT] |
@@ -367,6 +384,7 @@ __irq_usr: | |||
367 | teq r0, r7 | 384 | teq r0, r7 |
368 | strne r0, [r0, -r0] | 385 | strne r0, [r0, -r0] |
369 | #endif | 386 | #endif |
387 | |||
370 | mov why, #0 | 388 | mov why, #0 |
371 | b ret_to_user | 389 | b ret_to_user |
372 | 390 | ||
@@ -374,7 +392,7 @@ __irq_usr: | |||
374 | 392 | ||
375 | .align 5 | 393 | .align 5 |
376 | __und_usr: | 394 | __und_usr: |
377 | usr_entry und | 395 | usr_entry |
378 | 396 | ||
379 | tst r3, #PSR_T_BIT @ Thumb mode? | 397 | tst r3, #PSR_T_BIT @ Thumb mode? |
380 | bne fpundefinstr @ ignore FP | 398 | bne fpundefinstr @ ignore FP |
@@ -490,7 +508,7 @@ fpundefinstr: | |||
490 | 508 | ||
491 | .align 5 | 509 | .align 5 |
492 | __pabt_usr: | 510 | __pabt_usr: |
493 | usr_entry abt | 511 | usr_entry |
494 | 512 | ||
495 | enable_irq @ Enable interrupts | 513 | enable_irq @ Enable interrupts |
496 | mov r0, r2 @ address (pc) | 514 | mov r0, r2 @ address (pc) |
@@ -749,29 +767,41 @@ __kuser_helper_end: | |||
749 | * | 767 | * |
750 | * Common stub entry macro: | 768 | * Common stub entry macro: |
751 | * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC | 769 | * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC |
770 | * | ||
771 | * SP points to a minimal amount of processor-private memory, the address | ||
772 | * of which is copied into r0 for the mode specific abort handler. | ||
752 | */ | 773 | */ |
753 | .macro vector_stub, name, sym, correction=0 | 774 | .macro vector_stub, name, correction=0 |
754 | .align 5 | 775 | .align 5 |
755 | 776 | ||
756 | vector_\name: | 777 | vector_\name: |
757 | ldr r13, .LCs\sym | ||
758 | .if \correction | 778 | .if \correction |
759 | sub lr, lr, #\correction | 779 | sub lr, lr, #\correction |
760 | .endif | 780 | .endif |
761 | str lr, [r13] @ save lr_IRQ | 781 | |
782 | @ | ||
783 | @ Save r0, lr_<exception> (parent PC) and spsr_<exception> | ||
784 | @ (parent CPSR) | ||
785 | @ | ||
786 | stmia sp, {r0, lr} @ save r0, lr | ||
762 | mrs lr, spsr | 787 | mrs lr, spsr |
763 | str lr, [r13, #4] @ save spsr_IRQ | 788 | str lr, [sp, #8] @ save spsr |
789 | |||
764 | @ | 790 | @ |
765 | @ now branch to the relevant MODE handling routine | 791 | @ Prepare for SVC32 mode. IRQs remain disabled. |
766 | @ | 792 | @ |
767 | mrs r13, cpsr | 793 | mrs r0, cpsr |
768 | bic r13, r13, #MODE_MASK | 794 | bic r0, r0, #MODE_MASK |
769 | orr r13, r13, #SVC_MODE | 795 | orr r0, r0, #SVC_MODE |
770 | msr spsr_cxsf, r13 @ switch to SVC_32 mode | 796 | msr spsr_cxsf, r0 |
771 | 797 | ||
772 | and lr, lr, #15 | 798 | @ |
799 | @ the branch table must immediately follow this code | ||
800 | @ | ||
801 | mov r0, sp | ||
802 | and lr, lr, #0x0f | ||
773 | ldr lr, [pc, lr, lsl #2] | 803 | ldr lr, [pc, lr, lsl #2] |
774 | movs pc, lr @ Changes mode and branches | 804 | movs pc, lr @ branch to handler in SVC mode |
775 | .endm | 805 | .endm |
776 | 806 | ||
777 | .globl __stubs_start | 807 | .globl __stubs_start |
@@ -779,7 +809,7 @@ __stubs_start: | |||
779 | /* | 809 | /* |
780 | * Interrupt dispatcher | 810 | * Interrupt dispatcher |
781 | */ | 811 | */ |
782 | vector_stub irq, irq, 4 | 812 | vector_stub irq, 4 |
783 | 813 | ||
784 | .long __irq_usr @ 0 (USR_26 / USR_32) | 814 | .long __irq_usr @ 0 (USR_26 / USR_32) |
785 | .long __irq_invalid @ 1 (FIQ_26 / FIQ_32) | 815 | .long __irq_invalid @ 1 (FIQ_26 / FIQ_32) |
@@ -802,7 +832,7 @@ __stubs_start: | |||
802 | * Data abort dispatcher | 832 | * Data abort dispatcher |
803 | * Enter in ABT mode, spsr = USR CPSR, lr = USR PC | 833 | * Enter in ABT mode, spsr = USR CPSR, lr = USR PC |
804 | */ | 834 | */ |
805 | vector_stub dabt, abt, 8 | 835 | vector_stub dabt, 8 |
806 | 836 | ||
807 | .long __dabt_usr @ 0 (USR_26 / USR_32) | 837 | .long __dabt_usr @ 0 (USR_26 / USR_32) |
808 | .long __dabt_invalid @ 1 (FIQ_26 / FIQ_32) | 838 | .long __dabt_invalid @ 1 (FIQ_26 / FIQ_32) |
@@ -825,7 +855,7 @@ __stubs_start: | |||
825 | * Prefetch abort dispatcher | 855 | * Prefetch abort dispatcher |
826 | * Enter in ABT mode, spsr = USR CPSR, lr = USR PC | 856 | * Enter in ABT mode, spsr = USR CPSR, lr = USR PC |
827 | */ | 857 | */ |
828 | vector_stub pabt, abt, 4 | 858 | vector_stub pabt, 4 |
829 | 859 | ||
830 | .long __pabt_usr @ 0 (USR_26 / USR_32) | 860 | .long __pabt_usr @ 0 (USR_26 / USR_32) |
831 | .long __pabt_invalid @ 1 (FIQ_26 / FIQ_32) | 861 | .long __pabt_invalid @ 1 (FIQ_26 / FIQ_32) |
@@ -848,7 +878,7 @@ __stubs_start: | |||
848 | * Undef instr entry dispatcher | 878 | * Undef instr entry dispatcher |
849 | * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC | 879 | * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC |
850 | */ | 880 | */ |
851 | vector_stub und, und | 881 | vector_stub und |
852 | 882 | ||
853 | .long __und_usr @ 0 (USR_26 / USR_32) | 883 | .long __und_usr @ 0 (USR_26 / USR_32) |
854 | .long __und_invalid @ 1 (FIQ_26 / FIQ_32) | 884 | .long __und_invalid @ 1 (FIQ_26 / FIQ_32) |
@@ -902,13 +932,6 @@ vector_addrexcptn: | |||
902 | .LCvswi: | 932 | .LCvswi: |
903 | .word vector_swi | 933 | .word vector_swi |
904 | 934 | ||
905 | .LCsirq: | ||
906 | .word __temp_irq | ||
907 | .LCsund: | ||
908 | .word __temp_und | ||
909 | .LCsabt: | ||
910 | .word __temp_abt | ||
911 | |||
912 | .globl __stubs_end | 935 | .globl __stubs_end |
913 | __stubs_end: | 936 | __stubs_end: |
914 | 937 | ||
@@ -930,23 +953,6 @@ __vectors_end: | |||
930 | 953 | ||
931 | .data | 954 | .data |
932 | 955 | ||
933 | /* | ||
934 | * Do not reorder these, and do not insert extra data between... | ||
935 | */ | ||
936 | |||
937 | __temp_irq: | ||
938 | .word 0 @ saved lr_irq | ||
939 | .word 0 @ saved spsr_irq | ||
940 | .word -1 @ old_r0 | ||
941 | __temp_und: | ||
942 | .word 0 @ Saved lr_und | ||
943 | .word 0 @ Saved spsr_und | ||
944 | .word -1 @ old_r0 | ||
945 | __temp_abt: | ||
946 | .word 0 @ Saved lr_abt | ||
947 | .word 0 @ Saved spsr_abt | ||
948 | .word -1 @ old_r0 | ||
949 | |||
950 | .globl cr_alignment | 956 | .globl cr_alignment |
951 | .globl cr_no_alignment | 957 | .globl cr_no_alignment |
952 | cr_alignment: | 958 | cr_alignment: |