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