diff options
Diffstat (limited to 'arch/arm/kernel/entry-armv.S')
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 63 |
1 files changed, 57 insertions, 6 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 29dec080a604..a46d5b456765 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -11,8 +11,8 @@ | |||
11 | * | 11 | * |
12 | * Low-level vector interface routines | 12 | * Low-level vector interface routines |
13 | * | 13 | * |
14 | * Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction that causes | 14 | * Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction |
15 | * it to save wrong values... Be aware! | 15 | * that causes it to save wrong values... Be aware! |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <asm/memory.h> | 18 | #include <asm/memory.h> |
@@ -58,6 +58,12 @@ | |||
58 | 58 | ||
59 | .endm | 59 | .endm |
60 | 60 | ||
61 | #ifdef CONFIG_KPROBES | ||
62 | .section .kprobes.text,"ax",%progbits | ||
63 | #else | ||
64 | .text | ||
65 | #endif | ||
66 | |||
61 | /* | 67 | /* |
62 | * Invalid mode handlers | 68 | * Invalid mode handlers |
63 | */ | 69 | */ |
@@ -112,8 +118,8 @@ common_invalid: | |||
112 | #define SPFIX(code...) | 118 | #define SPFIX(code...) |
113 | #endif | 119 | #endif |
114 | 120 | ||
115 | .macro svc_entry | 121 | .macro svc_entry, stack_hole=0 |
116 | sub sp, sp, #S_FRAME_SIZE | 122 | sub sp, sp, #(S_FRAME_SIZE + \stack_hole) |
117 | SPFIX( tst sp, #4 ) | 123 | SPFIX( tst sp, #4 ) |
118 | SPFIX( bicne sp, sp, #4 ) | 124 | SPFIX( bicne sp, sp, #4 ) |
119 | stmib sp, {r1 - r12} | 125 | stmib sp, {r1 - r12} |
@@ -121,7 +127,7 @@ common_invalid: | |||
121 | ldmia r0, {r1 - r3} | 127 | ldmia r0, {r1 - r3} |
122 | add r5, sp, #S_SP @ here for interlock avoidance | 128 | add r5, sp, #S_SP @ here for interlock avoidance |
123 | mov r4, #-1 @ "" "" "" "" | 129 | mov r4, #-1 @ "" "" "" "" |
124 | add r0, sp, #S_FRAME_SIZE @ "" "" "" "" | 130 | add r0, sp, #(S_FRAME_SIZE + \stack_hole) |
125 | SPFIX( addne r0, r0, #4 ) | 131 | SPFIX( addne r0, r0, #4 ) |
126 | str r1, [sp] @ save the "real" r0 copied | 132 | str r1, [sp] @ save the "real" r0 copied |
127 | @ from the exception stack | 133 | @ from the exception stack |
@@ -242,7 +248,14 @@ svc_preempt: | |||
242 | 248 | ||
243 | .align 5 | 249 | .align 5 |
244 | __und_svc: | 250 | __und_svc: |
251 | #ifdef CONFIG_KPROBES | ||
252 | @ If a kprobe is about to simulate a "stmdb sp..." instruction, | ||
253 | @ it obviously needs free stack space which then will belong to | ||
254 | @ the saved context. | ||
255 | svc_entry 64 | ||
256 | #else | ||
245 | svc_entry | 257 | svc_entry |
258 | #endif | ||
246 | 259 | ||
247 | @ | 260 | @ |
248 | @ call emulation code, which returns using r9 if it has emulated | 261 | @ call emulation code, which returns using r9 if it has emulated |
@@ -480,6 +493,13 @@ __und_usr: | |||
480 | * co-processor instructions. However, we have to watch out | 493 | * co-processor instructions. However, we have to watch out |
481 | * for the ARM6/ARM7 SWI bug. | 494 | * for the ARM6/ARM7 SWI bug. |
482 | * | 495 | * |
496 | * NEON is a special case that has to be handled here. Not all | ||
497 | * NEON instructions are co-processor instructions, so we have | ||
498 | * to make a special case of checking for them. Plus, there's | ||
499 | * five groups of them, so we have a table of mask/opcode pairs | ||
500 | * to check against, and if any match then we branch off into the | ||
501 | * NEON handler code. | ||
502 | * | ||
483 | * Emulators may wish to make use of the following registers: | 503 | * Emulators may wish to make use of the following registers: |
484 | * r0 = instruction opcode. | 504 | * r0 = instruction opcode. |
485 | * r2 = PC+4 | 505 | * r2 = PC+4 |
@@ -488,6 +508,23 @@ __und_usr: | |||
488 | * lr = unrecognised instruction return address | 508 | * lr = unrecognised instruction return address |
489 | */ | 509 | */ |
490 | call_fpe: | 510 | call_fpe: |
511 | #ifdef CONFIG_NEON | ||
512 | adr r6, .LCneon_opcodes | ||
513 | 2: | ||
514 | ldr r7, [r6], #4 @ mask value | ||
515 | cmp r7, #0 @ end mask? | ||
516 | beq 1f | ||
517 | and r8, r0, r7 | ||
518 | ldr r7, [r6], #4 @ opcode bits matching in mask | ||
519 | cmp r8, r7 @ NEON instruction? | ||
520 | bne 2b | ||
521 | get_thread_info r10 | ||
522 | mov r7, #1 | ||
523 | strb r7, [r10, #TI_USED_CP + 10] @ mark CP#10 as used | ||
524 | strb r7, [r10, #TI_USED_CP + 11] @ mark CP#11 as used | ||
525 | b do_vfp @ let VFP handler handle this | ||
526 | 1: | ||
527 | #endif | ||
491 | tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 | 528 | tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 |
492 | #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) | 529 | #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) |
493 | and r8, r0, #0x0f000000 @ mask out op-code bits | 530 | and r8, r0, #0x0f000000 @ mask out op-code bits |
@@ -537,6 +574,20 @@ call_fpe: | |||
537 | mov pc, lr @ CP#14 (Debug) | 574 | mov pc, lr @ CP#14 (Debug) |
538 | mov pc, lr @ CP#15 (Control) | 575 | mov pc, lr @ CP#15 (Control) |
539 | 576 | ||
577 | #ifdef CONFIG_NEON | ||
578 | .align 6 | ||
579 | |||
580 | .LCneon_opcodes: | ||
581 | .word 0xfe000000 @ mask | ||
582 | .word 0xf2000000 @ opcode | ||
583 | |||
584 | .word 0xff100000 @ mask | ||
585 | .word 0xf4000000 @ opcode | ||
586 | |||
587 | .word 0x00000000 @ mask | ||
588 | .word 0x00000000 @ opcode | ||
589 | #endif | ||
590 | |||
540 | do_fpe: | 591 | do_fpe: |
541 | enable_irq | 592 | enable_irq |
542 | ldr r4, .LCfp | 593 | ldr r4, .LCfp |
@@ -555,7 +606,7 @@ do_fpe: | |||
555 | .data | 606 | .data |
556 | ENTRY(fp_enter) | 607 | ENTRY(fp_enter) |
557 | .word no_fp | 608 | .word no_fp |
558 | .text | 609 | .previous |
559 | 610 | ||
560 | no_fp: mov pc, lr | 611 | no_fp: mov pc, lr |
561 | 612 | ||