root/arch/arm/mach-ep93xx/crunch-bits.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0-only */
   2 /*
   3  * arch/arm/kernel/crunch-bits.S
   4  * Cirrus MaverickCrunch context switching and handling
   5  *
   6  * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
   7  *
   8  * Shamelessly stolen from the iWMMXt code by Nicolas Pitre, which is
   9  * Copyright (c) 2003-2004, MontaVista Software, Inc.
  10  */
  11 
  12 #include <linux/linkage.h>
  13 #include <asm/ptrace.h>
  14 #include <asm/thread_info.h>
  15 #include <asm/asm-offsets.h>
  16 #include <asm/assembler.h>
  17 #include <mach/ep93xx-regs.h>
  18 
  19 /*
  20  * We can't use hex constants here due to a bug in gas.
  21  */
  22 #define CRUNCH_MVDX0            0
  23 #define CRUNCH_MVDX1            8
  24 #define CRUNCH_MVDX2            16
  25 #define CRUNCH_MVDX3            24
  26 #define CRUNCH_MVDX4            32
  27 #define CRUNCH_MVDX5            40
  28 #define CRUNCH_MVDX6            48
  29 #define CRUNCH_MVDX7            56
  30 #define CRUNCH_MVDX8            64
  31 #define CRUNCH_MVDX9            72
  32 #define CRUNCH_MVDX10           80
  33 #define CRUNCH_MVDX11           88
  34 #define CRUNCH_MVDX12           96
  35 #define CRUNCH_MVDX13           104
  36 #define CRUNCH_MVDX14           112
  37 #define CRUNCH_MVDX15           120
  38 #define CRUNCH_MVAX0L           128
  39 #define CRUNCH_MVAX0M           132
  40 #define CRUNCH_MVAX0H           136
  41 #define CRUNCH_MVAX1L           140
  42 #define CRUNCH_MVAX1M           144
  43 #define CRUNCH_MVAX1H           148
  44 #define CRUNCH_MVAX2L           152
  45 #define CRUNCH_MVAX2M           156
  46 #define CRUNCH_MVAX2H           160
  47 #define CRUNCH_MVAX3L           164
  48 #define CRUNCH_MVAX3M           168
  49 #define CRUNCH_MVAX3H           172
  50 #define CRUNCH_DSPSC            176
  51 
  52 #define CRUNCH_SIZE             184
  53 
  54         .text
  55 
  56 /*
  57  * Lazy switching of crunch coprocessor context
  58  *
  59  * r10 = struct thread_info pointer
  60  * r9  = ret_from_exception
  61  * lr  = undefined instr exit
  62  *
  63  * called from prefetch exception handler with interrupts enabled
  64  */
  65 ENTRY(crunch_task_enable)
  66         inc_preempt_count r10, r3
  67 
  68         ldr     r8, =(EP93XX_APB_VIRT_BASE + 0x00130000)        @ syscon addr
  69 
  70         ldr     r1, [r8, #0x80]
  71         tst     r1, #0x00800000                 @ access to crunch enabled?
  72         bne     2f                              @ if so no business here
  73         mov     r3, #0xaa                       @ unlock syscon swlock
  74         str     r3, [r8, #0xc0]
  75         orr     r1, r1, #0x00800000             @ enable access to crunch
  76         str     r1, [r8, #0x80]
  77 
  78         ldr     r3, =crunch_owner
  79         add     r0, r10, #TI_CRUNCH_STATE       @ get task crunch save area
  80         ldr     r2, [sp, #60]                   @ current task pc value
  81         ldr     r1, [r3]                        @ get current crunch owner
  82         str     r0, [r3]                        @ this task now owns crunch
  83         sub     r2, r2, #4                      @ adjust pc back
  84         str     r2, [sp, #60]
  85 
  86         ldr     r2, [r8, #0x80]
  87         mov     r2, r2                          @ flush out enable (@@@)
  88 
  89         teq     r1, #0                          @ test for last ownership
  90         mov     lr, r9                          @ normal exit from exception
  91         beq     crunch_load                     @ no owner, skip save
  92 
  93 crunch_save:
  94         cfstr64         mvdx0, [r1, #CRUNCH_MVDX0]      @ save 64b registers
  95         cfstr64         mvdx1, [r1, #CRUNCH_MVDX1]
  96         cfstr64         mvdx2, [r1, #CRUNCH_MVDX2]
  97         cfstr64         mvdx3, [r1, #CRUNCH_MVDX3]
  98         cfstr64         mvdx4, [r1, #CRUNCH_MVDX4]
  99         cfstr64         mvdx5, [r1, #CRUNCH_MVDX5]
 100         cfstr64         mvdx6, [r1, #CRUNCH_MVDX6]
 101         cfstr64         mvdx7, [r1, #CRUNCH_MVDX7]
 102         cfstr64         mvdx8, [r1, #CRUNCH_MVDX8]
 103         cfstr64         mvdx9, [r1, #CRUNCH_MVDX9]
 104         cfstr64         mvdx10, [r1, #CRUNCH_MVDX10]
 105         cfstr64         mvdx11, [r1, #CRUNCH_MVDX11]
 106         cfstr64         mvdx12, [r1, #CRUNCH_MVDX12]
 107         cfstr64         mvdx13, [r1, #CRUNCH_MVDX13]
 108         cfstr64         mvdx14, [r1, #CRUNCH_MVDX14]
 109         cfstr64         mvdx15, [r1, #CRUNCH_MVDX15]
 110 
 111 #ifdef __ARMEB__
 112 #error fix me for ARMEB
 113 #endif
 114 
 115         cfmv32al        mvfx0, mvax0                    @ save 72b accumulators
 116         cfstr32         mvfx0, [r1, #CRUNCH_MVAX0L]
 117         cfmv32am        mvfx0, mvax0
 118         cfstr32         mvfx0, [r1, #CRUNCH_MVAX0M]
 119         cfmv32ah        mvfx0, mvax0
 120         cfstr32         mvfx0, [r1, #CRUNCH_MVAX0H]
 121         cfmv32al        mvfx0, mvax1
 122         cfstr32         mvfx0, [r1, #CRUNCH_MVAX1L]
 123         cfmv32am        mvfx0, mvax1
 124         cfstr32         mvfx0, [r1, #CRUNCH_MVAX1M]
 125         cfmv32ah        mvfx0, mvax1
 126         cfstr32         mvfx0, [r1, #CRUNCH_MVAX1H]
 127         cfmv32al        mvfx0, mvax2
 128         cfstr32         mvfx0, [r1, #CRUNCH_MVAX2L]
 129         cfmv32am        mvfx0, mvax2
 130         cfstr32         mvfx0, [r1, #CRUNCH_MVAX2M]
 131         cfmv32ah        mvfx0, mvax2
 132         cfstr32         mvfx0, [r1, #CRUNCH_MVAX2H]
 133         cfmv32al        mvfx0, mvax3
 134         cfstr32         mvfx0, [r1, #CRUNCH_MVAX3L]
 135         cfmv32am        mvfx0, mvax3
 136         cfstr32         mvfx0, [r1, #CRUNCH_MVAX3M]
 137         cfmv32ah        mvfx0, mvax3
 138         cfstr32         mvfx0, [r1, #CRUNCH_MVAX3H]
 139 
 140         cfmv32sc        mvdx0, dspsc                    @ save status word
 141         cfstr64         mvdx0, [r1, #CRUNCH_DSPSC]
 142 
 143         teq             r0, #0                          @ anything to load?
 144         cfldr64eq       mvdx0, [r1, #CRUNCH_MVDX0]      @ mvdx0 was clobbered
 145         beq             1f
 146 
 147 crunch_load:
 148         cfldr64         mvdx0, [r0, #CRUNCH_DSPSC]      @ load status word
 149         cfmvsc32        dspsc, mvdx0
 150 
 151         cfldr32         mvfx0, [r0, #CRUNCH_MVAX0L]     @ load 72b accumulators
 152         cfmval32        mvax0, mvfx0
 153         cfldr32         mvfx0, [r0, #CRUNCH_MVAX0M]
 154         cfmvam32        mvax0, mvfx0
 155         cfldr32         mvfx0, [r0, #CRUNCH_MVAX0H]
 156         cfmvah32        mvax0, mvfx0
 157         cfldr32         mvfx0, [r0, #CRUNCH_MVAX1L]
 158         cfmval32        mvax1, mvfx0
 159         cfldr32         mvfx0, [r0, #CRUNCH_MVAX1M]
 160         cfmvam32        mvax1, mvfx0
 161         cfldr32         mvfx0, [r0, #CRUNCH_MVAX1H]
 162         cfmvah32        mvax1, mvfx0
 163         cfldr32         mvfx0, [r0, #CRUNCH_MVAX2L]
 164         cfmval32        mvax2, mvfx0
 165         cfldr32         mvfx0, [r0, #CRUNCH_MVAX2M]
 166         cfmvam32        mvax2, mvfx0
 167         cfldr32         mvfx0, [r0, #CRUNCH_MVAX2H]
 168         cfmvah32        mvax2, mvfx0
 169         cfldr32         mvfx0, [r0, #CRUNCH_MVAX3L]
 170         cfmval32        mvax3, mvfx0
 171         cfldr32         mvfx0, [r0, #CRUNCH_MVAX3M]
 172         cfmvam32        mvax3, mvfx0
 173         cfldr32         mvfx0, [r0, #CRUNCH_MVAX3H]
 174         cfmvah32        mvax3, mvfx0
 175 
 176         cfldr64         mvdx0, [r0, #CRUNCH_MVDX0]      @ load 64b registers
 177         cfldr64         mvdx1, [r0, #CRUNCH_MVDX1]
 178         cfldr64         mvdx2, [r0, #CRUNCH_MVDX2]
 179         cfldr64         mvdx3, [r0, #CRUNCH_MVDX3]
 180         cfldr64         mvdx4, [r0, #CRUNCH_MVDX4]
 181         cfldr64         mvdx5, [r0, #CRUNCH_MVDX5]
 182         cfldr64         mvdx6, [r0, #CRUNCH_MVDX6]
 183         cfldr64         mvdx7, [r0, #CRUNCH_MVDX7]
 184         cfldr64         mvdx8, [r0, #CRUNCH_MVDX8]
 185         cfldr64         mvdx9, [r0, #CRUNCH_MVDX9]
 186         cfldr64         mvdx10, [r0, #CRUNCH_MVDX10]
 187         cfldr64         mvdx11, [r0, #CRUNCH_MVDX11]
 188         cfldr64         mvdx12, [r0, #CRUNCH_MVDX12]
 189         cfldr64         mvdx13, [r0, #CRUNCH_MVDX13]
 190         cfldr64         mvdx14, [r0, #CRUNCH_MVDX14]
 191         cfldr64         mvdx15, [r0, #CRUNCH_MVDX15]
 192 
 193 1:
 194 #ifdef CONFIG_PREEMPT_COUNT
 195         get_thread_info r10
 196 #endif
 197 2:      dec_preempt_count r10, r3
 198         ret     lr
 199 
 200 /*
 201  * Back up crunch regs to save area and disable access to them
 202  * (mainly for gdb or sleep mode usage)
 203  *
 204  * r0 = struct thread_info pointer of target task or NULL for any
 205  */
 206 ENTRY(crunch_task_disable)
 207         stmfd   sp!, {r4, r5, lr}
 208 
 209         mrs     ip, cpsr
 210         orr     r2, ip, #PSR_I_BIT              @ disable interrupts
 211         msr     cpsr_c, r2
 212 
 213         ldr     r4, =(EP93XX_APB_VIRT_BASE + 0x00130000)        @ syscon addr
 214 
 215         ldr     r3, =crunch_owner
 216         add     r2, r0, #TI_CRUNCH_STATE        @ get task crunch save area
 217         ldr     r1, [r3]                        @ get current crunch owner
 218         teq     r1, #0                          @ any current owner?
 219         beq     1f                              @ no: quit
 220         teq     r0, #0                          @ any owner?
 221         teqne   r1, r2                          @ or specified one?
 222         bne     1f                              @ no: quit
 223 
 224         ldr     r5, [r4, #0x80]                 @ enable access to crunch
 225         mov     r2, #0xaa
 226         str     r2, [r4, #0xc0]
 227         orr     r5, r5, #0x00800000
 228         str     r5, [r4, #0x80]
 229 
 230         mov     r0, #0                          @ nothing to load
 231         str     r0, [r3]                        @ no more current owner
 232         ldr     r2, [r4, #0x80]                 @ flush out enable (@@@)
 233         mov     r2, r2
 234         bl      crunch_save
 235 
 236         mov     r2, #0xaa                       @ disable access to crunch
 237         str     r2, [r4, #0xc0]
 238         bic     r5, r5, #0x00800000
 239         str     r5, [r4, #0x80]
 240         ldr     r5, [r4, #0x80]                 @ flush out enable (@@@)
 241         mov     r5, r5
 242 
 243 1:      msr     cpsr_c, ip                      @ restore interrupt mode
 244         ldmfd   sp!, {r4, r5, pc}
 245 
 246 /*
 247  * Copy crunch state to given memory address
 248  *
 249  * r0 = struct thread_info pointer of target task
 250  * r1 = memory address where to store crunch state
 251  *
 252  * this is called mainly in the creation of signal stack frames
 253  */
 254 ENTRY(crunch_task_copy)
 255         mrs     ip, cpsr
 256         orr     r2, ip, #PSR_I_BIT              @ disable interrupts
 257         msr     cpsr_c, r2
 258 
 259         ldr     r3, =crunch_owner
 260         add     r2, r0, #TI_CRUNCH_STATE        @ get task crunch save area
 261         ldr     r3, [r3]                        @ get current crunch owner
 262         teq     r2, r3                          @ does this task own it...
 263         beq     1f
 264 
 265         @ current crunch values are in the task save area
 266         msr     cpsr_c, ip                      @ restore interrupt mode
 267         mov     r0, r1
 268         mov     r1, r2
 269         mov     r2, #CRUNCH_SIZE
 270         b       memcpy
 271 
 272 1:      @ this task owns crunch regs -- grab a copy from there
 273         mov     r0, #0                          @ nothing to load
 274         mov     r3, lr                          @ preserve return address
 275         bl      crunch_save
 276         msr     cpsr_c, ip                      @ restore interrupt mode
 277         ret     r3
 278 
 279 /*
 280  * Restore crunch state from given memory address
 281  *
 282  * r0 = struct thread_info pointer of target task
 283  * r1 = memory address where to get crunch state from
 284  *
 285  * this is used to restore crunch state when unwinding a signal stack frame
 286  */
 287 ENTRY(crunch_task_restore)
 288         mrs     ip, cpsr
 289         orr     r2, ip, #PSR_I_BIT              @ disable interrupts
 290         msr     cpsr_c, r2
 291 
 292         ldr     r3, =crunch_owner
 293         add     r2, r0, #TI_CRUNCH_STATE        @ get task crunch save area
 294         ldr     r3, [r3]                        @ get current crunch owner
 295         teq     r2, r3                          @ does this task own it...
 296         beq     1f
 297 
 298         @ this task doesn't own crunch regs -- use its save area
 299         msr     cpsr_c, ip                      @ restore interrupt mode
 300         mov     r0, r2
 301         mov     r2, #CRUNCH_SIZE
 302         b       memcpy
 303 
 304 1:      @ this task owns crunch regs -- load them directly
 305         mov     r0, r1
 306         mov     r1, #0                          @ nothing to save
 307         mov     r3, lr                          @ preserve return address
 308         bl      crunch_load
 309         msr     cpsr_c, ip                      @ restore interrupt mode
 310         ret     r3

/* [<][>][^][v][top][bottom][index][help] */