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

TOMOYO Linux Cross Reference
Linux/arch/arm/kernel/iwmmxt.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-only */
  2 /*
  3  *  linux/arch/arm/kernel/iwmmxt.S
  4  *
  5  *  XScale iWMMXt (Concan) context switching and handling
  6  *
  7  *  Initial code:
  8  *  Copyright (c) 2003, Intel Corporation
  9  *
 10  *  Full lazy switching support, optimizations and more, by Nicolas Pitre
 11 *   Copyright (c) 2003-2004, MontaVista Software, Inc.
 12  */
 13 
 14 #include <linux/linkage.h>
 15 #include <asm/ptrace.h>
 16 #include <asm/thread_info.h>
 17 #include <asm/asm-offsets.h>
 18 #include <asm/assembler.h>
 19 #include "iwmmxt.h"
 20 
 21 #define MMX_WR0                 (0x00)
 22 #define MMX_WR1                 (0x08)
 23 #define MMX_WR2                 (0x10)
 24 #define MMX_WR3                 (0x18)
 25 #define MMX_WR4                 (0x20)
 26 #define MMX_WR5                 (0x28)
 27 #define MMX_WR6                 (0x30)
 28 #define MMX_WR7                 (0x38)
 29 #define MMX_WR8                 (0x40)
 30 #define MMX_WR9                 (0x48)
 31 #define MMX_WR10                (0x50)
 32 #define MMX_WR11                (0x58)
 33 #define MMX_WR12                (0x60)
 34 #define MMX_WR13                (0x68)
 35 #define MMX_WR14                (0x70)
 36 #define MMX_WR15                (0x78)
 37 #define MMX_WCSSF               (0x80)
 38 #define MMX_WCASF               (0x84)
 39 #define MMX_WCGR0               (0x88)
 40 #define MMX_WCGR1               (0x8C)
 41 #define MMX_WCGR2               (0x90)
 42 #define MMX_WCGR3               (0x94)
 43 
 44 #define MMX_SIZE                (0x98)
 45 
 46         .text
 47         .arm
 48 
 49 ENTRY(iwmmxt_undef_handler)
 50         push            {r9, r10, lr}
 51         get_thread_info r10
 52         mov             r9, pc
 53         b               iwmmxt_task_enable
 54         mov             r0, #0
 55         pop             {r9, r10, pc}
 56 ENDPROC(iwmmxt_undef_handler)
 57 
 58 /*
 59  * Lazy switching of Concan coprocessor context
 60  *
 61  * r0  = struct pt_regs pointer
 62  * r10 = struct thread_info pointer
 63  * r9  = ret_from_exception
 64  * lr  = undefined instr exit
 65  *
 66  * called from prefetch exception handler with interrupts enabled
 67  */
 68 
 69 ENTRY(iwmmxt_task_enable)
 70         inc_preempt_count r10, r3
 71 
 72         mrc     p15, 0, r2, c15, c1, 0
 73         @ CP0 and CP1 accessible?
 74         tst     r2, #0x3
 75         bne     4f                              @ if so no business here
 76         @ enable access to CP0 and CP1
 77         orr     r2, r2, #0x3
 78         mcr     p15, 0, r2, c15, c1, 0
 79 
 80         ldr     r3, =concan_owner
 81         ldr     r2, [r0, #S_PC]                 @ current task pc value
 82         ldr     r1, [r3]                        @ get current Concan owner
 83         sub     r2, r2, #4                      @ adjust pc back
 84         str     r2, [r0, #S_PC]
 85         add     r0, r10, #TI_IWMMXT_STATE       @ get task Concan save area
 86         str     r0, [r3]                        @ this task now owns Concan regs
 87 
 88         mrc     p15, 0, r2, c2, c0, 0
 89         mov     r2, r2                          @ cpwait
 90         bl      concan_save
 91 
 92 #ifdef CONFIG_PREEMPT_COUNT
 93         get_thread_info r10
 94 #endif
 95 4:      dec_preempt_count r10, r3
 96         ret     r9                              @ normal exit from exception
 97 
 98 concan_save:
 99 
100         teq     r1, #0                          @ test for last ownership
101         beq     concan_load                     @ no owner, skip save
102 
103         tmrc    r2, wCon
104 
105         @ CUP? wCx
106         tst     r2, #0x1
107         beq     1f
108 
109 concan_dump:
110 
111         wstrw   wCSSF, r1, MMX_WCSSF
112         wstrw   wCASF, r1, MMX_WCASF
113         wstrw   wCGR0, r1, MMX_WCGR0
114         wstrw   wCGR1, r1, MMX_WCGR1
115         wstrw   wCGR2, r1, MMX_WCGR2
116         wstrw   wCGR3, r1, MMX_WCGR3
117 
118 1:      @ MUP? wRn
119         tst     r2, #0x2
120         beq     2f
121 
122         wstrd   wR0,  r1, MMX_WR0
123         wstrd   wR1,  r1, MMX_WR1
124         wstrd   wR2,  r1, MMX_WR2
125         wstrd   wR3,  r1, MMX_WR3
126         wstrd   wR4,  r1, MMX_WR4
127         wstrd   wR5,  r1, MMX_WR5
128         wstrd   wR6,  r1, MMX_WR6
129         wstrd   wR7,  r1, MMX_WR7
130         wstrd   wR8,  r1, MMX_WR8
131         wstrd   wR9,  r1, MMX_WR9
132         wstrd   wR10, r1, MMX_WR10
133         wstrd   wR11, r1, MMX_WR11
134         wstrd   wR12, r1, MMX_WR12
135         wstrd   wR13, r1, MMX_WR13
136         wstrd   wR14, r1, MMX_WR14
137         wstrd   wR15, r1, MMX_WR15
138 
139 2:      teq     r0, #0                          @ anything to load?
140         reteq   lr                              @ if not, return
141 
142 concan_load:
143 
144         @ Load wRn
145         wldrd   wR0,  r0, MMX_WR0
146         wldrd   wR1,  r0, MMX_WR1
147         wldrd   wR2,  r0, MMX_WR2
148         wldrd   wR3,  r0, MMX_WR3
149         wldrd   wR4,  r0, MMX_WR4
150         wldrd   wR5,  r0, MMX_WR5
151         wldrd   wR6,  r0, MMX_WR6
152         wldrd   wR7,  r0, MMX_WR7
153         wldrd   wR8,  r0, MMX_WR8
154         wldrd   wR9,  r0, MMX_WR9
155         wldrd   wR10, r0, MMX_WR10
156         wldrd   wR11, r0, MMX_WR11
157         wldrd   wR12, r0, MMX_WR12
158         wldrd   wR13, r0, MMX_WR13
159         wldrd   wR14, r0, MMX_WR14
160         wldrd   wR15, r0, MMX_WR15
161 
162         @ Load wCx
163         wldrw   wCSSF, r0, MMX_WCSSF
164         wldrw   wCASF, r0, MMX_WCASF
165         wldrw   wCGR0, r0, MMX_WCGR0
166         wldrw   wCGR1, r0, MMX_WCGR1
167         wldrw   wCGR2, r0, MMX_WCGR2
168         wldrw   wCGR3, r0, MMX_WCGR3
169 
170         @ clear CUP/MUP (only if r1 != 0)
171         teq     r1, #0
172         mov     r2, #0
173         reteq   lr
174 
175         tmcr    wCon, r2
176         ret     lr
177 
178 ENDPROC(iwmmxt_task_enable)
179 
180 /*
181  * Back up Concan regs to save area and disable access to them
182  * (mainly for gdb or sleep mode usage)
183  *
184  * r0 = struct thread_info pointer of target task or NULL for any
185  */
186 
187 ENTRY(iwmmxt_task_disable)
188 
189         stmfd   sp!, {r4, lr}
190 
191         mrs     ip, cpsr
192         orr     r2, ip, #PSR_I_BIT              @ disable interrupts
193         msr     cpsr_c, r2
194 
195         ldr     r3, =concan_owner
196         add     r2, r0, #TI_IWMMXT_STATE        @ get task Concan save area
197         ldr     r1, [r3]                        @ get current Concan owner
198         teq     r1, #0                          @ any current owner?
199         beq     1f                              @ no: quit
200         teq     r0, #0                          @ any owner?
201         teqne   r1, r2                          @ or specified one?
202         bne     1f                              @ no: quit
203 
204         @ enable access to CP0 and CP1
205         mrc     p15, 0, r4, c15, c1, 0
206         orr     r4, r4, #0x3
207         mcr     p15, 0, r4, c15, c1, 0
208 
209         mov     r0, #0                          @ nothing to load
210         str     r0, [r3]                        @ no more current owner
211         mrc     p15, 0, r2, c2, c0, 0
212         mov     r2, r2                          @ cpwait
213         bl      concan_save
214 
215         @ disable access to CP0 and CP1
216         bic     r4, r4, #0x3
217         mcr     p15, 0, r4, c15, c1, 0
218 
219         mrc     p15, 0, r2, c2, c0, 0
220         mov     r2, r2                          @ cpwait
221 
222 1:      msr     cpsr_c, ip                      @ restore interrupt mode
223         ldmfd   sp!, {r4, pc}
224 
225 ENDPROC(iwmmxt_task_disable)
226 
227 /*
228  * Copy Concan state to given memory address
229  *
230  * r0 = struct thread_info pointer of target task
231  * r1 = memory address where to store Concan state
232  *
233  * this is called mainly in the creation of signal stack frames
234  */
235 
236 ENTRY(iwmmxt_task_copy)
237 
238         mrs     ip, cpsr
239         orr     r2, ip, #PSR_I_BIT              @ disable interrupts
240         msr     cpsr_c, r2
241 
242         ldr     r3, =concan_owner
243         add     r2, r0, #TI_IWMMXT_STATE        @ get task Concan save area
244         ldr     r3, [r3]                        @ get current Concan owner
245         teq     r2, r3                          @ does this task own it...
246         beq     1f
247 
248         @ current Concan values are in the task save area
249         msr     cpsr_c, ip                      @ restore interrupt mode
250         mov     r0, r1
251         mov     r1, r2
252         mov     r2, #MMX_SIZE
253         b       memcpy
254 
255 1:      @ this task owns Concan regs -- grab a copy from there
256         mov     r0, #0                          @ nothing to load
257         mov     r2, #3                          @ save all regs
258         mov     r3, lr                          @ preserve return address
259         bl      concan_dump
260         msr     cpsr_c, ip                      @ restore interrupt mode
261         ret     r3
262 
263 ENDPROC(iwmmxt_task_copy)
264 
265 /*
266  * Restore Concan state from given memory address
267  *
268  * r0 = struct thread_info pointer of target task
269  * r1 = memory address where to get Concan state from
270  *
271  * this is used to restore Concan state when unwinding a signal stack frame
272  */
273 
274 ENTRY(iwmmxt_task_restore)
275 
276         mrs     ip, cpsr
277         orr     r2, ip, #PSR_I_BIT              @ disable interrupts
278         msr     cpsr_c, r2
279 
280         ldr     r3, =concan_owner
281         add     r2, r0, #TI_IWMMXT_STATE        @ get task Concan save area
282         ldr     r3, [r3]                        @ get current Concan owner
283         bic     r2, r2, #0x7                    @ 64-bit alignment
284         teq     r2, r3                          @ does this task own it...
285         beq     1f
286 
287         @ this task doesn't own Concan regs -- use its save area
288         msr     cpsr_c, ip                      @ restore interrupt mode
289         mov     r0, r2
290         mov     r2, #MMX_SIZE
291         b       memcpy
292 
293 1:      @ this task owns Concan regs -- load them directly
294         mov     r0, r1
295         mov     r1, #0                          @ don't clear CUP/MUP
296         mov     r3, lr                          @ preserve return address
297         bl      concan_load
298         msr     cpsr_c, ip                      @ restore interrupt mode
299         ret     r3
300 
301 ENDPROC(iwmmxt_task_restore)
302 
303 /*
304  * Concan handling on task switch
305  *
306  * r0 = next thread_info pointer
307  *
308  * Called only from the iwmmxt notifier with task preemption disabled.
309  */
310 ENTRY(iwmmxt_task_switch)
311 
312         mrc     p15, 0, r1, c15, c1, 0
313         @ CP0 and CP1 accessible?
314         tst     r1, #0x3
315         bne     1f                              @ yes: block them for next task
316 
317         ldr     r2, =concan_owner
318         add     r3, r0, #TI_IWMMXT_STATE        @ get next task Concan save area
319         ldr     r2, [r2]                        @ get current Concan owner
320         teq     r2, r3                          @ next task owns it?
321         retne   lr                              @ no: leave Concan disabled
322 
323 1:      @ flip Concan access
324         eor     r1, r1, #0x3
325         mcr     p15, 0, r1, c15, c1, 0
326 
327         mrc     p15, 0, r1, c2, c0, 0
328         sub     pc, lr, r1, lsr #32             @ cpwait and return
329 
330 ENDPROC(iwmmxt_task_switch)
331 
332 /*
333  * Remove Concan ownership of given task
334  *
335  * r0 = struct thread_info pointer
336  */
337 ENTRY(iwmmxt_task_release)
338 
339         mrs     r2, cpsr
340         orr     ip, r2, #PSR_I_BIT              @ disable interrupts
341         msr     cpsr_c, ip
342         ldr     r3, =concan_owner
343         add     r0, r0, #TI_IWMMXT_STATE        @ get task Concan save area
344         ldr     r1, [r3]                        @ get current Concan owner
345         eors    r0, r0, r1                      @ if equal...
346         streq   r0, [r3]                        @ then clear ownership
347         msr     cpsr_c, r2                      @ restore interrupts
348         ret     lr
349 
350 ENDPROC(iwmmxt_task_release)
351 
352         .data
353         .align  2
354 concan_owner:
355         .word   0
356 

~ [ 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