linux/arch/arm/kernel/crunch-bits.S
<<
>>
Prefs
   1/*
   2 * arch/arm/kernel/crunch-bits.S
   3 * Cirrus MaverickCrunch context switching and handling
   4 *
   5 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
   6 *
   7 * Shamelessly stolen from the iWMMXt code by Nicolas Pitre, which is
   8 * Copyright (c) 2003-2004, MontaVista Software, Inc.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 */
  14
  15#include <linux/linkage.h>
  16#include <asm/ptrace.h>
  17#include <asm/thread_info.h>
  18#include <asm/asm-offsets.h>
  19#include <mach/ep93xx-regs.h>
  20
  21/*
  22 * We can't use hex constants here due to a bug in gas.
  23 */
  24#define CRUNCH_MVDX0            0
  25#define CRUNCH_MVDX1            8
  26#define CRUNCH_MVDX2            16
  27#define CRUNCH_MVDX3            24
  28#define CRUNCH_MVDX4            32
  29#define CRUNCH_MVDX5            40
  30#define CRUNCH_MVDX6            48
  31#define CRUNCH_MVDX7            56
  32#define CRUNCH_MVDX8            64
  33#define CRUNCH_MVDX9            72
  34#define CRUNCH_MVDX10           80
  35#define CRUNCH_MVDX11           88
  36#define CRUNCH_MVDX12           96
  37#define CRUNCH_MVDX13           104
  38#define CRUNCH_MVDX14           112
  39#define CRUNCH_MVDX15           120
  40#define CRUNCH_MVAX0L           128
  41#define CRUNCH_MVAX0M           132
  42#define CRUNCH_MVAX0H           136
  43#define CRUNCH_MVAX1L           140
  44#define CRUNCH_MVAX1M           144
  45#define CRUNCH_MVAX1H           148
  46#define CRUNCH_MVAX2L           152
  47#define CRUNCH_MVAX2M           156
  48#define CRUNCH_MVAX2H           160
  49#define CRUNCH_MVAX3L           164
  50#define CRUNCH_MVAX3M           168
  51#define CRUNCH_MVAX3H           172
  52#define CRUNCH_DSPSC            176
  53
  54#define CRUNCH_SIZE             184
  55
  56        .text
  57
  58/*
  59 * Lazy switching of crunch coprocessor context
  60 *
  61 * r10 = struct thread_info pointer
  62 * r9  = ret_from_exception
  63 * lr  = undefined instr exit
  64 *
  65 * called from prefetch exception handler with interrupts disabled
  66 */
  67ENTRY(crunch_task_enable)
  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        movne   pc, lr                          @ 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
  93crunch_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        moveq           pc, lr
 146
 147crunch_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        mov     pc, lr
 194
 195/*
 196 * Back up crunch regs to save area and disable access to them
 197 * (mainly for gdb or sleep mode usage)
 198 *
 199 * r0 = struct thread_info pointer of target task or NULL for any
 200 */
 201ENTRY(crunch_task_disable)
 202        stmfd   sp!, {r4, r5, lr}
 203
 204        mrs     ip, cpsr
 205        orr     r2, ip, #PSR_I_BIT              @ disable interrupts
 206        msr     cpsr_c, r2
 207
 208        ldr     r4, =(EP93XX_APB_VIRT_BASE + 0x00130000)        @ syscon addr
 209
 210        ldr     r3, =crunch_owner
 211        add     r2, r0, #TI_CRUNCH_STATE        @ get task crunch save area
 212        ldr     r1, [r3]                        @ get current crunch owner
 213        teq     r1, #0                          @ any current owner?
 214        beq     1f                              @ no: quit
 215        teq     r0, #0                          @ any owner?
 216        teqne   r1, r2                          @ or specified one?
 217        bne     1f                              @ no: quit
 218
 219        ldr     r5, [r4, #0x80]                 @ enable access to crunch
 220        mov     r2, #0xaa
 221        str     r2, [r4, #0xc0]
 222        orr     r5, r5, #0x00800000
 223        str     r5, [r4, #0x80]
 224
 225        mov     r0, #0                          @ nothing to load
 226        str     r0, [r3]                        @ no more current owner
 227        ldr     r2, [r4, #0x80]                 @ flush out enable (@@@)
 228        mov     r2, r2
 229        bl      crunch_save
 230
 231        mov     r2, #0xaa                       @ disable access to crunch
 232        str     r2, [r4, #0xc0]
 233        bic     r5, r5, #0x00800000
 234        str     r5, [r4, #0x80]
 235        ldr     r5, [r4, #0x80]                 @ flush out enable (@@@)
 236        mov     r5, r5
 237
 2381:      msr     cpsr_c, ip                      @ restore interrupt mode
 239        ldmfd   sp!, {r4, r5, pc}
 240
 241/*
 242 * Copy crunch state to given memory address
 243 *
 244 * r0 = struct thread_info pointer of target task
 245 * r1 = memory address where to store crunch state
 246 *
 247 * this is called mainly in the creation of signal stack frames
 248 */
 249ENTRY(crunch_task_copy)
 250        mrs     ip, cpsr
 251        orr     r2, ip, #PSR_I_BIT              @ disable interrupts
 252        msr     cpsr_c, r2
 253
 254        ldr     r3, =crunch_owner
 255        add     r2, r0, #TI_CRUNCH_STATE        @ get task crunch save area
 256        ldr     r3, [r3]                        @ get current crunch owner
 257        teq     r2, r3                          @ does this task own it...
 258        beq     1f
 259
 260        @ current crunch values are in the task save area
 261        msr     cpsr_c, ip                      @ restore interrupt mode
 262        mov     r0, r1
 263        mov     r1, r2
 264        mov     r2, #CRUNCH_SIZE
 265        b       memcpy
 266
 2671:      @ this task owns crunch regs -- grab a copy from there
 268        mov     r0, #0                          @ nothing to load
 269        mov     r3, lr                          @ preserve return address
 270        bl      crunch_save
 271        msr     cpsr_c, ip                      @ restore interrupt mode
 272        mov     pc, r3
 273
 274/*
 275 * Restore crunch state from given memory address
 276 *
 277 * r0 = struct thread_info pointer of target task
 278 * r1 = memory address where to get crunch state from
 279 *
 280 * this is used to restore crunch state when unwinding a signal stack frame
 281 */
 282ENTRY(crunch_task_restore)
 283        mrs     ip, cpsr
 284        orr     r2, ip, #PSR_I_BIT              @ disable interrupts
 285        msr     cpsr_c, r2
 286
 287        ldr     r3, =crunch_owner
 288        add     r2, r0, #TI_CRUNCH_STATE        @ get task crunch save area
 289        ldr     r3, [r3]                        @ get current crunch owner
 290        teq     r2, r3                          @ does this task own it...
 291        beq     1f
 292
 293        @ this task doesn't own crunch regs -- use its save area
 294        msr     cpsr_c, ip                      @ restore interrupt mode
 295        mov     r0, r2
 296        mov     r2, #CRUNCH_SIZE
 297        b       memcpy
 298
 2991:      @ this task owns crunch regs -- load them directly
 300        mov     r0, r1
 301        mov     r1, #0                          @ nothing to save
 302        mov     r3, lr                          @ preserve return address
 303        bl      crunch_load
 304        msr     cpsr_c, ip                      @ restore interrupt mode
 305        mov     pc, r3
 306