0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/linkage.h>
0015 #include <asm/ptrace.h>
0016 #include <asm/thread_info.h>
0017 #include <asm/asm-offsets.h>
0018 #include <asm/assembler.h>
0019 #include "iwmmxt.h"
0020
0021 #if defined(CONFIG_CPU_PJ4) || defined(CONFIG_CPU_PJ4B)
0022 #define PJ4(code...) code
0023 #define XSC(code...)
0024 #elif defined(CONFIG_CPU_MOHAWK) || \
0025 defined(CONFIG_CPU_XSC3) || \
0026 defined(CONFIG_CPU_XSCALE)
0027 #define PJ4(code...)
0028 #define XSC(code...) code
0029 #else
0030 #error "Unsupported iWMMXt architecture"
0031 #endif
0032
0033 #define MMX_WR0 (0x00)
0034 #define MMX_WR1 (0x08)
0035 #define MMX_WR2 (0x10)
0036 #define MMX_WR3 (0x18)
0037 #define MMX_WR4 (0x20)
0038 #define MMX_WR5 (0x28)
0039 #define MMX_WR6 (0x30)
0040 #define MMX_WR7 (0x38)
0041 #define MMX_WR8 (0x40)
0042 #define MMX_WR9 (0x48)
0043 #define MMX_WR10 (0x50)
0044 #define MMX_WR11 (0x58)
0045 #define MMX_WR12 (0x60)
0046 #define MMX_WR13 (0x68)
0047 #define MMX_WR14 (0x70)
0048 #define MMX_WR15 (0x78)
0049 #define MMX_WCSSF (0x80)
0050 #define MMX_WCASF (0x84)
0051 #define MMX_WCGR0 (0x88)
0052 #define MMX_WCGR1 (0x8C)
0053 #define MMX_WCGR2 (0x90)
0054 #define MMX_WCGR3 (0x94)
0055
0056 #define MMX_SIZE (0x98)
0057
0058 .text
0059 .arm
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 ENTRY(iwmmxt_task_enable)
0072 inc_preempt_count r10, r3
0073
0074 XSC(mrc p15, 0, r2, c15, c1, 0)
0075 PJ4(mrc p15, 0, r2, c1, c0, 2)
0076 @ CP0 and CP1 accessible?
0077 XSC(tst r2, #0x3)
0078 PJ4(tst r2, #0xf)
0079 bne 4f @ if so no business here
0080 @ enable access to CP0 and CP1
0081 XSC(orr r2, r2, #0x3)
0082 XSC(mcr p15, 0, r2, c15, c1, 0)
0083 PJ4(orr r2, r2, #0xf)
0084 PJ4(mcr p15, 0, r2, c1, c0, 2)
0085
0086 ldr r3, =concan_owner
0087 add r0, r10, #TI_IWMMXT_STATE @ get task Concan save area
0088 ldr r2, [sp, #60] @ current task pc value
0089 ldr r1, [r3] @ get current Concan owner
0090 str r0, [r3] @ this task now owns Concan regs
0091 sub r2, r2, #4 @ adjust pc back
0092 str r2, [sp, #60]
0093
0094 mrc p15, 0, r2, c2, c0, 0
0095 mov r2, r2 @ cpwait
0096 bl concan_save
0097
0098 #ifdef CONFIG_PREEMPT_COUNT
0099 get_thread_info r10
0100 #endif
0101 4: dec_preempt_count r10, r3
0102 ret r9 @ normal exit from exception
0103
0104 concan_save:
0105
0106 teq r1, #0 @ test for last ownership
0107 beq concan_load @ no owner, skip save
0108
0109 tmrc r2, wCon
0110
0111 @ CUP? wCx
0112 tst r2, #0x1
0113 beq 1f
0114
0115 concan_dump:
0116
0117 wstrw wCSSF, r1, MMX_WCSSF
0118 wstrw wCASF, r1, MMX_WCASF
0119 wstrw wCGR0, r1, MMX_WCGR0
0120 wstrw wCGR1, r1, MMX_WCGR1
0121 wstrw wCGR2, r1, MMX_WCGR2
0122 wstrw wCGR3, r1, MMX_WCGR3
0123
0124 1: @ MUP? wRn
0125 tst r2, #0x2
0126 beq 2f
0127
0128 wstrd wR0, r1, MMX_WR0
0129 wstrd wR1, r1, MMX_WR1
0130 wstrd wR2, r1, MMX_WR2
0131 wstrd wR3, r1, MMX_WR3
0132 wstrd wR4, r1, MMX_WR4
0133 wstrd wR5, r1, MMX_WR5
0134 wstrd wR6, r1, MMX_WR6
0135 wstrd wR7, r1, MMX_WR7
0136 wstrd wR8, r1, MMX_WR8
0137 wstrd wR9, r1, MMX_WR9
0138 wstrd wR10, r1, MMX_WR10
0139 wstrd wR11, r1, MMX_WR11
0140 wstrd wR12, r1, MMX_WR12
0141 wstrd wR13, r1, MMX_WR13
0142 wstrd wR14, r1, MMX_WR14
0143 wstrd wR15, r1, MMX_WR15
0144
0145 2: teq r0, #0 @ anything to load?
0146 reteq lr @ if not, return
0147
0148 concan_load:
0149
0150 @ Load wRn
0151 wldrd wR0, r0, MMX_WR0
0152 wldrd wR1, r0, MMX_WR1
0153 wldrd wR2, r0, MMX_WR2
0154 wldrd wR3, r0, MMX_WR3
0155 wldrd wR4, r0, MMX_WR4
0156 wldrd wR5, r0, MMX_WR5
0157 wldrd wR6, r0, MMX_WR6
0158 wldrd wR7, r0, MMX_WR7
0159 wldrd wR8, r0, MMX_WR8
0160 wldrd wR9, r0, MMX_WR9
0161 wldrd wR10, r0, MMX_WR10
0162 wldrd wR11, r0, MMX_WR11
0163 wldrd wR12, r0, MMX_WR12
0164 wldrd wR13, r0, MMX_WR13
0165 wldrd wR14, r0, MMX_WR14
0166 wldrd wR15, r0, MMX_WR15
0167
0168 @ Load wCx
0169 wldrw wCSSF, r0, MMX_WCSSF
0170 wldrw wCASF, r0, MMX_WCASF
0171 wldrw wCGR0, r0, MMX_WCGR0
0172 wldrw wCGR1, r0, MMX_WCGR1
0173 wldrw wCGR2, r0, MMX_WCGR2
0174 wldrw wCGR3, r0, MMX_WCGR3
0175
0176 @ clear CUP/MUP (only if r1 != 0)
0177 teq r1, #0
0178 mov r2, #0
0179 reteq lr
0180
0181 tmcr wCon, r2
0182 ret lr
0183
0184 ENDPROC(iwmmxt_task_enable)
0185
0186
0187
0188
0189
0190
0191
0192
0193 ENTRY(iwmmxt_task_disable)
0194
0195 stmfd sp!, {r4, lr}
0196
0197 mrs ip, cpsr
0198 orr r2, ip, #PSR_I_BIT @ disable interrupts
0199 msr cpsr_c, r2
0200
0201 ldr r3, =concan_owner
0202 add r2, r0, #TI_IWMMXT_STATE @ get task Concan save area
0203 ldr r1, [r3] @ get current Concan owner
0204 teq r1, #0 @ any current owner?
0205 beq 1f @ no: quit
0206 teq r0, #0 @ any owner?
0207 teqne r1, r2 @ or specified one?
0208 bne 1f @ no: quit
0209
0210 @ enable access to CP0 and CP1
0211 XSC(mrc p15, 0, r4, c15, c1, 0)
0212 XSC(orr r4, r4, #0x3)
0213 XSC(mcr p15, 0, r4, c15, c1, 0)
0214 PJ4(mrc p15, 0, r4, c1, c0, 2)
0215 PJ4(orr r4, r4, #0xf)
0216 PJ4(mcr p15, 0, r4, c1, c0, 2)
0217
0218 mov r0, #0 @ nothing to load
0219 str r0, [r3] @ no more current owner
0220 mrc p15, 0, r2, c2, c0, 0
0221 mov r2, r2 @ cpwait
0222 bl concan_save
0223
0224 @ disable access to CP0 and CP1
0225 XSC(bic r4, r4, #0x3)
0226 XSC(mcr p15, 0, r4, c15, c1, 0)
0227 PJ4(bic r4, r4, #0xf)
0228 PJ4(mcr p15, 0, r4, c1, c0, 2)
0229
0230 mrc p15, 0, r2, c2, c0, 0
0231 mov r2, r2 @ cpwait
0232
0233 1: msr cpsr_c, ip @ restore interrupt mode
0234 ldmfd sp!, {r4, pc}
0235
0236 ENDPROC(iwmmxt_task_disable)
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 ENTRY(iwmmxt_task_copy)
0248
0249 mrs ip, cpsr
0250 orr r2, ip, #PSR_I_BIT @ disable interrupts
0251 msr cpsr_c, r2
0252
0253 ldr r3, =concan_owner
0254 add r2, r0, #TI_IWMMXT_STATE @ get task Concan save area
0255 ldr r3, [r3] @ get current Concan owner
0256 teq r2, r3 @ does this task own it...
0257 beq 1f
0258
0259 @ current Concan values are in the task save area
0260 msr cpsr_c, ip @ restore interrupt mode
0261 mov r0, r1
0262 mov r1, r2
0263 mov r2, #MMX_SIZE
0264 b memcpy
0265
0266 1: @ this task owns Concan regs -- grab a copy from there
0267 mov r0, #0 @ nothing to load
0268 mov r2, #3 @ save all regs
0269 mov r3, lr @ preserve return address
0270 bl concan_dump
0271 msr cpsr_c, ip @ restore interrupt mode
0272 ret r3
0273
0274 ENDPROC(iwmmxt_task_copy)
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285 ENTRY(iwmmxt_task_restore)
0286
0287 mrs ip, cpsr
0288 orr r2, ip, #PSR_I_BIT @ disable interrupts
0289 msr cpsr_c, r2
0290
0291 ldr r3, =concan_owner
0292 add r2, r0, #TI_IWMMXT_STATE @ get task Concan save area
0293 ldr r3, [r3] @ get current Concan owner
0294 bic r2, r2, #0x7 @ 64-bit alignment
0295 teq r2, r3 @ does this task own it...
0296 beq 1f
0297
0298 @ this task doesn't own Concan regs -- use its save area
0299 msr cpsr_c, ip @ restore interrupt mode
0300 mov r0, r2
0301 mov r2, #MMX_SIZE
0302 b memcpy
0303
0304 1: @ this task owns Concan regs -- load them directly
0305 mov r0, r1
0306 mov r1, #0 @ don't clear CUP/MUP
0307 mov r3, lr @ preserve return address
0308 bl concan_load
0309 msr cpsr_c, ip @ restore interrupt mode
0310 ret r3
0311
0312 ENDPROC(iwmmxt_task_restore)
0313
0314
0315
0316
0317
0318
0319
0320
0321 ENTRY(iwmmxt_task_switch)
0322
0323 XSC(mrc p15, 0, r1, c15, c1, 0)
0324 PJ4(mrc p15, 0, r1, c1, c0, 2)
0325 @ CP0 and CP1 accessible?
0326 XSC(tst r1, #0x3)
0327 PJ4(tst r1, #0xf)
0328 bne 1f @ yes: block them for next task
0329
0330 ldr r2, =concan_owner
0331 add r3, r0, #TI_IWMMXT_STATE @ get next task Concan save area
0332 ldr r2, [r2] @ get current Concan owner
0333 teq r2, r3 @ next task owns it?
0334 retne lr @ no: leave Concan disabled
0335
0336 1: @ flip Concan access
0337 XSC(eor r1, r1, #0x3)
0338 XSC(mcr p15, 0, r1, c15, c1, 0)
0339 PJ4(eor r1, r1, #0xf)
0340 PJ4(mcr p15, 0, r1, c1, c0, 2)
0341
0342 mrc p15, 0, r1, c2, c0, 0
0343 sub pc, lr, r1, lsr #32 @ cpwait and return
0344
0345 ENDPROC(iwmmxt_task_switch)
0346
0347
0348
0349
0350
0351
0352 ENTRY(iwmmxt_task_release)
0353
0354 mrs r2, cpsr
0355 orr ip, r2, #PSR_I_BIT @ disable interrupts
0356 msr cpsr_c, ip
0357 ldr r3, =concan_owner
0358 add r0, r0, #TI_IWMMXT_STATE @ get task Concan save area
0359 ldr r1, [r3] @ get current Concan owner
0360 eors r0, r0, r1 @ if equal...
0361 streq r0, [r3] @ then clear ownership
0362 msr cpsr_c, r2 @ restore interrupts
0363 ret lr
0364
0365 ENDPROC(iwmmxt_task_release)
0366
0367 .data
0368 .align 2
0369 concan_owner:
0370 .word 0
0371