blob: 80828b95a51f031653fe7be541cf17e536869f52 [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>
Max Filippove3cacb72019-07-24 17:39:47 -070017#include <asm/asmmacro.h>
Chris Zankel5a0015d2005-06-23 22:01:16 -070018#include <asm/processor.h>
Chris Zankelc658eac2008-02-12 13:17:07 -080019#include <asm/coprocessor.h>
20#include <asm/thread_info.h>
Al Viro76580232016-09-04 14:26:36 -040021#include <asm/asm-uaccess.h>
Chris Zankelc658eac2008-02-12 13:17:07 -080022#include <asm/unistd.h>
23#include <asm/ptrace.h>
24#include <asm/current.h>
25#include <asm/pgtable.h>
26#include <asm/page.h>
27#include <asm/signal.h>
28#include <asm/tlbflush.h>
Chris Zankel5a0015d2005-06-23 22:01:16 -070029
Chris Zankelc658eac2008-02-12 13:17:07 -080030#if XTENSA_HAVE_COPROCESSORS
Chris Zankel5a0015d2005-06-23 22:01:16 -070031
Chris Zankelc658eac2008-02-12 13:17:07 -080032/*
33 * Macros for lazy context switch.
34 */
Chris Zankel5a0015d2005-06-23 22:01:16 -070035
Chris Zankelc658eac2008-02-12 13:17:07 -080036#define SAVE_CP_REGS(x) \
Chris Zankelc658eac2008-02-12 13:17:07 -080037 .if XTENSA_HAVE_COPROCESSOR(x); \
Max Filippov5dacbbe2018-11-25 23:32:28 -080038 .align 4; \
39 .Lsave_cp_regs_cp##x: \
Chris Zankelc658eac2008-02-12 13:17:07 -080040 xchal_cp##x##_store a2 a4 a5 a6 a7; \
Max Filippov5dacbbe2018-11-25 23:32:28 -080041 jx a0; \
42 .endif
Chris Zankelc658eac2008-02-12 13:17:07 -080043
44#define SAVE_CP_REGS_TAB(x) \
45 .if XTENSA_HAVE_COPROCESSOR(x); \
Max Filippov5dacbbe2018-11-25 23:32:28 -080046 .long .Lsave_cp_regs_cp##x; \
Chris Zankelc658eac2008-02-12 13:17:07 -080047 .else; \
48 .long 0; \
49 .endif; \
50 .long THREAD_XTREGS_CP##x
51
52
53#define LOAD_CP_REGS(x) \
Chris Zankelc658eac2008-02-12 13:17:07 -080054 .if XTENSA_HAVE_COPROCESSOR(x); \
Max Filippov5dacbbe2018-11-25 23:32:28 -080055 .align 4; \
56 .Lload_cp_regs_cp##x: \
Chris Zankelc658eac2008-02-12 13:17:07 -080057 xchal_cp##x##_load a2 a4 a5 a6 a7; \
Max Filippov5dacbbe2018-11-25 23:32:28 -080058 jx a0; \
59 .endif
Chris Zankelc658eac2008-02-12 13:17:07 -080060
61#define LOAD_CP_REGS_TAB(x) \
62 .if XTENSA_HAVE_COPROCESSOR(x); \
Max Filippov5dacbbe2018-11-25 23:32:28 -080063 .long .Lload_cp_regs_cp##x; \
Chris Zankelc658eac2008-02-12 13:17:07 -080064 .else; \
65 .long 0; \
66 .endif; \
67 .long THREAD_XTREGS_CP##x
68
69 SAVE_CP_REGS(0)
70 SAVE_CP_REGS(1)
71 SAVE_CP_REGS(2)
72 SAVE_CP_REGS(3)
73 SAVE_CP_REGS(4)
74 SAVE_CP_REGS(5)
75 SAVE_CP_REGS(6)
76 SAVE_CP_REGS(7)
77
78 LOAD_CP_REGS(0)
79 LOAD_CP_REGS(1)
80 LOAD_CP_REGS(2)
81 LOAD_CP_REGS(3)
82 LOAD_CP_REGS(4)
83 LOAD_CP_REGS(5)
84 LOAD_CP_REGS(6)
85 LOAD_CP_REGS(7)
86
Max Filippov5dacbbe2018-11-25 23:32:28 -080087 .section ".rodata", "a"
Chris Zankelc658eac2008-02-12 13:17:07 -080088 .align 4
89.Lsave_cp_regs_jump_table:
90 SAVE_CP_REGS_TAB(0)
91 SAVE_CP_REGS_TAB(1)
92 SAVE_CP_REGS_TAB(2)
93 SAVE_CP_REGS_TAB(3)
94 SAVE_CP_REGS_TAB(4)
95 SAVE_CP_REGS_TAB(5)
96 SAVE_CP_REGS_TAB(6)
97 SAVE_CP_REGS_TAB(7)
98
99.Lload_cp_regs_jump_table:
100 LOAD_CP_REGS_TAB(0)
101 LOAD_CP_REGS_TAB(1)
102 LOAD_CP_REGS_TAB(2)
103 LOAD_CP_REGS_TAB(3)
104 LOAD_CP_REGS_TAB(4)
105 LOAD_CP_REGS_TAB(5)
106 LOAD_CP_REGS_TAB(6)
107 LOAD_CP_REGS_TAB(7)
108
Max Filippov5dacbbe2018-11-25 23:32:28 -0800109 .previous
110
Chris Zankelc658eac2008-02-12 13:17:07 -0800111/*
Max Filippov3ffc2df2018-11-26 13:15:21 -0800112 * coprocessor_flush(struct thread_info*, index)
Chris Zankelc658eac2008-02-12 13:17:07 -0800113 * a2 a3
Chris Zankel5a0015d2005-06-23 22:01:16 -0700114 *
Max Filippov3ffc2df2018-11-26 13:15:21 -0800115 * Save coprocessor registers for coprocessor 'index'.
Chris Zankelc658eac2008-02-12 13:17:07 -0800116 * The register values are saved to or loaded from the coprocessor area
117 * inside the task_info structure.
Chris Zankel5a0015d2005-06-23 22:01:16 -0700118 *
Max Filippov3ffc2df2018-11-26 13:15:21 -0800119 * Note that this function doesn't update the coprocessor_owner information!
Chris Zankelc658eac2008-02-12 13:17:07 -0800120 *
Chris Zankel5a0015d2005-06-23 22:01:16 -0700121 */
122
Chris Zankelc658eac2008-02-12 13:17:07 -0800123ENTRY(coprocessor_flush)
Chris Zankeld1538c42012-11-16 16:16:20 -0800124
Max Filippovd6d5f192019-05-12 20:28:25 -0700125 /* reserve 4 bytes on stack to save a0 */
126 abi_entry(4)
127
Chris Zankelc658eac2008-02-12 13:17:07 -0800128 s32i a0, a1, 0
129 movi a0, .Lsave_cp_regs_jump_table
130 addx8 a3, a3, a0
131 l32i a4, a3, 4
132 l32i a3, a3, 0
133 add a2, a2, a4
134 beqz a3, 1f
Max Filippov5dacbbe2018-11-25 23:32:28 -0800135 callx0 a3
Chris Zankelc658eac2008-02-12 13:17:07 -08001361: l32i a0, a1, 0
Max Filippovd6d5f192019-05-12 20:28:25 -0700137
138 abi_ret(4)
Chris Zankel5a0015d2005-06-23 22:01:16 -0700139
Chris Zankeld1538c42012-11-16 16:16:20 -0800140ENDPROC(coprocessor_flush)
141
Chris Zankel5a0015d2005-06-23 22:01:16 -0700142/*
Chris Zankelc658eac2008-02-12 13:17:07 -0800143 * Entry condition:
144 *
145 * a0: trashed, original value saved on stack (PT_AREG0)
146 * a1: a1
147 * a2: new stack pointer, original in DEPC
Max Filippov99d50402013-07-03 20:23:28 +0400148 * a3: a3
Chris Zankelc658eac2008-02-12 13:17:07 -0800149 * depc: a2, original value saved on stack (PT_DEPC)
Max Filippov99d50402013-07-03 20:23:28 +0400150 * excsave_1: dispatch table
Chris Zankelc658eac2008-02-12 13:17:07 -0800151 *
152 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
153 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
Chris Zankel5a0015d2005-06-23 22:01:16 -0700154 */
155
Chris Zankelc658eac2008-02-12 13:17:07 -0800156ENTRY(fast_coprocessor_double)
Chris Zankeld1538c42012-11-16 16:16:20 -0800157
Max Filippovbc5378f2012-10-15 03:55:38 +0400158 wsr a0, excsave1
Max Filippov2da03d42017-12-09 18:44:11 -0800159 call0 unrecoverable_exception
Chris Zankel5a0015d2005-06-23 22:01:16 -0700160
Chris Zankeld1538c42012-11-16 16:16:20 -0800161ENDPROC(fast_coprocessor_double)
Chris Zankelc658eac2008-02-12 13:17:07 -0800162
163ENTRY(fast_coprocessor)
164
165 /* Save remaining registers a1-a3 and SAR */
166
Chris Zankelc658eac2008-02-12 13:17:07 -0800167 s32i a3, a2, PT_AREG3
Max Filippovbc5378f2012-10-15 03:55:38 +0400168 rsr a3, sar
Chris Zankelc658eac2008-02-12 13:17:07 -0800169 s32i a1, a2, PT_AREG1
170 s32i a3, a2, PT_SAR
171 mov a1, a2
Max Filippovbc5378f2012-10-15 03:55:38 +0400172 rsr a2, depc
Chris Zankelc658eac2008-02-12 13:17:07 -0800173 s32i a2, a1, PT_AREG2
174
175 /*
176 * The hal macros require up to 4 temporary registers. We use a3..a6.
177 */
178
179 s32i a4, a1, PT_AREG4
180 s32i a5, a1, PT_AREG5
181 s32i a6, a1, PT_AREG6
182
183 /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */
184
Max Filippovbc5378f2012-10-15 03:55:38 +0400185 rsr a3, exccause
Chris Zankelc658eac2008-02-12 13:17:07 -0800186 addi a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
187
188 /* Set corresponding CPENABLE bit -> (sar:cp-index, a3: 1<<cp-index)*/
189
190 ssl a3 # SAR: 32 - coprocessor_number
191 movi a2, 1
Max Filippovbc5378f2012-10-15 03:55:38 +0400192 rsr a0, cpenable
Chris Zankelc658eac2008-02-12 13:17:07 -0800193 sll a2, a2
194 or a0, a0, a2
Max Filippovbc5378f2012-10-15 03:55:38 +0400195 wsr a0, cpenable
Chris Zankelc658eac2008-02-12 13:17:07 -0800196 rsync
197
198 /* Retrieve previous owner. (a3 still holds CP number) */
199
200 movi a0, coprocessor_owner # list of owners
201 addx4 a0, a3, a0 # entry for CP
202 l32i a4, a0, 0
203
204 beqz a4, 1f # skip 'save' if no previous owner
205
206 /* Disable coprocessor for previous owner. (a2 = 1 << CP number) */
207
208 l32i a5, a4, THREAD_CPENABLE
209 xor a5, a5, a2 # (1 << cp-id) still in a2
210 s32i a5, a4, THREAD_CPENABLE
211
212 /*
213 * Get context save area and 'call' save routine.
214 * (a4 still holds previous owner (thread_info), a3 CP number)
215 */
216
217 movi a5, .Lsave_cp_regs_jump_table
218 movi a0, 2f # a0: 'return' address
219 addx8 a3, a3, a5 # a3: coprocessor number
220 l32i a2, a3, 4 # a2: xtregs offset
Max Filippov5dacbbe2018-11-25 23:32:28 -0800221 l32i a3, a3, 0 # a3: jump address
Chris Zankelc658eac2008-02-12 13:17:07 -0800222 add a2, a2, a4
Max Filippov5dacbbe2018-11-25 23:32:28 -0800223 jx a3
Chris Zankelc658eac2008-02-12 13:17:07 -0800224
225 /* Note that only a0 and a1 were preserved. */
226
Max Filippovbc5378f2012-10-15 03:55:38 +04002272: rsr a3, exccause
Chris Zankelc658eac2008-02-12 13:17:07 -0800228 addi a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
229 movi a0, coprocessor_owner
230 addx4 a0, a3, a0
231
232 /* Set new 'owner' (a0 points to the CP owner, a3 contains the CP nr) */
233
2341: GET_THREAD_INFO (a4, a1)
235 s32i a4, a0, 0
236
237 /* Get context save area and 'call' load routine. */
238
239 movi a5, .Lload_cp_regs_jump_table
240 movi a0, 1f
241 addx8 a3, a3, a5
242 l32i a2, a3, 4 # a2: xtregs offset
Max Filippov5dacbbe2018-11-25 23:32:28 -0800243 l32i a3, a3, 0 # a3: jump address
Chris Zankelc658eac2008-02-12 13:17:07 -0800244 add a2, a2, a4
Max Filippov5dacbbe2018-11-25 23:32:28 -0800245 jx a3
Chris Zankelc658eac2008-02-12 13:17:07 -0800246
247 /* Restore all registers and return from exception handler. */
248
2491: l32i a6, a1, PT_AREG6
250 l32i a5, a1, PT_AREG5
251 l32i a4, a1, PT_AREG4
252
253 l32i a0, a1, PT_SAR
254 l32i a3, a1, PT_AREG3
255 l32i a2, a1, PT_AREG2
Max Filippovbc5378f2012-10-15 03:55:38 +0400256 wsr a0, sar
Chris Zankelc658eac2008-02-12 13:17:07 -0800257 l32i a0, a1, PT_AREG0
258 l32i a1, a1, PT_AREG1
259
260 rfe
261
Chris Zankeld1538c42012-11-16 16:16:20 -0800262ENDPROC(fast_coprocessor)
263
Chris Zankelc658eac2008-02-12 13:17:07 -0800264 .data
Chris Zankeld1538c42012-11-16 16:16:20 -0800265
Chris Zankelc658eac2008-02-12 13:17:07 -0800266ENTRY(coprocessor_owner)
Chris Zankeld1538c42012-11-16 16:16:20 -0800267
Chris Zankelc658eac2008-02-12 13:17:07 -0800268 .fill XCHAL_CP_MAX, 4, 0
269
Chris Zankeld1538c42012-11-16 16:16:20 -0800270END(coprocessor_owner)
271
Chris Zankelc658eac2008-02-12 13:17:07 -0800272#endif /* XTENSA_HAVE_COPROCESSORS */