blob: 60c2200200547a7ad620cb54deb588deeee39521 [file] [log] [blame]
Chris Zankel5a0015d2005-06-23 22:01:16 -07001/*
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 *
Chris Zankelc658eac2008-02-12 13:17:07 -080011 * Copyright (C) 2003 - 2007 Tensilica Inc.
Chris Zankel5a0015d2005-06-23 22:01:16 -070012 */
13
Chris Zankel5a0015d2005-06-23 22:01:16 -070014
Chris Zankel5a0015d2005-06-23 22:01:16 -070015#include <linux/linkage.h>
Chris Zankelc658eac2008-02-12 13:17:07 -080016#include <asm/asm-offsets.h>
Chris Zankel5a0015d2005-06-23 22:01:16 -070017#include <asm/processor.h>
Chris Zankelc658eac2008-02-12 13:17:07 -080018#include <asm/coprocessor.h>
19#include <asm/thread_info.h>
Al Viro76580232016-09-04 14:26:36 -040020#include <asm/asm-uaccess.h>
Chris Zankelc658eac2008-02-12 13:17:07 -080021#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>
Chris Zankel5a0015d2005-06-23 22:01:16 -070028
Chris Zankelc658eac2008-02-12 13:17:07 -080029#if XTENSA_HAVE_COPROCESSORS
Chris Zankel5a0015d2005-06-23 22:01:16 -070030
Chris Zankelc658eac2008-02-12 13:17:07 -080031/*
32 * Macros for lazy context switch.
33 */
Chris Zankel5a0015d2005-06-23 22:01:16 -070034
Chris Zankelc658eac2008-02-12 13:17:07 -080035#define SAVE_CP_REGS(x) \
Chris Zankelc658eac2008-02-12 13:17:07 -080036 .if XTENSA_HAVE_COPROCESSOR(x); \
Max Filippov5dacbbe2018-11-25 23:32:28 -080037 .align 4; \
38 .Lsave_cp_regs_cp##x: \
Chris Zankelc658eac2008-02-12 13:17:07 -080039 xchal_cp##x##_store a2 a4 a5 a6 a7; \
Max Filippov5dacbbe2018-11-25 23:32:28 -080040 jx a0; \
41 .endif
Chris Zankelc658eac2008-02-12 13:17:07 -080042
43#define SAVE_CP_REGS_TAB(x) \
44 .if XTENSA_HAVE_COPROCESSOR(x); \
Max Filippov5dacbbe2018-11-25 23:32:28 -080045 .long .Lsave_cp_regs_cp##x; \
Chris Zankelc658eac2008-02-12 13:17:07 -080046 .else; \
47 .long 0; \
48 .endif; \
49 .long THREAD_XTREGS_CP##x
50
51
52#define LOAD_CP_REGS(x) \
Chris Zankelc658eac2008-02-12 13:17:07 -080053 .if XTENSA_HAVE_COPROCESSOR(x); \
Max Filippov5dacbbe2018-11-25 23:32:28 -080054 .align 4; \
55 .Lload_cp_regs_cp##x: \
Chris Zankelc658eac2008-02-12 13:17:07 -080056 xchal_cp##x##_load a2 a4 a5 a6 a7; \
Max Filippov5dacbbe2018-11-25 23:32:28 -080057 jx a0; \
58 .endif
Chris Zankelc658eac2008-02-12 13:17:07 -080059
60#define LOAD_CP_REGS_TAB(x) \
61 .if XTENSA_HAVE_COPROCESSOR(x); \
Max Filippov5dacbbe2018-11-25 23:32:28 -080062 .long .Lload_cp_regs_cp##x; \
Chris Zankelc658eac2008-02-12 13:17:07 -080063 .else; \
64 .long 0; \
65 .endif; \
66 .long THREAD_XTREGS_CP##x
67
68 SAVE_CP_REGS(0)
69 SAVE_CP_REGS(1)
70 SAVE_CP_REGS(2)
71 SAVE_CP_REGS(3)
72 SAVE_CP_REGS(4)
73 SAVE_CP_REGS(5)
74 SAVE_CP_REGS(6)
75 SAVE_CP_REGS(7)
76
77 LOAD_CP_REGS(0)
78 LOAD_CP_REGS(1)
79 LOAD_CP_REGS(2)
80 LOAD_CP_REGS(3)
81 LOAD_CP_REGS(4)
82 LOAD_CP_REGS(5)
83 LOAD_CP_REGS(6)
84 LOAD_CP_REGS(7)
85
Max Filippov5dacbbe2018-11-25 23:32:28 -080086 .section ".rodata", "a"
Chris Zankelc658eac2008-02-12 13:17:07 -080087 .align 4
88.Lsave_cp_regs_jump_table:
89 SAVE_CP_REGS_TAB(0)
90 SAVE_CP_REGS_TAB(1)
91 SAVE_CP_REGS_TAB(2)
92 SAVE_CP_REGS_TAB(3)
93 SAVE_CP_REGS_TAB(4)
94 SAVE_CP_REGS_TAB(5)
95 SAVE_CP_REGS_TAB(6)
96 SAVE_CP_REGS_TAB(7)
97
98.Lload_cp_regs_jump_table:
99 LOAD_CP_REGS_TAB(0)
100 LOAD_CP_REGS_TAB(1)
101 LOAD_CP_REGS_TAB(2)
102 LOAD_CP_REGS_TAB(3)
103 LOAD_CP_REGS_TAB(4)
104 LOAD_CP_REGS_TAB(5)
105 LOAD_CP_REGS_TAB(6)
106 LOAD_CP_REGS_TAB(7)
107
Max Filippov5dacbbe2018-11-25 23:32:28 -0800108 .previous
109
Chris Zankelc658eac2008-02-12 13:17:07 -0800110/*
Max Filippov3ffc2df2018-11-26 13:15:21 -0800111 * coprocessor_flush(struct thread_info*, index)
Chris Zankelc658eac2008-02-12 13:17:07 -0800112 * a2 a3
Chris Zankel5a0015d2005-06-23 22:01:16 -0700113 *
Max Filippov3ffc2df2018-11-26 13:15:21 -0800114 * Save coprocessor registers for coprocessor 'index'.
Chris Zankelc658eac2008-02-12 13:17:07 -0800115 * The register values are saved to or loaded from the coprocessor area
116 * inside the task_info structure.
Chris Zankel5a0015d2005-06-23 22:01:16 -0700117 *
Max Filippov3ffc2df2018-11-26 13:15:21 -0800118 * Note that this function doesn't update the coprocessor_owner information!
Chris Zankelc658eac2008-02-12 13:17:07 -0800119 *
Chris Zankel5a0015d2005-06-23 22:01:16 -0700120 */
121
Chris Zankelc658eac2008-02-12 13:17:07 -0800122ENTRY(coprocessor_flush)
Chris Zankeld1538c42012-11-16 16:16:20 -0800123
Max Filippovd6d5f192019-05-12 20:28:25 -0700124 /* reserve 4 bytes on stack to save a0 */
125 abi_entry(4)
126
Chris Zankelc658eac2008-02-12 13:17:07 -0800127 s32i a0, a1, 0
128 movi a0, .Lsave_cp_regs_jump_table
129 addx8 a3, a3, a0
130 l32i a4, a3, 4
131 l32i a3, a3, 0
132 add a2, a2, a4
133 beqz a3, 1f
Max Filippov5dacbbe2018-11-25 23:32:28 -0800134 callx0 a3
Chris Zankelc658eac2008-02-12 13:17:07 -08001351: l32i a0, a1, 0
Max Filippovd6d5f192019-05-12 20:28:25 -0700136
137 abi_ret(4)
Chris Zankel5a0015d2005-06-23 22:01:16 -0700138
Chris Zankeld1538c42012-11-16 16:16:20 -0800139ENDPROC(coprocessor_flush)
140
Chris Zankel5a0015d2005-06-23 22:01:16 -0700141/*
Chris Zankelc658eac2008-02-12 13:17:07 -0800142 * Entry condition:
143 *
144 * a0: trashed, original value saved on stack (PT_AREG0)
145 * a1: a1
146 * a2: new stack pointer, original in DEPC
Max Filippov99d50402013-07-03 20:23:28 +0400147 * a3: a3
Chris Zankelc658eac2008-02-12 13:17:07 -0800148 * depc: a2, original value saved on stack (PT_DEPC)
Max Filippov99d50402013-07-03 20:23:28 +0400149 * excsave_1: dispatch table
Chris Zankelc658eac2008-02-12 13:17:07 -0800150 *
151 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
152 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
Chris Zankel5a0015d2005-06-23 22:01:16 -0700153 */
154
Chris Zankelc658eac2008-02-12 13:17:07 -0800155ENTRY(fast_coprocessor_double)
Chris Zankeld1538c42012-11-16 16:16:20 -0800156
Max Filippovbc5378f2012-10-15 03:55:38 +0400157 wsr a0, excsave1
Max Filippov2da03d42017-12-09 18:44:11 -0800158 call0 unrecoverable_exception
Chris Zankel5a0015d2005-06-23 22:01:16 -0700159
Chris Zankeld1538c42012-11-16 16:16:20 -0800160ENDPROC(fast_coprocessor_double)
Chris Zankelc658eac2008-02-12 13:17:07 -0800161
162ENTRY(fast_coprocessor)
163
164 /* Save remaining registers a1-a3 and SAR */
165
Chris Zankelc658eac2008-02-12 13:17:07 -0800166 s32i a3, a2, PT_AREG3
Max Filippovbc5378f2012-10-15 03:55:38 +0400167 rsr a3, sar
Chris Zankelc658eac2008-02-12 13:17:07 -0800168 s32i a1, a2, PT_AREG1
169 s32i a3, a2, PT_SAR
170 mov a1, a2
Max Filippovbc5378f2012-10-15 03:55:38 +0400171 rsr a2, depc
Chris Zankelc658eac2008-02-12 13:17:07 -0800172 s32i a2, a1, PT_AREG2
173
174 /*
175 * The hal macros require up to 4 temporary registers. We use a3..a6.
176 */
177
178 s32i a4, a1, PT_AREG4
179 s32i a5, a1, PT_AREG5
180 s32i a6, a1, PT_AREG6
181
182 /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */
183
Max Filippovbc5378f2012-10-15 03:55:38 +0400184 rsr a3, exccause
Chris Zankelc658eac2008-02-12 13:17:07 -0800185 addi a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
186
187 /* Set corresponding CPENABLE bit -> (sar:cp-index, a3: 1<<cp-index)*/
188
189 ssl a3 # SAR: 32 - coprocessor_number
190 movi a2, 1
Max Filippovbc5378f2012-10-15 03:55:38 +0400191 rsr a0, cpenable
Chris Zankelc658eac2008-02-12 13:17:07 -0800192 sll a2, a2
193 or a0, a0, a2
Max Filippovbc5378f2012-10-15 03:55:38 +0400194 wsr a0, cpenable
Chris Zankelc658eac2008-02-12 13:17:07 -0800195 rsync
196
197 /* Retrieve previous owner. (a3 still holds CP number) */
198
199 movi a0, coprocessor_owner # list of owners
200 addx4 a0, a3, a0 # entry for CP
201 l32i a4, a0, 0
202
203 beqz a4, 1f # skip 'save' if no previous owner
204
205 /* Disable coprocessor for previous owner. (a2 = 1 << CP number) */
206
207 l32i a5, a4, THREAD_CPENABLE
208 xor a5, a5, a2 # (1 << cp-id) still in a2
209 s32i a5, a4, THREAD_CPENABLE
210
211 /*
212 * Get context save area and 'call' save routine.
213 * (a4 still holds previous owner (thread_info), a3 CP number)
214 */
215
216 movi a5, .Lsave_cp_regs_jump_table
217 movi a0, 2f # a0: 'return' address
218 addx8 a3, a3, a5 # a3: coprocessor number
219 l32i a2, a3, 4 # a2: xtregs offset
Max Filippov5dacbbe2018-11-25 23:32:28 -0800220 l32i a3, a3, 0 # a3: jump address
Chris Zankelc658eac2008-02-12 13:17:07 -0800221 add a2, a2, a4
Max Filippov5dacbbe2018-11-25 23:32:28 -0800222 jx a3
Chris Zankelc658eac2008-02-12 13:17:07 -0800223
224 /* Note that only a0 and a1 were preserved. */
225
Max Filippovbc5378f2012-10-15 03:55:38 +04002262: rsr a3, exccause
Chris Zankelc658eac2008-02-12 13:17:07 -0800227 addi a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
228 movi a0, coprocessor_owner
229 addx4 a0, a3, a0
230
231 /* Set new 'owner' (a0 points to the CP owner, a3 contains the CP nr) */
232
2331: GET_THREAD_INFO (a4, a1)
234 s32i a4, a0, 0
235
236 /* Get context save area and 'call' load routine. */
237
238 movi a5, .Lload_cp_regs_jump_table
239 movi a0, 1f
240 addx8 a3, a3, a5
241 l32i a2, a3, 4 # a2: xtregs offset
Max Filippov5dacbbe2018-11-25 23:32:28 -0800242 l32i a3, a3, 0 # a3: jump address
Chris Zankelc658eac2008-02-12 13:17:07 -0800243 add a2, a2, a4
Max Filippov5dacbbe2018-11-25 23:32:28 -0800244 jx a3
Chris Zankelc658eac2008-02-12 13:17:07 -0800245
246 /* Restore all registers and return from exception handler. */
247
2481: l32i a6, a1, PT_AREG6
249 l32i a5, a1, PT_AREG5
250 l32i a4, a1, PT_AREG4
251
252 l32i a0, a1, PT_SAR
253 l32i a3, a1, PT_AREG3
254 l32i a2, a1, PT_AREG2
Max Filippovbc5378f2012-10-15 03:55:38 +0400255 wsr a0, sar
Chris Zankelc658eac2008-02-12 13:17:07 -0800256 l32i a0, a1, PT_AREG0
257 l32i a1, a1, PT_AREG1
258
259 rfe
260
Chris Zankeld1538c42012-11-16 16:16:20 -0800261ENDPROC(fast_coprocessor)
262
Chris Zankelc658eac2008-02-12 13:17:07 -0800263 .data
Chris Zankeld1538c42012-11-16 16:16:20 -0800264
Chris Zankelc658eac2008-02-12 13:17:07 -0800265ENTRY(coprocessor_owner)
Chris Zankeld1538c42012-11-16 16:16:20 -0800266
Chris Zankelc658eac2008-02-12 13:17:07 -0800267 .fill XCHAL_CP_MAX, 4, 0
268
Chris Zankeld1538c42012-11-16 16:16:20 -0800269END(coprocessor_owner)
270
Chris Zankelc658eac2008-02-12 13:17:07 -0800271#endif /* XTENSA_HAVE_COPROCESSORS */