diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2017-01-18 14:36:27 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2017-01-24 15:34:19 +0100 |
commit | 9bb6050d40b9936beda5cb1cd15040f6c1b07179 (patch) | |
tree | 03fa1ad2b5d20db4cae1d8f7b75deb4d98fbdeee /utils/hwstub/stub/asm | |
parent | f3cce72269703e983e4a4e6ec8dc9217b0c2b6fe (diff) | |
download | rockbox-9bb6050d40b9936beda5cb1cd15040f6c1b07179.tar.gz rockbox-9bb6050d40b9936beda5cb1cd15040f6c1b07179.zip |
hwstub: rewrite exception catching
Since we can catch exceptions like data aborts on read/write, it takes very
little to also catch exceptions in calls. When extending this with the catching
of illegal instructions, the call instruction now becomes much more robust and
also for address and instruction probing. Since we can catch several types of
exception, rename set_data_abort_jmp to set_exception_jmp. At the same time,
simplify the logic in read/write request handlers. Also fix a bug in ARM
jump code: it was using
stmia r1, {..., pc}
as if pc would get current pc + 8 but this is actually implementation defined
on older ARMs (typically pc + 12) and deprecated on newer ARMs, so rewrite the
code avoid that. The set_exception_jmp() function now also reports the exception
type.
Change-Id: Icd0dd52d2456b361b27c4776be09c3d13528ed93
Diffstat (limited to 'utils/hwstub/stub/asm')
-rw-r--r-- | utils/hwstub/stub/asm/arm/system.S | 28 | ||||
-rw-r--r-- | utils/hwstub/stub/asm/mips/system.S | 27 |
2 files changed, 30 insertions, 25 deletions
diff --git a/utils/hwstub/stub/asm/arm/system.S b/utils/hwstub/stub/asm/arm/system.S index df6b5a2e81..41551a8004 100644 --- a/utils/hwstub/stub/asm/arm/system.S +++ b/utils/hwstub/stub/asm/arm/system.S | |||
@@ -18,32 +18,33 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include "system.h" | ||
21 | 22 | ||
22 | /* Handling of data abort: | 23 | /* Handling of data abort: |
23 | * the code can register a "longjmp" buffer to restore the context in case of | 24 | * the code can register a "longjmp" buffer to restore the context in case of |
24 | * fault */ | 25 | * fault */ |
25 | .data | 26 | .data |
26 | data_abort_jmp_ctx_ptr: | 27 | exception_jmp_ctx_ptr: |
27 | /* buffer contains in order: cpsr,r4-r11,sp,lr,pc */ | 28 | /* buffer contains in order: cpsr,r4-r11,sp,lr,pc */ |
28 | .skip 48 /* = 4 * (cpsr + 11 registers) */ | 29 | .skip 48 /* = 4 * (cpsr + 11 registers) */ |
29 | 30 | ||
30 | .text | 31 | .text |
31 | /* Prototype: int set_data_abort_jmp() | 32 | /* Prototype: int set_exception_jmp() |
32 | * Return: 1 in case of data abort, 0 otherwise */ | 33 | * Return: !=0 in case of exception, 0 otherwise */ |
33 | .global set_data_abort_jmp | 34 | .global set_exception_jmp |
34 | set_data_abort_jmp: | 35 | set_exception_jmp: |
35 | mrs r2, cpsr | 36 | mrs r2, cpsr |
36 | ldr r1, =data_abort_jmp_ctx_ptr | 37 | ldr r1, =exception_jmp_ctx_ptr |
37 | mov r0, #0 | 38 | mov r0, #EXCEPTION_NONE /* nothing to report */ |
38 | stmia r1, {r2,r4-r11,sp,lr,pc} /* see PC note below */ | 39 | stmia r1!, {r2,r4-r11,sp,lr} /* see PC note below */ |
39 | bx lr | 40 | mov r3, pc /* see note below */ |
40 | mov r0, #1 /* <-- PC points here in stmia */ | 41 | str r3, [r1] /* store PC */ |
41 | bx lr | 42 | bx lr /* <-- PC points here in mov */ |
42 | 43 | ||
43 | .global data_abort_handler | 44 | .global data_abort_handler |
44 | data_abort_handler: | 45 | data_abort_handler: |
45 | /* restore everything from context */ | 46 | /* restore everything from context */ |
46 | ldr r1, =data_abort_jmp_ctx_ptr | 47 | ldr r1, =exception_jmp_ctx_ptr |
47 | /* NOTE: we need to restore sp_sys and lr_sys, for this we need the | 48 | /* NOTE: we need to restore sp_sys and lr_sys, for this we need the |
48 | * LDM Rn, {}^ | 49 | * LDM Rn, {}^ |
49 | * variant, but we cannot restore PC from it because ^ has a different | 50 | * variant, but we cannot restore PC from it because ^ has a different |
@@ -54,4 +55,5 @@ data_abort_handler: | |||
54 | * because we do not save the abort address and we don't use an abort stack */ | 55 | * because we do not save the abort address and we don't use an abort stack */ |
55 | ldmia r1, {r0,r4-r11,sp,lr}^ /* this variant cannot have writeback (r1!) */ | 56 | ldmia r1, {r0,r4-r11,sp,lr}^ /* this variant cannot have writeback (r1!) */ |
56 | msr spsr, r0 | 57 | msr spsr, r0 |
57 | ldmia r1, {r0,r4-r11,sp,lr,pc}^ /* reload some registers but we don't care */ | 58 | mov r0, #EXCEPTION_ADDR |
59 | ldmia r1, {r1,r4-r11,sp,lr,pc}^ /* reload some registers but we don't care */ | ||
diff --git a/utils/hwstub/stub/asm/mips/system.S b/utils/hwstub/stub/asm/mips/system.S index 2d89bde096..7f619c6edd 100644 --- a/utils/hwstub/stub/asm/mips/system.S +++ b/utils/hwstub/stub/asm/mips/system.S | |||
@@ -19,23 +19,24 @@ | |||
19 | ****************************************************************************/ | 19 | ****************************************************************************/ |
20 | #include "mips.h" | 20 | #include "mips.h" |
21 | #include "target-config.h" | 21 | #include "target-config.h" |
22 | #include "system.h" | ||
22 | 23 | ||
23 | /* Handling of data abort: | 24 | /* Handling of exception: |
24 | * the code can register a "longjmp" buffer to restore the context in case of | 25 | * the code can register a "longjmp" buffer to restore the context in case of |
25 | * fault */ | 26 | * fault */ |
26 | .data | 27 | .data |
27 | .global data_abort_jmp_ctx_ptr | 28 | .global exception_jmp_ctx_ptr |
28 | data_abort_jmp_ctx_ptr: | 29 | exception_jmp_ctx_ptr: |
29 | /* buffer contains in order: s0-s7, sp, s8, ra */ | 30 | /* buffer contains in order: s0-s7, sp, s8, ra */ |
30 | .skip 44 /* = 4 * (9 callee saved registers + sp + ra) */ | 31 | .skip 44 /* = 4 * (9 callee saved registers + sp + ra) */ |
31 | 32 | ||
32 | .set noreorder | 33 | .set noreorder |
33 | .section .icode, "ax", %progbits | 34 | .section .icode, "ax", %progbits |
34 | /* Prototype: int set_data_abort_jmp() | 35 | /* Prototype: int set_exception_jmp() |
35 | * Return: 1 in case of data abort, 0 otherwise */ | 36 | * Return: 1 in case of data abort, 0 otherwise */ |
36 | .global set_data_abort_jmp | 37 | .global set_exception_jmp |
37 | set_data_abort_jmp: | 38 | set_exception_jmp: |
38 | la v0, data_abort_jmp_ctx_ptr | 39 | la v0, exception_jmp_ctx_ptr |
39 | sw s0, 0(v0) | 40 | sw s0, 0(v0) |
40 | sw s1, 4(v0) | 41 | sw s1, 4(v0) |
41 | sw s2, 8(v0) | 42 | sw s2, 8(v0) |
@@ -50,10 +51,12 @@ set_data_abort_jmp: | |||
50 | jr ra | 51 | jr ra |
51 | move v0, zero | 52 | move v0, zero |
52 | 53 | ||
53 | /* restore context on read/write error, performs the interrupt return */ | 54 | /* restore context on read/write error, performs the interrupt return |
54 | .global restore_data_abort_jmp | 55 | * arguments: |
55 | restore_data_abort_jmp: | 56 | * a0: exception type (EXCEPTION_*) */ |
56 | la k1, data_abort_jmp_ctx_ptr | 57 | .global restore_exception_jmp |
58 | restore_exception_jmp: | ||
59 | la k1, exception_jmp_ctx_ptr | ||
57 | lw s0, 0(k1) | 60 | lw s0, 0(k1) |
58 | lw s1, 4(k1) | 61 | lw s1, 4(k1) |
59 | lw s2, 8(k1) | 62 | lw s2, 8(k1) |
@@ -73,7 +76,7 @@ la k1, data_abort_jmp_ctx_ptr | |||
73 | #else | 76 | #else |
74 | ehb | 77 | ehb |
75 | #endif | 78 | #endif |
76 | li v0, 1 | 79 | move v0, a0 /* set exception type */ |
77 | eret | 80 | eret |
78 | nop | 81 | nop |
79 | .set reorder | 82 | .set reorder |