Merge branch 'fix/hda' into for-linus
[linux-block.git] / arch / xtensa / kernel / coprocessor.S
CommitLineData
5a0015d6
CZ
1/*
2 * arch/xtensa/kernel/coprocessor.S
3 *
4 * Xtensa processor configuration-specific table of coprocessor and
5 * other custom register layout information.
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 *
c658eac6 11 * Copyright (C) 2003 - 2007 Tensilica Inc.
5a0015d6
CZ
12 */
13
5a0015d6 14
5a0015d6 15#include <linux/linkage.h>
c658eac6 16#include <asm/asm-offsets.h>
5a0015d6 17#include <asm/processor.h>
c658eac6
CZ
18#include <asm/coprocessor.h>
19#include <asm/thread_info.h>
20#include <asm/uaccess.h>
21#include <asm/unistd.h>
22#include <asm/ptrace.h>
23#include <asm/current.h>
24#include <asm/pgtable.h>
25#include <asm/page.h>
26#include <asm/signal.h>
27#include <asm/tlbflush.h>
5a0015d6 28
c658eac6
CZ
29/*
30 * Entry condition:
31 *
32 * a0: trashed, original value saved on stack (PT_AREG0)
33 * a1: a1
34 * a2: new stack pointer, original in DEPC
35 * a3: dispatch table
36 * depc: a2, original value saved on stack (PT_DEPC)
37 * excsave_1: a3
38 *
39 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
40 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
41 */
5a0015d6 42
c658eac6 43/* IO protection is currently unsupported. */
5a0015d6 44
c658eac6
CZ
45ENTRY(fast_io_protect)
46 wsr a0, EXCSAVE_1
47 movi a0, unrecoverable_exception
48 callx0 a0
5a0015d6 49
c658eac6 50#if XTENSA_HAVE_COPROCESSORS
5a0015d6 51
c658eac6
CZ
52/*
53 * Macros for lazy context switch.
54 */
5a0015d6 55
c658eac6
CZ
56#define SAVE_CP_REGS(x) \
57 .align 4; \
58 .Lsave_cp_regs_cp##x: \
59 .if XTENSA_HAVE_COPROCESSOR(x); \
60 xchal_cp##x##_store a2 a4 a5 a6 a7; \
61 .endif; \
62 jx a0
5a0015d6 63
c658eac6
CZ
64#define SAVE_CP_REGS_TAB(x) \
65 .if XTENSA_HAVE_COPROCESSOR(x); \
66 .long .Lsave_cp_regs_cp##x - .Lsave_cp_regs_jump_table; \
67 .else; \
68 .long 0; \
69 .endif; \
70 .long THREAD_XTREGS_CP##x
5a0015d6 71
5a0015d6 72
c658eac6
CZ
73#define LOAD_CP_REGS(x) \
74 .align 4; \
75 .Lload_cp_regs_cp##x: \
76 .if XTENSA_HAVE_COPROCESSOR(x); \
77 xchal_cp##x##_load a2 a4 a5 a6 a7; \
78 .endif; \
79 jx a0
5a0015d6 80
c658eac6
CZ
81#define LOAD_CP_REGS_TAB(x) \
82 .if XTENSA_HAVE_COPROCESSOR(x); \
83 .long .Lload_cp_regs_cp##x - .Lload_cp_regs_jump_table; \
84 .else; \
85 .long 0; \
86 .endif; \
87 .long THREAD_XTREGS_CP##x
5a0015d6 88
c658eac6
CZ
89 SAVE_CP_REGS(0)
90 SAVE_CP_REGS(1)
91 SAVE_CP_REGS(2)
92 SAVE_CP_REGS(3)
93 SAVE_CP_REGS(4)
94 SAVE_CP_REGS(5)
95 SAVE_CP_REGS(6)
96 SAVE_CP_REGS(7)
5a0015d6 97
c658eac6
CZ
98 LOAD_CP_REGS(0)
99 LOAD_CP_REGS(1)
100 LOAD_CP_REGS(2)
101 LOAD_CP_REGS(3)
102 LOAD_CP_REGS(4)
103 LOAD_CP_REGS(5)
104 LOAD_CP_REGS(6)
105 LOAD_CP_REGS(7)
5a0015d6 106
c658eac6
CZ
107 .align 4
108.Lsave_cp_regs_jump_table:
109 SAVE_CP_REGS_TAB(0)
110 SAVE_CP_REGS_TAB(1)
111 SAVE_CP_REGS_TAB(2)
112 SAVE_CP_REGS_TAB(3)
113 SAVE_CP_REGS_TAB(4)
114 SAVE_CP_REGS_TAB(5)
115 SAVE_CP_REGS_TAB(6)
116 SAVE_CP_REGS_TAB(7)
5a0015d6 117
c658eac6
CZ
118.Lload_cp_regs_jump_table:
119 LOAD_CP_REGS_TAB(0)
120 LOAD_CP_REGS_TAB(1)
121 LOAD_CP_REGS_TAB(2)
122 LOAD_CP_REGS_TAB(3)
123 LOAD_CP_REGS_TAB(4)
124 LOAD_CP_REGS_TAB(5)
125 LOAD_CP_REGS_TAB(6)
126 LOAD_CP_REGS_TAB(7)
5a0015d6 127
c658eac6
CZ
128/*
129 * coprocessor_save(buffer, index)
130 * a2 a3
131 * coprocessor_load(buffer, index)
132 * a2 a3
133 *
134 * Save or load coprocessor registers for coprocessor 'index'.
135 * The register values are saved to or loaded from them 'buffer' address.
136 *
137 * Note that these functions don't update the coprocessor_owner information!
138 *
139 */
5a0015d6 140
c658eac6
CZ
141ENTRY(coprocessor_save)
142 entry a1, 32
143 s32i a0, a1, 0
144 movi a0, .Lsave_cp_regs_jump_table
145 addx8 a3, a3, a0
146 l32i a3, a3, 0
147 beqz a3, 1f
148 add a0, a0, a3
149 callx0 a0
1501: l32i a0, a1, 0
5a0015d6
CZ
151 retw
152
c658eac6
CZ
153ENTRY(coprocessor_load)
154 entry a1, 32
155 s32i a0, a1, 0
156 movi a0, .Lload_cp_regs_jump_table
157 addx4 a3, a3, a0
158 l32i a3, a3, 0
159 beqz a3, 1f
160 add a0, a0, a3
161 callx0 a0
1621: l32i a0, a1, 0
5a0015d6
CZ
163 retw
164
c658eac6
CZ
165/*
166 * coprocessor_flush(struct task_info*, index)
167 * a2 a3
168 * coprocessor_restore(struct task_info*, index)
169 * a2 a3
170 *
171 * Save or load coprocessor registers for coprocessor 'index'.
172 * The register values are saved to or loaded from the coprocessor area
173 * inside the task_info structure.
174 *
175 * Note that these functions don't update the coprocessor_owner information!
176 *
177 */
178
179
180ENTRY(coprocessor_flush)
181 entry a1, 32
182 s32i a0, a1, 0
183 movi a0, .Lsave_cp_regs_jump_table
184 addx8 a3, a3, a0
185 l32i a4, a3, 4
186 l32i a3, a3, 0
187 add a2, a2, a4
188 beqz a3, 1f
189 add a0, a0, a3
190 callx0 a0
1911: l32i a0, a1, 0
5a0015d6
CZ
192 retw
193
c658eac6
CZ
194ENTRY(coprocessor_restore)
195 entry a1, 32
196 s32i a0, a1, 0
197 movi a0, .Lload_cp_regs_jump_table
198 addx4 a3, a3, a0
199 l32i a4, a3, 4
200 l32i a3, a3, 0
201 add a2, a2, a4
202 beqz a3, 1f
203 add a0, a0, a3
204 callx0 a0
2051: l32i a0, a1, 0
206 retw
5a0015d6
CZ
207
208/*
c658eac6 209 * Entry condition:
5a0015d6 210 *
c658eac6
CZ
211 * a0: trashed, original value saved on stack (PT_AREG0)
212 * a1: a1
213 * a2: new stack pointer, original in DEPC
214 * a3: dispatch table
215 * depc: a2, original value saved on stack (PT_DEPC)
216 * excsave_1: a3
5a0015d6 217 *
c658eac6
CZ
218 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
219 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
5a0015d6
CZ
220 */
221
c658eac6
CZ
222ENTRY(fast_coprocessor_double)
223 wsr a0, EXCSAVE_1
224 movi a0, unrecoverable_exception
225 callx0 a0
5a0015d6 226
5a0015d6 227
c658eac6
CZ
228ENTRY(fast_coprocessor)
229
230 /* Save remaining registers a1-a3 and SAR */
231
232 xsr a3, EXCSAVE_1
233 s32i a3, a2, PT_AREG3
234 rsr a3, SAR
235 s32i a1, a2, PT_AREG1
236 s32i a3, a2, PT_SAR
237 mov a1, a2
238 rsr a2, DEPC
239 s32i a2, a1, PT_AREG2
240
241 /*
242 * The hal macros require up to 4 temporary registers. We use a3..a6.
243 */
244
245 s32i a4, a1, PT_AREG4
246 s32i a5, a1, PT_AREG5
247 s32i a6, a1, PT_AREG6
248
249 /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */
250
251 rsr a3, EXCCAUSE
252 addi a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
253
254 /* Set corresponding CPENABLE bit -> (sar:cp-index, a3: 1<<cp-index)*/
255
256 ssl a3 # SAR: 32 - coprocessor_number
257 movi a2, 1
258 rsr a0, CPENABLE
259 sll a2, a2
260 or a0, a0, a2
261 wsr a0, CPENABLE
262 rsync
263
264 /* Retrieve previous owner. (a3 still holds CP number) */
265
266 movi a0, coprocessor_owner # list of owners
267 addx4 a0, a3, a0 # entry for CP
268 l32i a4, a0, 0
269
270 beqz a4, 1f # skip 'save' if no previous owner
271
272 /* Disable coprocessor for previous owner. (a2 = 1 << CP number) */
273
274 l32i a5, a4, THREAD_CPENABLE
275 xor a5, a5, a2 # (1 << cp-id) still in a2
276 s32i a5, a4, THREAD_CPENABLE
277
278 /*
279 * Get context save area and 'call' save routine.
280 * (a4 still holds previous owner (thread_info), a3 CP number)
281 */
282
283 movi a5, .Lsave_cp_regs_jump_table
284 movi a0, 2f # a0: 'return' address
285 addx8 a3, a3, a5 # a3: coprocessor number
286 l32i a2, a3, 4 # a2: xtregs offset
287 l32i a3, a3, 0 # a3: jump offset
288 add a2, a2, a4
289 add a4, a3, a5 # a4: address of save routine
290 jx a4
291
292 /* Note that only a0 and a1 were preserved. */
293
2942: rsr a3, EXCCAUSE
295 addi a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
296 movi a0, coprocessor_owner
297 addx4 a0, a3, a0
298
299 /* Set new 'owner' (a0 points to the CP owner, a3 contains the CP nr) */
300
3011: GET_THREAD_INFO (a4, a1)
302 s32i a4, a0, 0
303
304 /* Get context save area and 'call' load routine. */
305
306 movi a5, .Lload_cp_regs_jump_table
307 movi a0, 1f
308 addx8 a3, a3, a5
309 l32i a2, a3, 4 # a2: xtregs offset
310 l32i a3, a3, 0 # a3: jump offset
311 add a2, a2, a4
312 add a4, a3, a5
313 jx a4
314
315 /* Restore all registers and return from exception handler. */
316
3171: l32i a6, a1, PT_AREG6
318 l32i a5, a1, PT_AREG5
319 l32i a4, a1, PT_AREG4
320
321 l32i a0, a1, PT_SAR
322 l32i a3, a1, PT_AREG3
323 l32i a2, a1, PT_AREG2
324 wsr a0, SAR
325 l32i a0, a1, PT_AREG0
326 l32i a1, a1, PT_AREG1
327
328 rfe
329
330 .data
331ENTRY(coprocessor_owner)
332 .fill XCHAL_CP_MAX, 4, 0
333
334#endif /* XTENSA_HAVE_COPROCESSORS */
5a0015d6 335