/*1* arch/arm/kernel/crunch-bits.S2* Cirrus MaverickCrunch context switching and handling3*4* Copyright (C) 2006 Lennert Buytenhek <[email protected]>5*6* Shamelessly stolen from the iWMMXt code by Nicolas Pitre, which is7* Copyright (c) 2003-2004, MontaVista Software, Inc.8*9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU General Public License version 2 as11* published by the Free Software Foundation.12*/1314#include <linux/linkage.h>15#include <asm/ptrace.h>16#include <asm/thread_info.h>17#include <asm/asm-offsets.h>18#include <mach/ep93xx-regs.h>1920/*21* We can't use hex constants here due to a bug in gas.22*/23#define CRUNCH_MVDX0 024#define CRUNCH_MVDX1 825#define CRUNCH_MVDX2 1626#define CRUNCH_MVDX3 2427#define CRUNCH_MVDX4 3228#define CRUNCH_MVDX5 4029#define CRUNCH_MVDX6 4830#define CRUNCH_MVDX7 5631#define CRUNCH_MVDX8 6432#define CRUNCH_MVDX9 7233#define CRUNCH_MVDX10 8034#define CRUNCH_MVDX11 8835#define CRUNCH_MVDX12 9636#define CRUNCH_MVDX13 10437#define CRUNCH_MVDX14 11238#define CRUNCH_MVDX15 12039#define CRUNCH_MVAX0L 12840#define CRUNCH_MVAX0M 13241#define CRUNCH_MVAX0H 13642#define CRUNCH_MVAX1L 14043#define CRUNCH_MVAX1M 14444#define CRUNCH_MVAX1H 14845#define CRUNCH_MVAX2L 15246#define CRUNCH_MVAX2M 15647#define CRUNCH_MVAX2H 16048#define CRUNCH_MVAX3L 16449#define CRUNCH_MVAX3M 16850#define CRUNCH_MVAX3H 17251#define CRUNCH_DSPSC 1765253#define CRUNCH_SIZE 1845455.text5657/*58* Lazy switching of crunch coprocessor context59*60* r10 = struct thread_info pointer61* r9 = ret_from_exception62* lr = undefined instr exit63*64* called from prefetch exception handler with interrupts disabled65*/66ENTRY(crunch_task_enable)67ldr r8, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr6869ldr r1, [r8, #0x80]70tst r1, #0x00800000 @ access to crunch enabled?71movne pc, lr @ if so no business here72mov r3, #0xaa @ unlock syscon swlock73str r3, [r8, #0xc0]74orr r1, r1, #0x00800000 @ enable access to crunch75str r1, [r8, #0x80]7677ldr r3, =crunch_owner78add r0, r10, #TI_CRUNCH_STATE @ get task crunch save area79ldr r2, [sp, #60] @ current task pc value80ldr r1, [r3] @ get current crunch owner81str r0, [r3] @ this task now owns crunch82sub r2, r2, #4 @ adjust pc back83str r2, [sp, #60]8485ldr r2, [r8, #0x80]86mov r2, r2 @ flush out enable (@@@)8788teq r1, #0 @ test for last ownership89mov lr, r9 @ normal exit from exception90beq crunch_load @ no owner, skip save9192crunch_save:93cfstr64 mvdx0, [r1, #CRUNCH_MVDX0] @ save 64b registers94cfstr64 mvdx1, [r1, #CRUNCH_MVDX1]95cfstr64 mvdx2, [r1, #CRUNCH_MVDX2]96cfstr64 mvdx3, [r1, #CRUNCH_MVDX3]97cfstr64 mvdx4, [r1, #CRUNCH_MVDX4]98cfstr64 mvdx5, [r1, #CRUNCH_MVDX5]99cfstr64 mvdx6, [r1, #CRUNCH_MVDX6]100cfstr64 mvdx7, [r1, #CRUNCH_MVDX7]101cfstr64 mvdx8, [r1, #CRUNCH_MVDX8]102cfstr64 mvdx9, [r1, #CRUNCH_MVDX9]103cfstr64 mvdx10, [r1, #CRUNCH_MVDX10]104cfstr64 mvdx11, [r1, #CRUNCH_MVDX11]105cfstr64 mvdx12, [r1, #CRUNCH_MVDX12]106cfstr64 mvdx13, [r1, #CRUNCH_MVDX13]107cfstr64 mvdx14, [r1, #CRUNCH_MVDX14]108cfstr64 mvdx15, [r1, #CRUNCH_MVDX15]109110#ifdef __ARMEB__111#error fix me for ARMEB112#endif113114cfmv32al mvfx0, mvax0 @ save 72b accumulators115cfstr32 mvfx0, [r1, #CRUNCH_MVAX0L]116cfmv32am mvfx0, mvax0117cfstr32 mvfx0, [r1, #CRUNCH_MVAX0M]118cfmv32ah mvfx0, mvax0119cfstr32 mvfx0, [r1, #CRUNCH_MVAX0H]120cfmv32al mvfx0, mvax1121cfstr32 mvfx0, [r1, #CRUNCH_MVAX1L]122cfmv32am mvfx0, mvax1123cfstr32 mvfx0, [r1, #CRUNCH_MVAX1M]124cfmv32ah mvfx0, mvax1125cfstr32 mvfx0, [r1, #CRUNCH_MVAX1H]126cfmv32al mvfx0, mvax2127cfstr32 mvfx0, [r1, #CRUNCH_MVAX2L]128cfmv32am mvfx0, mvax2129cfstr32 mvfx0, [r1, #CRUNCH_MVAX2M]130cfmv32ah mvfx0, mvax2131cfstr32 mvfx0, [r1, #CRUNCH_MVAX2H]132cfmv32al mvfx0, mvax3133cfstr32 mvfx0, [r1, #CRUNCH_MVAX3L]134cfmv32am mvfx0, mvax3135cfstr32 mvfx0, [r1, #CRUNCH_MVAX3M]136cfmv32ah mvfx0, mvax3137cfstr32 mvfx0, [r1, #CRUNCH_MVAX3H]138139cfmv32sc mvdx0, dspsc @ save status word140cfstr64 mvdx0, [r1, #CRUNCH_DSPSC]141142teq r0, #0 @ anything to load?143cfldr64eq mvdx0, [r1, #CRUNCH_MVDX0] @ mvdx0 was clobbered144moveq pc, lr145146crunch_load:147cfldr64 mvdx0, [r0, #CRUNCH_DSPSC] @ load status word148cfmvsc32 dspsc, mvdx0149150cfldr32 mvfx0, [r0, #CRUNCH_MVAX0L] @ load 72b accumulators151cfmval32 mvax0, mvfx0152cfldr32 mvfx0, [r0, #CRUNCH_MVAX0M]153cfmvam32 mvax0, mvfx0154cfldr32 mvfx0, [r0, #CRUNCH_MVAX0H]155cfmvah32 mvax0, mvfx0156cfldr32 mvfx0, [r0, #CRUNCH_MVAX1L]157cfmval32 mvax1, mvfx0158cfldr32 mvfx0, [r0, #CRUNCH_MVAX1M]159cfmvam32 mvax1, mvfx0160cfldr32 mvfx0, [r0, #CRUNCH_MVAX1H]161cfmvah32 mvax1, mvfx0162cfldr32 mvfx0, [r0, #CRUNCH_MVAX2L]163cfmval32 mvax2, mvfx0164cfldr32 mvfx0, [r0, #CRUNCH_MVAX2M]165cfmvam32 mvax2, mvfx0166cfldr32 mvfx0, [r0, #CRUNCH_MVAX2H]167cfmvah32 mvax2, mvfx0168cfldr32 mvfx0, [r0, #CRUNCH_MVAX3L]169cfmval32 mvax3, mvfx0170cfldr32 mvfx0, [r0, #CRUNCH_MVAX3M]171cfmvam32 mvax3, mvfx0172cfldr32 mvfx0, [r0, #CRUNCH_MVAX3H]173cfmvah32 mvax3, mvfx0174175cfldr64 mvdx0, [r0, #CRUNCH_MVDX0] @ load 64b registers176cfldr64 mvdx1, [r0, #CRUNCH_MVDX1]177cfldr64 mvdx2, [r0, #CRUNCH_MVDX2]178cfldr64 mvdx3, [r0, #CRUNCH_MVDX3]179cfldr64 mvdx4, [r0, #CRUNCH_MVDX4]180cfldr64 mvdx5, [r0, #CRUNCH_MVDX5]181cfldr64 mvdx6, [r0, #CRUNCH_MVDX6]182cfldr64 mvdx7, [r0, #CRUNCH_MVDX7]183cfldr64 mvdx8, [r0, #CRUNCH_MVDX8]184cfldr64 mvdx9, [r0, #CRUNCH_MVDX9]185cfldr64 mvdx10, [r0, #CRUNCH_MVDX10]186cfldr64 mvdx11, [r0, #CRUNCH_MVDX11]187cfldr64 mvdx12, [r0, #CRUNCH_MVDX12]188cfldr64 mvdx13, [r0, #CRUNCH_MVDX13]189cfldr64 mvdx14, [r0, #CRUNCH_MVDX14]190cfldr64 mvdx15, [r0, #CRUNCH_MVDX15]191192mov pc, lr193194/*195* Back up crunch regs to save area and disable access to them196* (mainly for gdb or sleep mode usage)197*198* r0 = struct thread_info pointer of target task or NULL for any199*/200ENTRY(crunch_task_disable)201stmfd sp!, {r4, r5, lr}202203mrs ip, cpsr204orr r2, ip, #PSR_I_BIT @ disable interrupts205msr cpsr_c, r2206207ldr r4, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr208209ldr r3, =crunch_owner210add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area211ldr r1, [r3] @ get current crunch owner212teq r1, #0 @ any current owner?213beq 1f @ no: quit214teq r0, #0 @ any owner?215teqne r1, r2 @ or specified one?216bne 1f @ no: quit217218ldr r5, [r4, #0x80] @ enable access to crunch219mov r2, #0xaa220str r2, [r4, #0xc0]221orr r5, r5, #0x00800000222str r5, [r4, #0x80]223224mov r0, #0 @ nothing to load225str r0, [r3] @ no more current owner226ldr r2, [r4, #0x80] @ flush out enable (@@@)227mov r2, r2228bl crunch_save229230mov r2, #0xaa @ disable access to crunch231str r2, [r4, #0xc0]232bic r5, r5, #0x00800000233str r5, [r4, #0x80]234ldr r5, [r4, #0x80] @ flush out enable (@@@)235mov r5, r52362371: msr cpsr_c, ip @ restore interrupt mode238ldmfd sp!, {r4, r5, pc}239240/*241* Copy crunch state to given memory address242*243* r0 = struct thread_info pointer of target task244* r1 = memory address where to store crunch state245*246* this is called mainly in the creation of signal stack frames247*/248ENTRY(crunch_task_copy)249mrs ip, cpsr250orr r2, ip, #PSR_I_BIT @ disable interrupts251msr cpsr_c, r2252253ldr r3, =crunch_owner254add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area255ldr r3, [r3] @ get current crunch owner256teq r2, r3 @ does this task own it...257beq 1f258259@ current crunch values are in the task save area260msr cpsr_c, ip @ restore interrupt mode261mov r0, r1262mov r1, r2263mov r2, #CRUNCH_SIZE264b memcpy2652661: @ this task owns crunch regs -- grab a copy from there267mov r0, #0 @ nothing to load268mov r3, lr @ preserve return address269bl crunch_save270msr cpsr_c, ip @ restore interrupt mode271mov pc, r3272273/*274* Restore crunch state from given memory address275*276* r0 = struct thread_info pointer of target task277* r1 = memory address where to get crunch state from278*279* this is used to restore crunch state when unwinding a signal stack frame280*/281ENTRY(crunch_task_restore)282mrs ip, cpsr283orr r2, ip, #PSR_I_BIT @ disable interrupts284msr cpsr_c, r2285286ldr r3, =crunch_owner287add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area288ldr r3, [r3] @ get current crunch owner289teq r2, r3 @ does this task own it...290beq 1f291292@ this task doesn't own crunch regs -- use its save area293msr cpsr_c, ip @ restore interrupt mode294mov r0, r2295mov r2, #CRUNCH_SIZE296b memcpy2972981: @ this task owns crunch regs -- load them directly299mov r0, r1300mov r1, #0 @ nothing to save301mov r3, lr @ preserve return address302bl crunch_load303msr cpsr_c, ip @ restore interrupt mode304mov pc, r3305306307