~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mm/abort-lv4t.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 #include <linux/linkage.h>
  3 #include <asm/assembler.h>
  4 /*
  5  * Function: v4t_late_abort
  6  *
  7  * Params  : r2 = pt_regs
  8  *         : r4 = aborted context pc
  9  *         : r5 = aborted context psr
 10  *
 11  * Returns : r4-r5, r9-r11, r13 preserved
 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  */
 18 ENTRY(v4t_late_abort)
 19         tst     r5, #PSR_T_BIT                  @ check for thumb mode
 20 #ifdef CONFIG_CPU_CP15_MMU
 21         mrc     p15, 0, r1, c5, c0, 0           @ get FSR
 22         mrc     p15, 0, r0, c6, c0, 0           @ get FAR
 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
 28         bne     .data_thumb_abort
 29         ldr     r8, [r4]                        @ read arm instruction
 30         uaccess_disable ip                      @ disable userspace access
 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
 49 /* c */ b       do_DataAbort                    @ ldc   rd, [rn], #m    @ Same as ldr   rd, [rn], #m
 50 /* d */ b       do_DataAbort                    @ ldc   rd, [rn, #m]
 51 /* e */ b       .data_unknown
 52 /* f */ b       .data_unknown
 53 
 54 .data_unknown_r9:
 55         ldr     r9, [sp], #4
 56 .data_unknown:  @ Part of jumptable
 57         mov     r0, r4
 58         mov     r1, r8
 59         b       baddataabort
 60 
 61 .data_arm_ldmstm:
 62         tst     r8, #1 << 21                    @ check writeback bit
 63         beq     do_DataAbort                    @ no writeback -> no fixup
 64         str     r9, [sp, #-4]!
 65         mov     r7, #0x11
 66         orr     r7, r7, #0x1100
 67         and     r6, r8, r7
 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
 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.
 77         and     r9, r8, #15 << 16               @ Extract 'n' from instruction
 78         ldr     r7, [r2, r9, lsr #14]           @ Get register 'Rn'
 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
 82         str     r7, [r2, r9, lsr #14]           @ Put register 'Rn'
 83         ldr     r9, [sp], #4
 84         b       do_DataAbort
 85 
 86 .data_arm_lateldrhpre:
 87         tst     r8, #1 << 21                    @ Check writeback bit
 88         beq     do_DataAbort                    @ No writeback -> no fixup
 89 .data_arm_lateldrhpost:
 90         str     r9, [sp, #-4]!
 91         and     r9, r8, #0x00f                  @ get Rm / low nibble of immediate value
 92         tst     r8, #1 << 22                    @ if (immediate offset)
 93         andne   r6, r8, #0xf00                  @ { immediate high nibble
 94         orrne   r6, r9, r6, lsr #4              @   combine nibbles } else
 95         ldreq   r6, [r2, r9, lsl #2]            @ { load Rm value }
 96 .data_arm_apply_r6_and_rn:
 97         and     r9, r8, #15 << 16               @ Extract 'n' from instruction
 98         ldr     r7, [r2, r9, lsr #14]           @ Get register 'Rn'
 99         tst     r8, #1 << 23                    @ Check U bit
100         subne   r7, r7, r6                      @ Undo incrmenet
101         addeq   r7, r7, r6                      @ Undo decrement
102         str     r7, [r2, r9, lsr #14]           @ Put register 'Rn'
103         ldr     r9, [sp], #4
104         b       do_DataAbort
105 
106 .data_arm_lateldrpreconst:
107         tst     r8, #1 << 21                    @ check writeback bit
108         beq     do_DataAbort                    @ no writeback -> no fixup
109 .data_arm_lateldrpostconst:
110         movs    r6, r8, lsl #20                 @ Get offset
111         beq     do_DataAbort                    @ zero -> no fixup
112         str     r9, [sp, #-4]!
113         and     r9, r8, #15 << 16               @ Extract 'n' from instruction
114         ldr     r7, [r2, r9, lsr #14]           @ Get register 'Rn'
115         tst     r8, #1 << 23                    @ Check U bit
116         subne   r7, r7, r6, lsr #20             @ Undo increment
117         addeq   r7, r7, r6, lsr #20             @ Undo decrement
118         str     r7, [r2, r9, lsr #14]           @ Put register 'Rn'
119         ldr     r9, [sp], #4
120         b       do_DataAbort
121 
122 .data_arm_lateldrprereg:
123         tst     r8, #1 << 21                    @ check writeback bit
124         beq     do_DataAbort                    @ no writeback -> no fixup
125 .data_arm_lateldrpostreg:
126         and     r7, r8, #15                     @ Extract 'm' from instruction
127         ldr     r6, [r2, r7, lsl #2]            @ Get register 'Rm'
128         str     r9, [sp, #-4]!
129         mov     r9, r8, lsr #7                  @ get shift count
130         ands    r9, r9, #31
131         and     r7, r8, #0x70                   @ get shift type
132         orreq   r7, r7, #8                      @ shift count = 0
133         add     pc, pc, r7
134         nop
135 
136         mov     r6, r6, lsl r9                  @ 0: LSL #!0
137         b       .data_arm_apply_r6_and_rn
138         b       .data_arm_apply_r6_and_rn       @ 1: LSL #0
139         nop
140         b       .data_unknown_r9                @ 2: MUL?
141         nop
142         b       .data_unknown_r9                @ 3: MUL?
143         nop
144         mov     r6, r6, lsr r9                  @ 4: LSR #!0
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
148         b       .data_unknown_r9                @ 6: MUL?
149         nop
150         b       .data_unknown_r9                @ 7: MUL?
151         nop
152         mov     r6, r6, asr r9                  @ 8: ASR #!0
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
156         b       .data_unknown_r9                @ A: MUL?
157         nop
158         b       .data_unknown_r9                @ B: MUL?
159         nop
160         mov     r6, r6, ror r9                  @ C: ROR #!0
161         b       .data_arm_apply_r6_and_rn
162         mov     r6, r6, rrx                     @ D: RRX
163         b       .data_arm_apply_r6_and_rn
164         b       .data_unknown_r9                @ E: MUL?
165         nop
166         b       .data_unknown_r9                @ F: MUL?
167 
168 .data_thumb_abort:
169         ldrh    r8, [r4]                        @ read instruction
170         uaccess_disable ip                      @ disable userspace access
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
183 /* 6 */ b       do_DataAbort
184 /* 7 */ b       do_DataAbort
185 /* 8 */ b       do_DataAbort
186 /* 9 */ b       do_DataAbort
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
196         beq     do_DataAbort
197         tst     r8, #1 << 10                    @ If 'S' (signed) bit is set
198         movne   r1, #0                          @ it must be a load instr
199         b       do_DataAbort
200 
201 .data_thumb_pushpop:
202         tst     r8, #1 << 10
203         beq     .data_unknown
204         str     r9, [sp, #-4]!
205         and     r6, r8, #0x55                   @ hweight8(r8) + R bit
206         and     r9, r8, #0xaa
207         add     r6, r6, r9, lsr #1
208         and     r9, r6, #0xcc
209         and     r6, r6, #0x33
210         add     r6, r6, r9, lsr #2
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
214         ldr     r7, [r2, #13 << 2]
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
218         str     r7, [r2, #13 << 2]
219         ldr     r9, [sp], #4
220         b       do_DataAbort
221 
222 .data_thumb_ldmstm:
223         str     r9, [sp, #-4]!
224         and     r6, r8, #0x55                   @ hweight8(r8)
225         and     r9, r8, #0xaa
226         add     r6, r6, r9, lsr #1
227         and     r9, r6, #0xcc
228         and     r6, r6, #0x33
229         add     r6, r6, r9, lsr #2
230         add     r6, r6, r6, lsr #4
231         and     r9, r8, #7 << 8
232         ldr     r7, [r2, r9, lsr #6]
233         and     r6, r6, #15                     @ number of regs to transfer
234         sub     r7, r7, r6, lsl #2              @ always decrement
235         str     r7, [r2, r9, lsr #6]
236         ldr     r9, [sp], #4
237         b       do_DataAbort

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php