diff options
-rw-r--r-- | arch/arm/mm/abort-lv4t.S | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/arch/arm/mm/abort-lv4t.S b/arch/arm/mm/abort-lv4t.S index 6d8e8e3365d1..4cdfab31a0b6 100644 --- a/arch/arm/mm/abort-lv4t.S +++ b/arch/arm/mm/abort-lv4t.S | |||
@@ -7,7 +7,7 @@ | |||
7 | * : r4 = aborted context pc | 7 | * : r4 = aborted context pc |
8 | * : r5 = aborted context psr | 8 | * : r5 = aborted context psr |
9 | * | 9 | * |
10 | * Returns : r4-r5, r10-r11, r13 preserved | 10 | * Returns : r4-r5, r9-r11, r13 preserved |
11 | * | 11 | * |
12 | * Purpose : obtain information about current aborted instruction. | 12 | * Purpose : obtain information about current aborted instruction. |
13 | * Note: we read user space. This means we might cause a data | 13 | * Note: we read user space. This means we might cause a data |
@@ -48,7 +48,10 @@ ENTRY(v4t_late_abort) | |||
48 | /* c */ b do_DataAbort @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m | 48 | /* c */ b do_DataAbort @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m |
49 | /* d */ b do_DataAbort @ ldc rd, [rn, #m] | 49 | /* d */ b do_DataAbort @ ldc rd, [rn, #m] |
50 | /* e */ b .data_unknown | 50 | /* e */ b .data_unknown |
51 | /* f */ | 51 | /* f */ b .data_unknown |
52 | |||
53 | .data_unknown_r9: | ||
54 | ldr r9, [sp], #4 | ||
52 | .data_unknown: @ Part of jumptable | 55 | .data_unknown: @ Part of jumptable |
53 | mov r0, r4 | 56 | mov r0, r4 |
54 | mov r1, r8 | 57 | mov r1, r8 |
@@ -57,6 +60,7 @@ ENTRY(v4t_late_abort) | |||
57 | .data_arm_ldmstm: | 60 | .data_arm_ldmstm: |
58 | tst r8, #1 << 21 @ check writeback bit | 61 | tst r8, #1 << 21 @ check writeback bit |
59 | beq do_DataAbort @ no writeback -> no fixup | 62 | beq do_DataAbort @ no writeback -> no fixup |
63 | str r9, [sp, #-4]! | ||
60 | mov r7, #0x11 | 64 | mov r7, #0x11 |
61 | orr r7, r7, #0x1100 | 65 | orr r7, r7, #0x1100 |
62 | and r6, r8, r7 | 66 | and r6, r8, r7 |
@@ -75,12 +79,14 @@ ENTRY(v4t_late_abort) | |||
75 | subne r7, r7, r6, lsl #2 @ Undo increment | 79 | subne r7, r7, r6, lsl #2 @ Undo increment |
76 | addeq r7, r7, r6, lsl #2 @ Undo decrement | 80 | addeq r7, r7, r6, lsl #2 @ Undo decrement |
77 | str r7, [r2, r9, lsr #14] @ Put register 'Rn' | 81 | str r7, [r2, r9, lsr #14] @ Put register 'Rn' |
82 | ldr r9, [sp], #4 | ||
78 | b do_DataAbort | 83 | b do_DataAbort |
79 | 84 | ||
80 | .data_arm_lateldrhpre: | 85 | .data_arm_lateldrhpre: |
81 | tst r8, #1 << 21 @ Check writeback bit | 86 | tst r8, #1 << 21 @ Check writeback bit |
82 | beq do_DataAbort @ No writeback -> no fixup | 87 | beq do_DataAbort @ No writeback -> no fixup |
83 | .data_arm_lateldrhpost: | 88 | .data_arm_lateldrhpost: |
89 | str r9, [sp, #-4]! | ||
84 | and r9, r8, #0x00f @ get Rm / low nibble of immediate value | 90 | and r9, r8, #0x00f @ get Rm / low nibble of immediate value |
85 | tst r8, #1 << 22 @ if (immediate offset) | 91 | tst r8, #1 << 22 @ if (immediate offset) |
86 | andne r6, r8, #0xf00 @ { immediate high nibble | 92 | andne r6, r8, #0xf00 @ { immediate high nibble |
@@ -93,6 +99,7 @@ ENTRY(v4t_late_abort) | |||
93 | subne r7, r7, r6 @ Undo incrmenet | 99 | subne r7, r7, r6 @ Undo incrmenet |
94 | addeq r7, r7, r6 @ Undo decrement | 100 | addeq r7, r7, r6 @ Undo decrement |
95 | str r7, [r2, r9, lsr #14] @ Put register 'Rn' | 101 | str r7, [r2, r9, lsr #14] @ Put register 'Rn' |
102 | ldr r9, [sp], #4 | ||
96 | b do_DataAbort | 103 | b do_DataAbort |
97 | 104 | ||
98 | .data_arm_lateldrpreconst: | 105 | .data_arm_lateldrpreconst: |
@@ -101,12 +108,14 @@ ENTRY(v4t_late_abort) | |||
101 | .data_arm_lateldrpostconst: | 108 | .data_arm_lateldrpostconst: |
102 | movs r6, r8, lsl #20 @ Get offset | 109 | movs r6, r8, lsl #20 @ Get offset |
103 | beq do_DataAbort @ zero -> no fixup | 110 | beq do_DataAbort @ zero -> no fixup |
111 | str r9, [sp, #-4]! | ||
104 | and r9, r8, #15 << 16 @ Extract 'n' from instruction | 112 | and r9, r8, #15 << 16 @ Extract 'n' from instruction |
105 | ldr r7, [r2, r9, lsr #14] @ Get register 'Rn' | 113 | ldr r7, [r2, r9, lsr #14] @ Get register 'Rn' |
106 | tst r8, #1 << 23 @ Check U bit | 114 | tst r8, #1 << 23 @ Check U bit |
107 | subne r7, r7, r6, lsr #20 @ Undo increment | 115 | subne r7, r7, r6, lsr #20 @ Undo increment |
108 | addeq r7, r7, r6, lsr #20 @ Undo decrement | 116 | addeq r7, r7, r6, lsr #20 @ Undo decrement |
109 | str r7, [r2, r9, lsr #14] @ Put register 'Rn' | 117 | str r7, [r2, r9, lsr #14] @ Put register 'Rn' |
118 | ldr r9, [sp], #4 | ||
110 | b do_DataAbort | 119 | b do_DataAbort |
111 | 120 | ||
112 | .data_arm_lateldrprereg: | 121 | .data_arm_lateldrprereg: |
@@ -115,6 +124,7 @@ ENTRY(v4t_late_abort) | |||
115 | .data_arm_lateldrpostreg: | 124 | .data_arm_lateldrpostreg: |
116 | and r7, r8, #15 @ Extract 'm' from instruction | 125 | and r7, r8, #15 @ Extract 'm' from instruction |
117 | ldr r6, [r2, r7, lsl #2] @ Get register 'Rm' | 126 | ldr r6, [r2, r7, lsl #2] @ Get register 'Rm' |
127 | str r9, [sp, #-4]! | ||
118 | mov r9, r8, lsr #7 @ get shift count | 128 | mov r9, r8, lsr #7 @ get shift count |
119 | ands r9, r9, #31 | 129 | ands r9, r9, #31 |
120 | and r7, r8, #0x70 @ get shift type | 130 | and r7, r8, #0x70 @ get shift type |
@@ -126,33 +136,33 @@ ENTRY(v4t_late_abort) | |||
126 | b .data_arm_apply_r6_and_rn | 136 | b .data_arm_apply_r6_and_rn |
127 | b .data_arm_apply_r6_and_rn @ 1: LSL #0 | 137 | b .data_arm_apply_r6_and_rn @ 1: LSL #0 |
128 | nop | 138 | nop |
129 | b .data_unknown @ 2: MUL? | 139 | b .data_unknown_r9 @ 2: MUL? |
130 | nop | 140 | nop |
131 | b .data_unknown @ 3: MUL? | 141 | b .data_unknown_r9 @ 3: MUL? |
132 | nop | 142 | nop |
133 | mov r6, r6, lsr r9 @ 4: LSR #!0 | 143 | mov r6, r6, lsr r9 @ 4: LSR #!0 |
134 | b .data_arm_apply_r6_and_rn | 144 | b .data_arm_apply_r6_and_rn |
135 | mov r6, r6, lsr #32 @ 5: LSR #32 | 145 | mov r6, r6, lsr #32 @ 5: LSR #32 |
136 | b .data_arm_apply_r6_and_rn | 146 | b .data_arm_apply_r6_and_rn |
137 | b .data_unknown @ 6: MUL? | 147 | b .data_unknown_r9 @ 6: MUL? |
138 | nop | 148 | nop |
139 | b .data_unknown @ 7: MUL? | 149 | b .data_unknown_r9 @ 7: MUL? |
140 | nop | 150 | nop |
141 | mov r6, r6, asr r9 @ 8: ASR #!0 | 151 | mov r6, r6, asr r9 @ 8: ASR #!0 |
142 | b .data_arm_apply_r6_and_rn | 152 | b .data_arm_apply_r6_and_rn |
143 | mov r6, r6, asr #32 @ 9: ASR #32 | 153 | mov r6, r6, asr #32 @ 9: ASR #32 |
144 | b .data_arm_apply_r6_and_rn | 154 | b .data_arm_apply_r6_and_rn |
145 | b .data_unknown @ A: MUL? | 155 | b .data_unknown_r9 @ A: MUL? |
146 | nop | 156 | nop |
147 | b .data_unknown @ B: MUL? | 157 | b .data_unknown_r9 @ B: MUL? |
148 | nop | 158 | nop |
149 | mov r6, r6, ror r9 @ C: ROR #!0 | 159 | mov r6, r6, ror r9 @ C: ROR #!0 |
150 | b .data_arm_apply_r6_and_rn | 160 | b .data_arm_apply_r6_and_rn |
151 | mov r6, r6, rrx @ D: RRX | 161 | mov r6, r6, rrx @ D: RRX |
152 | b .data_arm_apply_r6_and_rn | 162 | b .data_arm_apply_r6_and_rn |
153 | b .data_unknown @ E: MUL? | 163 | b .data_unknown_r9 @ E: MUL? |
154 | nop | 164 | nop |
155 | b .data_unknown @ F: MUL? | 165 | b .data_unknown_r9 @ F: MUL? |
156 | 166 | ||
157 | .data_thumb_abort: | 167 | .data_thumb_abort: |
158 | ldrh r8, [r4] @ read instruction | 168 | ldrh r8, [r4] @ read instruction |
@@ -190,6 +200,7 @@ ENTRY(v4t_late_abort) | |||
190 | .data_thumb_pushpop: | 200 | .data_thumb_pushpop: |
191 | tst r8, #1 << 10 | 201 | tst r8, #1 << 10 |
192 | beq .data_unknown | 202 | beq .data_unknown |
203 | str r9, [sp, #-4]! | ||
193 | and r6, r8, #0x55 @ hweight8(r8) + R bit | 204 | and r6, r8, #0x55 @ hweight8(r8) + R bit |
194 | and r9, r8, #0xaa | 205 | and r9, r8, #0xaa |
195 | add r6, r6, r9, lsr #1 | 206 | add r6, r6, r9, lsr #1 |
@@ -204,9 +215,11 @@ ENTRY(v4t_late_abort) | |||
204 | addeq r7, r7, r6, lsl #2 @ increment SP if PUSH | 215 | addeq r7, r7, r6, lsl #2 @ increment SP if PUSH |
205 | subne r7, r7, r6, lsl #2 @ decrement SP if POP | 216 | subne r7, r7, r6, lsl #2 @ decrement SP if POP |
206 | str r7, [r2, #13 << 2] | 217 | str r7, [r2, #13 << 2] |
218 | ldr r9, [sp], #4 | ||
207 | b do_DataAbort | 219 | b do_DataAbort |
208 | 220 | ||
209 | .data_thumb_ldmstm: | 221 | .data_thumb_ldmstm: |
222 | str r9, [sp, #-4]! | ||
210 | and r6, r8, #0x55 @ hweight8(r8) | 223 | and r6, r8, #0x55 @ hweight8(r8) |
211 | and r9, r8, #0xaa | 224 | and r9, r8, #0xaa |
212 | add r6, r6, r9, lsr #1 | 225 | add r6, r6, r9, lsr #1 |
@@ -219,4 +232,5 @@ ENTRY(v4t_late_abort) | |||
219 | and r6, r6, #15 @ number of regs to transfer | 232 | and r6, r6, #15 @ number of regs to transfer |
220 | sub r7, r7, r6, lsl #2 @ always decrement | 233 | sub r7, r7, r6, lsl #2 @ always decrement |
221 | str r7, [r2, r9, lsr #6] | 234 | str r7, [r2, r9, lsr #6] |
235 | ldr r9, [sp], #4 | ||
222 | b do_DataAbort | 236 | b do_DataAbort |