diff options
Diffstat (limited to 'arch/arm/mm/abort-lv4t.S')
-rw-r--r-- | arch/arm/mm/abort-lv4t.S | 141 |
1 files changed, 68 insertions, 73 deletions
diff --git a/arch/arm/mm/abort-lv4t.S b/arch/arm/mm/abort-lv4t.S index 9fb7b0e25ea1..f3982580c273 100644 --- a/arch/arm/mm/abort-lv4t.S +++ b/arch/arm/mm/abort-lv4t.S | |||
@@ -3,14 +3,11 @@ | |||
3 | /* | 3 | /* |
4 | * Function: v4t_late_abort | 4 | * Function: v4t_late_abort |
5 | * | 5 | * |
6 | * Params : r2 = address of aborted instruction | 6 | * Params : r2 = pt_regs |
7 | * : r3 = saved SPSR | 7 | * : r4 = aborted context pc |
8 | * : r5 = aborted context psr | ||
8 | * | 9 | * |
9 | * Returns : r0 = address of abort | 10 | * Returns : r4-r5, r10-r11, r13 preserved |
10 | * : r1 = FSR, bit 11 = write | ||
11 | * : r2-r8 = corrupted | ||
12 | * : r9 = preserved | ||
13 | * : sp = pointer to registers | ||
14 | * | 11 | * |
15 | * Purpose : obtain information about current aborted instruction. | 12 | * Purpose : obtain information about current aborted instruction. |
16 | * 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 |
@@ -18,7 +15,7 @@ | |||
18 | * picture. Unfortunately, this does happen. We live with it. | 15 | * picture. Unfortunately, this does happen. We live with it. |
19 | */ | 16 | */ |
20 | ENTRY(v4t_late_abort) | 17 | ENTRY(v4t_late_abort) |
21 | tst r3, #PSR_T_BIT @ check for thumb mode | 18 | tst r5, #PSR_T_BIT @ check for thumb mode |
22 | #ifdef CONFIG_CPU_CP15_MMU | 19 | #ifdef CONFIG_CPU_CP15_MMU |
23 | mrc p15, 0, r1, c5, c0, 0 @ get FSR | 20 | mrc p15, 0, r1, c5, c0, 0 @ get FSR |
24 | mrc p15, 0, r0, c6, c0, 0 @ get FAR | 21 | mrc p15, 0, r0, c6, c0, 0 @ get FAR |
@@ -28,7 +25,7 @@ ENTRY(v4t_late_abort) | |||
28 | mov r1, #0 | 25 | mov r1, #0 |
29 | #endif | 26 | #endif |
30 | bne .data_thumb_abort | 27 | bne .data_thumb_abort |
31 | ldr r8, [r2] @ read arm instruction | 28 | ldr r8, [r4] @ read arm instruction |
32 | tst r8, #1 << 20 @ L = 1 -> write? | 29 | tst r8, #1 << 20 @ L = 1 -> write? |
33 | orreq r1, r1, #1 << 11 @ yes. | 30 | orreq r1, r1, #1 << 11 @ yes. |
34 | and r7, r8, #15 << 24 | 31 | and r7, r8, #15 << 24 |
@@ -47,86 +44,84 @@ ENTRY(v4t_late_abort) | |||
47 | /* 9 */ b .data_arm_ldmstm @ ldm*b rn, <rlist> | 44 | /* 9 */ b .data_arm_ldmstm @ ldm*b rn, <rlist> |
48 | /* a */ b .data_unknown | 45 | /* a */ b .data_unknown |
49 | /* b */ b .data_unknown | 46 | /* b */ b .data_unknown |
50 | /* c */ mov pc, lr @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m | 47 | /* c */ b do_DataAbort @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m |
51 | /* d */ mov pc, lr @ ldc rd, [rn, #m] | 48 | /* d */ b do_DataAbort @ ldc rd, [rn, #m] |
52 | /* e */ b .data_unknown | 49 | /* e */ b .data_unknown |
53 | /* f */ | 50 | /* f */ |
54 | .data_unknown: @ Part of jumptable | 51 | .data_unknown: @ Part of jumptable |
55 | mov r0, r2 | 52 | mov r0, r4 |
56 | mov r1, r8 | 53 | mov r1, r8 |
57 | mov r2, sp | 54 | b baddataabort |
58 | bl baddataabort | ||
59 | b ret_from_exception | ||
60 | 55 | ||
61 | .data_arm_ldmstm: | 56 | .data_arm_ldmstm: |
62 | tst r8, #1 << 21 @ check writeback bit | 57 | tst r8, #1 << 21 @ check writeback bit |
63 | moveq pc, lr @ no writeback -> no fixup | 58 | beq do_DataAbort @ no writeback -> no fixup |
64 | mov r7, #0x11 | 59 | mov r7, #0x11 |
65 | orr r7, r7, #0x1100 | 60 | orr r7, r7, #0x1100 |
66 | and r6, r8, r7 | 61 | and r6, r8, r7 |
67 | and r2, r8, r7, lsl #1 | 62 | and r9, r8, r7, lsl #1 |
68 | add r6, r6, r2, lsr #1 | 63 | add r6, r6, r9, lsr #1 |
69 | and r2, r8, r7, lsl #2 | 64 | and r9, r8, r7, lsl #2 |
70 | add r6, r6, r2, lsr #2 | 65 | add r6, r6, r9, lsr #2 |
71 | and r2, r8, r7, lsl #3 | 66 | and r9, r8, r7, lsl #3 |
72 | add r6, r6, r2, lsr #3 | 67 | add r6, r6, r9, lsr #3 |
73 | add r6, r6, r6, lsr #8 | 68 | add r6, r6, r6, lsr #8 |
74 | add r6, r6, r6, lsr #4 | 69 | add r6, r6, r6, lsr #4 |
75 | and r6, r6, #15 @ r6 = no. of registers to transfer. | 70 | and r6, r6, #15 @ r6 = no. of registers to transfer. |
76 | and r5, r8, #15 << 16 @ Extract 'n' from instruction | 71 | and r9, r8, #15 << 16 @ Extract 'n' from instruction |
77 | ldr r7, [sp, r5, lsr #14] @ Get register 'Rn' | 72 | ldr r7, [r2, r9, lsr #14] @ Get register 'Rn' |
78 | tst r8, #1 << 23 @ Check U bit | 73 | tst r8, #1 << 23 @ Check U bit |
79 | subne r7, r7, r6, lsl #2 @ Undo increment | 74 | subne r7, r7, r6, lsl #2 @ Undo increment |
80 | addeq r7, r7, r6, lsl #2 @ Undo decrement | 75 | addeq r7, r7, r6, lsl #2 @ Undo decrement |
81 | str r7, [sp, r5, lsr #14] @ Put register 'Rn' | 76 | str r7, [r2, r9, lsr #14] @ Put register 'Rn' |
82 | mov pc, lr | 77 | b do_DataAbort |
83 | 78 | ||
84 | .data_arm_lateldrhpre: | 79 | .data_arm_lateldrhpre: |
85 | tst r8, #1 << 21 @ Check writeback bit | 80 | tst r8, #1 << 21 @ Check writeback bit |
86 | moveq pc, lr @ No writeback -> no fixup | 81 | beq do_DataAbort @ No writeback -> no fixup |
87 | .data_arm_lateldrhpost: | 82 | .data_arm_lateldrhpost: |
88 | and r5, r8, #0x00f @ get Rm / low nibble of immediate value | 83 | and r9, r8, #0x00f @ get Rm / low nibble of immediate value |
89 | tst r8, #1 << 22 @ if (immediate offset) | 84 | tst r8, #1 << 22 @ if (immediate offset) |
90 | andne r6, r8, #0xf00 @ { immediate high nibble | 85 | andne r6, r8, #0xf00 @ { immediate high nibble |
91 | orrne r6, r5, r6, lsr #4 @ combine nibbles } else | 86 | orrne r6, r9, r6, lsr #4 @ combine nibbles } else |
92 | ldreq r6, [sp, r5, lsl #2] @ { load Rm value } | 87 | ldreq r6, [r2, r9, lsl #2] @ { load Rm value } |
93 | .data_arm_apply_r6_and_rn: | 88 | .data_arm_apply_r6_and_rn: |
94 | and r5, r8, #15 << 16 @ Extract 'n' from instruction | 89 | and r9, r8, #15 << 16 @ Extract 'n' from instruction |
95 | ldr r7, [sp, r5, lsr #14] @ Get register 'Rn' | 90 | ldr r7, [r2, r9, lsr #14] @ Get register 'Rn' |
96 | tst r8, #1 << 23 @ Check U bit | 91 | tst r8, #1 << 23 @ Check U bit |
97 | subne r7, r7, r6 @ Undo incrmenet | 92 | subne r7, r7, r6 @ Undo incrmenet |
98 | addeq r7, r7, r6 @ Undo decrement | 93 | addeq r7, r7, r6 @ Undo decrement |
99 | str r7, [sp, r5, lsr #14] @ Put register 'Rn' | 94 | str r7, [r2, r9, lsr #14] @ Put register 'Rn' |
100 | mov pc, lr | 95 | b do_DataAbort |
101 | 96 | ||
102 | .data_arm_lateldrpreconst: | 97 | .data_arm_lateldrpreconst: |
103 | tst r8, #1 << 21 @ check writeback bit | 98 | tst r8, #1 << 21 @ check writeback bit |
104 | moveq pc, lr @ no writeback -> no fixup | 99 | beq do_DataAbort @ no writeback -> no fixup |
105 | .data_arm_lateldrpostconst: | 100 | .data_arm_lateldrpostconst: |
106 | movs r2, r8, lsl #20 @ Get offset | 101 | movs r6, r8, lsl #20 @ Get offset |
107 | moveq pc, lr @ zero -> no fixup | 102 | beq do_DataAbort @ zero -> no fixup |
108 | and r5, r8, #15 << 16 @ Extract 'n' from instruction | 103 | and r9, r8, #15 << 16 @ Extract 'n' from instruction |
109 | ldr r7, [sp, r5, lsr #14] @ Get register 'Rn' | 104 | ldr r7, [r2, r9, lsr #14] @ Get register 'Rn' |
110 | tst r8, #1 << 23 @ Check U bit | 105 | tst r8, #1 << 23 @ Check U bit |
111 | subne r7, r7, r2, lsr #20 @ Undo increment | 106 | subne r7, r7, r6, lsr #20 @ Undo increment |
112 | addeq r7, r7, r2, lsr #20 @ Undo decrement | 107 | addeq r7, r7, r6, lsr #20 @ Undo decrement |
113 | str r7, [sp, r5, lsr #14] @ Put register 'Rn' | 108 | str r7, [r2, r9, lsr #14] @ Put register 'Rn' |
114 | mov pc, lr | 109 | b do_DataAbort |
115 | 110 | ||
116 | .data_arm_lateldrprereg: | 111 | .data_arm_lateldrprereg: |
117 | tst r8, #1 << 21 @ check writeback bit | 112 | tst r8, #1 << 21 @ check writeback bit |
118 | moveq pc, lr @ no writeback -> no fixup | 113 | beq do_DataAbort @ no writeback -> no fixup |
119 | .data_arm_lateldrpostreg: | 114 | .data_arm_lateldrpostreg: |
120 | and r7, r8, #15 @ Extract 'm' from instruction | 115 | and r7, r8, #15 @ Extract 'm' from instruction |
121 | ldr r6, [sp, r7, lsl #2] @ Get register 'Rm' | 116 | ldr r6, [r2, r7, lsl #2] @ Get register 'Rm' |
122 | mov r5, r8, lsr #7 @ get shift count | 117 | mov r9, r8, lsr #7 @ get shift count |
123 | ands r5, r5, #31 | 118 | ands r9, r9, #31 |
124 | and r7, r8, #0x70 @ get shift type | 119 | and r7, r8, #0x70 @ get shift type |
125 | orreq r7, r7, #8 @ shift count = 0 | 120 | orreq r7, r7, #8 @ shift count = 0 |
126 | add pc, pc, r7 | 121 | add pc, pc, r7 |
127 | nop | 122 | nop |
128 | 123 | ||
129 | mov r6, r6, lsl r5 @ 0: LSL #!0 | 124 | mov r6, r6, lsl r9 @ 0: LSL #!0 |
130 | b .data_arm_apply_r6_and_rn | 125 | b .data_arm_apply_r6_and_rn |
131 | b .data_arm_apply_r6_and_rn @ 1: LSL #0 | 126 | b .data_arm_apply_r6_and_rn @ 1: LSL #0 |
132 | nop | 127 | nop |
@@ -134,7 +129,7 @@ ENTRY(v4t_late_abort) | |||
134 | nop | 129 | nop |
135 | b .data_unknown @ 3: MUL? | 130 | b .data_unknown @ 3: MUL? |
136 | nop | 131 | nop |
137 | mov r6, r6, lsr r5 @ 4: LSR #!0 | 132 | mov r6, r6, lsr r9 @ 4: LSR #!0 |
138 | b .data_arm_apply_r6_and_rn | 133 | b .data_arm_apply_r6_and_rn |
139 | mov r6, r6, lsr #32 @ 5: LSR #32 | 134 | mov r6, r6, lsr #32 @ 5: LSR #32 |
140 | b .data_arm_apply_r6_and_rn | 135 | b .data_arm_apply_r6_and_rn |
@@ -142,7 +137,7 @@ ENTRY(v4t_late_abort) | |||
142 | nop | 137 | nop |
143 | b .data_unknown @ 7: MUL? | 138 | b .data_unknown @ 7: MUL? |
144 | nop | 139 | nop |
145 | mov r6, r6, asr r5 @ 8: ASR #!0 | 140 | mov r6, r6, asr r9 @ 8: ASR #!0 |
146 | b .data_arm_apply_r6_and_rn | 141 | b .data_arm_apply_r6_and_rn |
147 | mov r6, r6, asr #32 @ 9: ASR #32 | 142 | mov r6, r6, asr #32 @ 9: ASR #32 |
148 | b .data_arm_apply_r6_and_rn | 143 | b .data_arm_apply_r6_and_rn |
@@ -150,7 +145,7 @@ ENTRY(v4t_late_abort) | |||
150 | nop | 145 | nop |
151 | b .data_unknown @ B: MUL? | 146 | b .data_unknown @ B: MUL? |
152 | nop | 147 | nop |
153 | mov r6, r6, ror r5 @ C: ROR #!0 | 148 | mov r6, r6, ror r9 @ C: ROR #!0 |
154 | b .data_arm_apply_r6_and_rn | 149 | b .data_arm_apply_r6_and_rn |
155 | mov r6, r6, rrx @ D: RRX | 150 | mov r6, r6, rrx @ D: RRX |
156 | b .data_arm_apply_r6_and_rn | 151 | b .data_arm_apply_r6_and_rn |
@@ -159,7 +154,7 @@ ENTRY(v4t_late_abort) | |||
159 | b .data_unknown @ F: MUL? | 154 | b .data_unknown @ F: MUL? |
160 | 155 | ||
161 | .data_thumb_abort: | 156 | .data_thumb_abort: |
162 | ldrh r8, [r2] @ read instruction | 157 | ldrh r8, [r4] @ read instruction |
163 | tst r8, #1 << 11 @ L = 1 -> write? | 158 | tst r8, #1 << 11 @ L = 1 -> write? |
164 | orreq r1, r1, #1 << 8 @ yes | 159 | orreq r1, r1, #1 << 8 @ yes |
165 | and r7, r8, #15 << 12 | 160 | and r7, r8, #15 << 12 |
@@ -172,10 +167,10 @@ ENTRY(v4t_late_abort) | |||
172 | /* 3 */ b .data_unknown | 167 | /* 3 */ b .data_unknown |
173 | /* 4 */ b .data_unknown | 168 | /* 4 */ b .data_unknown |
174 | /* 5 */ b .data_thumb_reg | 169 | /* 5 */ b .data_thumb_reg |
175 | /* 6 */ mov pc, lr | 170 | /* 6 */ b do_DataAbort |
176 | /* 7 */ mov pc, lr | 171 | /* 7 */ b do_DataAbort |
177 | /* 8 */ mov pc, lr | 172 | /* 8 */ b do_DataAbort |
178 | /* 9 */ mov pc, lr | 173 | /* 9 */ b do_DataAbort |
179 | /* A */ b .data_unknown | 174 | /* A */ b .data_unknown |
180 | /* B */ b .data_thumb_pushpop | 175 | /* B */ b .data_thumb_pushpop |
181 | /* C */ b .data_thumb_ldmstm | 176 | /* C */ b .data_thumb_ldmstm |
@@ -185,41 +180,41 @@ ENTRY(v4t_late_abort) | |||
185 | 180 | ||
186 | .data_thumb_reg: | 181 | .data_thumb_reg: |
187 | tst r8, #1 << 9 | 182 | tst r8, #1 << 9 |
188 | moveq pc, lr | 183 | beq do_DataAbort |
189 | tst r8, #1 << 10 @ If 'S' (signed) bit is set | 184 | tst r8, #1 << 10 @ If 'S' (signed) bit is set |
190 | movne r1, #0 @ it must be a load instr | 185 | movne r1, #0 @ it must be a load instr |
191 | mov pc, lr | 186 | b do_DataAbort |
192 | 187 | ||
193 | .data_thumb_pushpop: | 188 | .data_thumb_pushpop: |
194 | tst r8, #1 << 10 | 189 | tst r8, #1 << 10 |
195 | beq .data_unknown | 190 | beq .data_unknown |
196 | and r6, r8, #0x55 @ hweight8(r8) + R bit | 191 | and r6, r8, #0x55 @ hweight8(r8) + R bit |
197 | and r2, r8, #0xaa | 192 | and r9, r8, #0xaa |
198 | add r6, r6, r2, lsr #1 | 193 | add r6, r6, r9, lsr #1 |
199 | and r2, r6, #0xcc | 194 | and r9, r6, #0xcc |
200 | and r6, r6, #0x33 | 195 | and r6, r6, #0x33 |
201 | add r6, r6, r2, lsr #2 | 196 | add r6, r6, r9, lsr #2 |
202 | movs r7, r8, lsr #9 @ C = r8 bit 8 (R bit) | 197 | movs r7, r8, lsr #9 @ C = r8 bit 8 (R bit) |
203 | adc r6, r6, r6, lsr #4 @ high + low nibble + R bit | 198 | adc r6, r6, r6, lsr #4 @ high + low nibble + R bit |
204 | and r6, r6, #15 @ number of regs to transfer | 199 | and r6, r6, #15 @ number of regs to transfer |
205 | ldr r7, [sp, #13 << 2] | 200 | ldr r7, [r2, #13 << 2] |
206 | tst r8, #1 << 11 | 201 | tst r8, #1 << 11 |
207 | addeq r7, r7, r6, lsl #2 @ increment SP if PUSH | 202 | addeq r7, r7, r6, lsl #2 @ increment SP if PUSH |
208 | subne r7, r7, r6, lsl #2 @ decrement SP if POP | 203 | subne r7, r7, r6, lsl #2 @ decrement SP if POP |
209 | str r7, [sp, #13 << 2] | 204 | str r7, [r2, #13 << 2] |
210 | mov pc, lr | 205 | b do_DataAbort |
211 | 206 | ||
212 | .data_thumb_ldmstm: | 207 | .data_thumb_ldmstm: |
213 | and r6, r8, #0x55 @ hweight8(r8) | 208 | and r6, r8, #0x55 @ hweight8(r8) |
214 | and r2, r8, #0xaa | 209 | and r9, r8, #0xaa |
215 | add r6, r6, r2, lsr #1 | 210 | add r6, r6, r9, lsr #1 |
216 | and r2, r6, #0xcc | 211 | and r9, r6, #0xcc |
217 | and r6, r6, #0x33 | 212 | and r6, r6, #0x33 |
218 | add r6, r6, r2, lsr #2 | 213 | add r6, r6, r9, lsr #2 |
219 | add r6, r6, r6, lsr #4 | 214 | add r6, r6, r6, lsr #4 |
220 | and r5, r8, #7 << 8 | 215 | and r9, r8, #7 << 8 |
221 | ldr r7, [sp, r5, lsr #6] | 216 | ldr r7, [r2, r9, lsr #6] |
222 | and r6, r6, #15 @ number of regs to transfer | 217 | and r6, r6, #15 @ number of regs to transfer |
223 | sub r7, r7, r6, lsl #2 @ always decrement | 218 | sub r7, r7, r6, lsl #2 @ always decrement |
224 | str r7, [sp, r5, lsr #6] | 219 | str r7, [r2, r9, lsr #6] |
225 | mov pc, lr | 220 | b do_DataAbort |