]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - arch/arm/mm/abort-lv4t.S
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[mirror_ubuntu-jammy-kernel.git] / arch / arm / mm / abort-lv4t.S
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
1da177e4
LT
2#include <linux/linkage.h>
3#include <asm/assembler.h>
4/*
5 * Function: v4t_late_abort
6 *
da740472
RK
7 * Params : r2 = pt_regs
8 * : r4 = aborted context pc
3e287bec 9 * : r5 = aborted context psr
1da177e4 10 *
04946fb6 11 * Returns : r4-r5, r9-r11, r13 preserved
1da177e4
LT
12 *
13 * Purpose : obtain information about current aborted instruction.
14 * Note: we read user space. This means we might cause a data
15 * abort here if the I-TLB and D-TLB aren't seeing the same
16 * picture. Unfortunately, this does happen. We live with it.
17 */
18ENTRY(v4t_late_abort)
3e287bec 19 tst r5, #PSR_T_BIT @ check for thumb mode
0f45d7f3 20#ifdef CONFIG_CPU_CP15_MMU
1da177e4
LT
21 mrc p15, 0, r1, c5, c0, 0 @ get FSR
22 mrc p15, 0, r0, c6, c0, 0 @ get FAR
0f45d7f3
HC
23 bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
24#else
25 mov r0, #0 @ clear r0, r1 (no FSR/FAR)
26 mov r1, #0
27#endif
1da177e4 28 bne .data_thumb_abort
3e287bec 29 ldr r8, [r4] @ read arm instruction
2190fed6 30 uaccess_disable ip @ disable userspace access
1da177e4
LT
31 tst r8, #1 << 20 @ L = 1 -> write?
32 orreq r1, r1, #1 << 11 @ yes.
33 and r7, r8, #15 << 24
34 add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
35 nop
36
37/* 0 */ b .data_arm_lateldrhpost @ ldrh rd, [rn], #m/rm
38/* 1 */ b .data_arm_lateldrhpre @ ldrh rd, [rn, #m/rm]
39/* 2 */ b .data_unknown
40/* 3 */ b .data_unknown
41/* 4 */ b .data_arm_lateldrpostconst @ ldr rd, [rn], #m
42/* 5 */ b .data_arm_lateldrpreconst @ ldr rd, [rn, #m]
43/* 6 */ b .data_arm_lateldrpostreg @ ldr rd, [rn], rm
44/* 7 */ b .data_arm_lateldrprereg @ ldr rd, [rn, rm]
45/* 8 */ b .data_arm_ldmstm @ ldm*a rn, <rlist>
46/* 9 */ b .data_arm_ldmstm @ ldm*b rn, <rlist>
47/* a */ b .data_unknown
48/* b */ b .data_unknown
da740472
RK
49/* c */ b do_DataAbort @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
50/* d */ b do_DataAbort @ ldc rd, [rn, #m]
1da177e4 51/* e */ b .data_unknown
04946fb6
RK
52/* f */ b .data_unknown
53
54.data_unknown_r9:
55 ldr r9, [sp], #4
1da177e4 56.data_unknown: @ Part of jumptable
3e287bec 57 mov r0, r4
1da177e4 58 mov r1, r8
da740472 59 b baddataabort
1da177e4
LT
60
61.data_arm_ldmstm:
62 tst r8, #1 << 21 @ check writeback bit
da740472 63 beq do_DataAbort @ no writeback -> no fixup
04946fb6 64 str r9, [sp, #-4]!
1da177e4
LT
65 mov r7, #0x11
66 orr r7, r7, #0x1100
67 and r6, r8, r7
0d147db0
RK
68 and r9, r8, r7, lsl #1
69 add r6, r6, r9, lsr #1
70 and r9, r8, r7, lsl #2
71 add r6, r6, r9, lsr #2
72 and r9, r8, r7, lsl #3
73 add r6, r6, r9, lsr #3
1da177e4
LT
74 add r6, r6, r6, lsr #8
75 add r6, r6, r6, lsr #4
76 and r6, r6, #15 @ r6 = no. of registers to transfer.
40f0b90a
RK
77 and r9, r8, #15 << 16 @ Extract 'n' from instruction
78 ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
1da177e4
LT
79 tst r8, #1 << 23 @ Check U bit
80 subne r7, r7, r6, lsl #2 @ Undo increment
81 addeq r7, r7, r6, lsl #2 @ Undo decrement
40f0b90a 82 str r7, [r2, r9, lsr #14] @ Put register 'Rn'
04946fb6 83 ldr r9, [sp], #4
da740472 84 b do_DataAbort
1da177e4
LT
85
86.data_arm_lateldrhpre:
87 tst r8, #1 << 21 @ Check writeback bit
da740472 88 beq do_DataAbort @ No writeback -> no fixup
1da177e4 89.data_arm_lateldrhpost:
04946fb6 90 str r9, [sp, #-4]!
40f0b90a 91 and r9, r8, #0x00f @ get Rm / low nibble of immediate value
1da177e4
LT
92 tst r8, #1 << 22 @ if (immediate offset)
93 andne r6, r8, #0xf00 @ { immediate high nibble
40f0b90a
RK
94 orrne r6, r9, r6, lsr #4 @ combine nibbles } else
95 ldreq r6, [r2, r9, lsl #2] @ { load Rm value }
1da177e4 96.data_arm_apply_r6_and_rn:
40f0b90a
RK
97 and r9, r8, #15 << 16 @ Extract 'n' from instruction
98 ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
1da177e4
LT
99 tst r8, #1 << 23 @ Check U bit
100 subne r7, r7, r6 @ Undo incrmenet
101 addeq r7, r7, r6 @ Undo decrement
40f0b90a 102 str r7, [r2, r9, lsr #14] @ Put register 'Rn'
04946fb6 103 ldr r9, [sp], #4
da740472 104 b do_DataAbort
1da177e4
LT
105
106.data_arm_lateldrpreconst:
107 tst r8, #1 << 21 @ check writeback bit
da740472 108 beq do_DataAbort @ no writeback -> no fixup
1da177e4 109.data_arm_lateldrpostconst:
108f6af0 110 movs r6, r8, lsl #20 @ Get offset
da740472 111 beq do_DataAbort @ zero -> no fixup
04946fb6 112 str r9, [sp, #-4]!
40f0b90a
RK
113 and r9, r8, #15 << 16 @ Extract 'n' from instruction
114 ldr r7, [r2, r9, lsr #14] @ Get register 'Rn'
1da177e4 115 tst r8, #1 << 23 @ Check U bit
108f6af0
RK
116 subne r7, r7, r6, lsr #20 @ Undo increment
117 addeq r7, r7, r6, lsr #20 @ Undo decrement
40f0b90a 118 str r7, [r2, r9, lsr #14] @ Put register 'Rn'
04946fb6 119 ldr r9, [sp], #4
da740472 120 b do_DataAbort
1da177e4
LT
121
122.data_arm_lateldrprereg:
123 tst r8, #1 << 21 @ check writeback bit
da740472 124 beq do_DataAbort @ no writeback -> no fixup
1da177e4
LT
125.data_arm_lateldrpostreg:
126 and r7, r8, #15 @ Extract 'm' from instruction
e22c12f9 127 ldr r6, [r2, r7, lsl #2] @ Get register 'Rm'
04946fb6 128 str r9, [sp, #-4]!
40f0b90a
RK
129 mov r9, r8, lsr #7 @ get shift count
130 ands r9, r9, #31
1da177e4
LT
131 and r7, r8, #0x70 @ get shift type
132 orreq r7, r7, #8 @ shift count = 0
133 add pc, pc, r7
134 nop
135
40f0b90a 136 mov r6, r6, lsl r9 @ 0: LSL #!0
1da177e4
LT
137 b .data_arm_apply_r6_and_rn
138 b .data_arm_apply_r6_and_rn @ 1: LSL #0
139 nop
04946fb6 140 b .data_unknown_r9 @ 2: MUL?
1da177e4 141 nop
04946fb6 142 b .data_unknown_r9 @ 3: MUL?
1da177e4 143 nop
40f0b90a 144 mov r6, r6, lsr r9 @ 4: LSR #!0
1da177e4
LT
145 b .data_arm_apply_r6_and_rn
146 mov r6, r6, lsr #32 @ 5: LSR #32
147 b .data_arm_apply_r6_and_rn
04946fb6 148 b .data_unknown_r9 @ 6: MUL?
1da177e4 149 nop
04946fb6 150 b .data_unknown_r9 @ 7: MUL?
1da177e4 151 nop
40f0b90a 152 mov r6, r6, asr r9 @ 8: ASR #!0
1da177e4
LT
153 b .data_arm_apply_r6_and_rn
154 mov r6, r6, asr #32 @ 9: ASR #32
155 b .data_arm_apply_r6_and_rn
04946fb6 156 b .data_unknown_r9 @ A: MUL?
1da177e4 157 nop
04946fb6 158 b .data_unknown_r9 @ B: MUL?
1da177e4 159 nop
40f0b90a 160 mov r6, r6, ror r9 @ C: ROR #!0
1da177e4
LT
161 b .data_arm_apply_r6_and_rn
162 mov r6, r6, rrx @ D: RRX
163 b .data_arm_apply_r6_and_rn
04946fb6 164 b .data_unknown_r9 @ E: MUL?
1da177e4 165 nop
04946fb6 166 b .data_unknown_r9 @ F: MUL?
1da177e4
LT
167
168.data_thumb_abort:
3e287bec 169 ldrh r8, [r4] @ read instruction
2190fed6 170 uaccess_disable ip @ disable userspace access
1da177e4
LT
171 tst r8, #1 << 11 @ L = 1 -> write?
172 orreq r1, r1, #1 << 8 @ yes
173 and r7, r8, #15 << 12
174 add pc, pc, r7, lsr #10 @ lookup in table
175 nop
176
177/* 0 */ b .data_unknown
178/* 1 */ b .data_unknown
179/* 2 */ b .data_unknown
180/* 3 */ b .data_unknown
181/* 4 */ b .data_unknown
182/* 5 */ b .data_thumb_reg
da740472
RK
183/* 6 */ b do_DataAbort
184/* 7 */ b do_DataAbort
185/* 8 */ b do_DataAbort
186/* 9 */ b do_DataAbort
1da177e4
LT
187/* A */ b .data_unknown
188/* B */ b .data_thumb_pushpop
189/* C */ b .data_thumb_ldmstm
190/* D */ b .data_unknown
191/* E */ b .data_unknown
192/* F */ b .data_unknown
193
194.data_thumb_reg:
195 tst r8, #1 << 9
da740472 196 beq do_DataAbort
1da177e4
LT
197 tst r8, #1 << 10 @ If 'S' (signed) bit is set
198 movne r1, #0 @ it must be a load instr
da740472 199 b do_DataAbort
1da177e4
LT
200
201.data_thumb_pushpop:
202 tst r8, #1 << 10
203 beq .data_unknown
04946fb6 204 str r9, [sp, #-4]!
1da177e4 205 and r6, r8, #0x55 @ hweight8(r8) + R bit
0d147db0
RK
206 and r9, r8, #0xaa
207 add r6, r6, r9, lsr #1
208 and r9, r6, #0xcc
1da177e4 209 and r6, r6, #0x33
0d147db0 210 add r6, r6, r9, lsr #2
1da177e4
LT
211 movs r7, r8, lsr #9 @ C = r8 bit 8 (R bit)
212 adc r6, r6, r6, lsr #4 @ high + low nibble + R bit
213 and r6, r6, #15 @ number of regs to transfer
e22c12f9 214 ldr r7, [r2, #13 << 2]
1da177e4
LT
215 tst r8, #1 << 11
216 addeq r7, r7, r6, lsl #2 @ increment SP if PUSH
217 subne r7, r7, r6, lsl #2 @ decrement SP if POP
e22c12f9 218 str r7, [r2, #13 << 2]
04946fb6 219 ldr r9, [sp], #4
da740472 220 b do_DataAbort
1da177e4
LT
221
222.data_thumb_ldmstm:
04946fb6 223 str r9, [sp, #-4]!
1da177e4 224 and r6, r8, #0x55 @ hweight8(r8)
0d147db0
RK
225 and r9, r8, #0xaa
226 add r6, r6, r9, lsr #1
227 and r9, r6, #0xcc
1da177e4 228 and r6, r6, #0x33
0d147db0 229 add r6, r6, r9, lsr #2
1da177e4 230 add r6, r6, r6, lsr #4
40f0b90a
RK
231 and r9, r8, #7 << 8
232 ldr r7, [r2, r9, lsr #6]
1da177e4
LT
233 and r6, r6, #15 @ number of regs to transfer
234 sub r7, r7, r6, lsl #2 @ always decrement
40f0b90a 235 str r7, [r2, r9, lsr #6]
04946fb6 236 ldr r9, [sp], #4
da740472 237 b do_DataAbort