PageRenderTime 24ms CodeModel.GetById 10ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

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

https://github.com/AICP/kernel_google_msm
Assembly | 305 lines | 302 code | 3 blank | 0 comment | 0 complexity | a2c84416cbf7817d9f99f3a5831405a2 MD5 | raw file
  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