xref: /linux/arch/xtensa/kernel/entry.S (revision a4cdb556cae05cd3e7b602b3a44c01420c4e2258)
1/*
2 * Low-level exception handling
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License.  See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2004 - 2008 by Tensilica Inc.
9 * Copyright (C) 2015 Cadence Design Systems Inc.
10 *
11 * Chris Zankel <chris@zankel.net>
12 *
13 */
14
15#include <linux/linkage.h>
16#include <asm/asm-offsets.h>
17#include <asm/processor.h>
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>
28#include <variant/tie-asm.h>
29
30/* Unimplemented features. */
31
32#undef KERNEL_STACK_OVERFLOW_CHECK
33
34/* Not well tested.
35 *
36 * - fast_coprocessor
37 */
38
39/*
40 * Macro to find first bit set in WINDOWBASE from the left + 1
41 *
42 * 100....0 -> 1
43 * 010....0 -> 2
44 * 000....1 -> WSBITS
45 */
46
47	.macro ffs_ws bit mask
48
49#if XCHAL_HAVE_NSA
50	nsau    \bit, \mask			# 32-WSBITS ... 31 (32 iff 0)
51	addi    \bit, \bit, WSBITS - 32 + 1   	# uppest bit set -> return 1
52#else
53	movi    \bit, WSBITS
54#if WSBITS > 16
55	_bltui  \mask, 0x10000, 99f
56	addi    \bit, \bit, -16
57	extui   \mask, \mask, 16, 16
58#endif
59#if WSBITS > 8
6099:	_bltui  \mask, 0x100, 99f
61	addi    \bit, \bit, -8
62	srli    \mask, \mask, 8
63#endif
6499:	_bltui  \mask, 0x10, 99f
65	addi    \bit, \bit, -4
66	srli    \mask, \mask, 4
6799:	_bltui  \mask, 0x4, 99f
68	addi    \bit, \bit, -2
69	srli    \mask, \mask, 2
7099:	_bltui  \mask, 0x2, 99f
71	addi    \bit, \bit, -1
7299:
73
74#endif
75	.endm
76
77
78	.macro	irq_save flags tmp
79#if XTENSA_FAKE_NMI
80#if defined(CONFIG_DEBUG_KERNEL) && (LOCKLEVEL | TOPLEVEL) >= XCHAL_DEBUGLEVEL
81	rsr	\flags, ps
82	extui	\tmp, \flags, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
83	bgei	\tmp, LOCKLEVEL, 99f
84	rsil	\tmp, LOCKLEVEL
8599:
86#else
87	movi	\tmp, LOCKLEVEL
88	rsr	\flags, ps
89	or	\flags, \flags, \tmp
90	xsr	\flags, ps
91	rsync
92#endif
93#else
94	rsil	\flags, LOCKLEVEL
95#endif
96	.endm
97
98/* ----------------- DEFAULT FIRST LEVEL EXCEPTION HANDLERS ----------------- */
99
100/*
101 * First-level exception handler for user exceptions.
102 * Save some special registers, extra states and all registers in the AR
103 * register file that were in use in the user task, and jump to the common
104 * exception code.
105 * We save SAR (used to calculate WMASK), and WB and WS (we don't have to
106 * save them for kernel exceptions).
107 *
108 * Entry condition for user_exception:
109 *
110 *   a0:	trashed, original value saved on stack (PT_AREG0)
111 *   a1:	a1
112 *   a2:	new stack pointer, original value in depc
113 *   a3:	a3
114 *   depc:	a2, original value saved on stack (PT_DEPC)
115 *   excsave1:	dispatch table
116 *
117 *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
118 *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
119 *
120 * Entry condition for _user_exception:
121 *
122 *   a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC
123 *   excsave has been restored, and
124 *   stack pointer (a1) has been set.
125 *
126 * Note: _user_exception might be at an odd address. Don't use call0..call12
127 */
128
129ENTRY(user_exception)
130
131	/* Save a1, a2, a3, and set SP. */
132
133	rsr	a0, depc
134	s32i	a1, a2, PT_AREG1
135	s32i	a0, a2, PT_AREG2
136	s32i	a3, a2, PT_AREG3
137	mov	a1, a2
138
139	.globl _user_exception
140_user_exception:
141
142	/* Save SAR and turn off single stepping */
143
144	movi	a2, 0
145	wsr	a2, depc		# terminate user stack trace with 0
146	rsr	a3, sar
147	xsr	a2, icountlevel
148	s32i	a3, a1, PT_SAR
149	s32i	a2, a1, PT_ICOUNTLEVEL
150
151#if XCHAL_HAVE_THREADPTR
152	rur	a2, threadptr
153	s32i	a2, a1, PT_THREADPTR
154#endif
155
156	/* Rotate ws so that the current windowbase is at bit0. */
157	/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
158
159	rsr	a2, windowbase
160	rsr	a3, windowstart
161	ssr	a2
162	s32i	a2, a1, PT_WINDOWBASE
163	s32i	a3, a1, PT_WINDOWSTART
164	slli	a2, a3, 32-WSBITS
165	src	a2, a3, a2
166	srli	a2, a2, 32-WSBITS
167	s32i	a2, a1, PT_WMASK	# needed for restoring registers
168
169	/* Save only live registers. */
170
171	_bbsi.l	a2, 1, 1f
172	s32i	a4, a1, PT_AREG4
173	s32i	a5, a1, PT_AREG5
174	s32i	a6, a1, PT_AREG6
175	s32i	a7, a1, PT_AREG7
176	_bbsi.l	a2, 2, 1f
177	s32i	a8, a1, PT_AREG8
178	s32i	a9, a1, PT_AREG9
179	s32i	a10, a1, PT_AREG10
180	s32i	a11, a1, PT_AREG11
181	_bbsi.l	a2, 3, 1f
182	s32i	a12, a1, PT_AREG12
183	s32i	a13, a1, PT_AREG13
184	s32i	a14, a1, PT_AREG14
185	s32i	a15, a1, PT_AREG15
186	_bnei	a2, 1, 1f		# only one valid frame?
187
188	/* Only one valid frame, skip saving regs. */
189
190	j	2f
191
192	/* Save the remaining registers.
193	 * We have to save all registers up to the first '1' from
194	 * the right, except the current frame (bit 0).
195	 * Assume a2 is:  001001000110001
196	 * All register frames starting from the top field to the marked '1'
197	 * must be saved.
198	 */
199
2001:	addi	a3, a2, -1		# eliminate '1' in bit 0: yyyyxxww0
201	neg	a3, a3			# yyyyxxww0 -> YYYYXXWW1+1
202	and	a3, a3, a2		# max. only one bit is set
203
204	/* Find number of frames to save */
205
206	ffs_ws	a0, a3			# number of frames to the '1' from left
207
208	/* Store information into WMASK:
209	 * bits 0..3: xxx1 masked lower 4 bits of the rotated windowstart,
210	 * bits 4...: number of valid 4-register frames
211	 */
212
213	slli	a3, a0, 4		# number of frames to save in bits 8..4
214	extui	a2, a2, 0, 4		# mask for the first 16 registers
215	or	a2, a3, a2
216	s32i	a2, a1, PT_WMASK	# needed when we restore the reg-file
217
218	/* Save 4 registers at a time */
219
2201:	rotw	-1
221	s32i	a0, a5, PT_AREG_END - 16
222	s32i	a1, a5, PT_AREG_END - 12
223	s32i	a2, a5, PT_AREG_END - 8
224	s32i	a3, a5, PT_AREG_END - 4
225	addi	a0, a4, -1
226	addi	a1, a5, -16
227	_bnez	a0, 1b
228
229	/* WINDOWBASE still in SAR! */
230
231	rsr	a2, sar			# original WINDOWBASE
232	movi	a3, 1
233	ssl	a2
234	sll	a3, a3
235	wsr	a3, windowstart		# set corresponding WINDOWSTART bit
236	wsr	a2, windowbase		# and WINDOWSTART
237	rsync
238
239	/* We are back to the original stack pointer (a1) */
240
2412:	/* Now, jump to the common exception handler. */
242
243	j	common_exception
244
245ENDPROC(user_exception)
246
247/*
248 * First-level exit handler for kernel exceptions
249 * Save special registers and the live window frame.
250 * Note: Even though we changes the stack pointer, we don't have to do a
251 *	 MOVSP here, as we do that when we return from the exception.
252 *	 (See comment in the kernel exception exit code)
253 *
254 * Entry condition for kernel_exception:
255 *
256 *   a0:	trashed, original value saved on stack (PT_AREG0)
257 *   a1:	a1
258 *   a2:	new stack pointer, original in DEPC
259 *   a3:	a3
260 *   depc:	a2, original value saved on stack (PT_DEPC)
261 *   excsave_1:	dispatch table
262 *
263 *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
264 *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
265 *
266 * Entry condition for _kernel_exception:
267 *
268 *   a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC
269 *   excsave has been restored, and
270 *   stack pointer (a1) has been set.
271 *
272 * Note: _kernel_exception might be at an odd address. Don't use call0..call12
273 */
274
275ENTRY(kernel_exception)
276
277	/* Save a1, a2, a3, and set SP. */
278
279	rsr	a0, depc		# get a2
280	s32i	a1, a2, PT_AREG1
281	s32i	a0, a2, PT_AREG2
282	s32i	a3, a2, PT_AREG3
283	mov	a1, a2
284
285	.globl _kernel_exception
286_kernel_exception:
287
288	/* Save SAR and turn off single stepping */
289
290	movi	a2, 0
291	rsr	a3, sar
292	xsr	a2, icountlevel
293	s32i	a3, a1, PT_SAR
294	s32i	a2, a1, PT_ICOUNTLEVEL
295
296	/* Rotate ws so that the current windowbase is at bit0. */
297	/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
298
299	rsr	a2, windowbase		# don't need to save these, we only
300	rsr	a3, windowstart		# need shifted windowstart: windowmask
301	ssr	a2
302	slli	a2, a3, 32-WSBITS
303	src	a2, a3, a2
304	srli	a2, a2, 32-WSBITS
305	s32i	a2, a1, PT_WMASK	# needed for kernel_exception_exit
306
307	/* Save only the live window-frame */
308
309	_bbsi.l	a2, 1, 1f
310	s32i	a4, a1, PT_AREG4
311	s32i	a5, a1, PT_AREG5
312	s32i	a6, a1, PT_AREG6
313	s32i	a7, a1, PT_AREG7
314	_bbsi.l	a2, 2, 1f
315	s32i	a8, a1, PT_AREG8
316	s32i	a9, a1, PT_AREG9
317	s32i	a10, a1, PT_AREG10
318	s32i	a11, a1, PT_AREG11
319	_bbsi.l	a2, 3, 1f
320	s32i	a12, a1, PT_AREG12
321	s32i	a13, a1, PT_AREG13
322	s32i	a14, a1, PT_AREG14
323	s32i	a15, a1, PT_AREG15
324
325	_bnei	a2, 1, 1f
326
327	/* Copy spill slots of a0 and a1 to imitate movsp
328	 * in order to keep exception stack continuous
329	 */
330	l32i	a3, a1, PT_SIZE
331	l32i	a0, a1, PT_SIZE + 4
332	s32e	a3, a1, -16
333	s32e	a0, a1, -12
3341:
335	l32i	a0, a1, PT_AREG0	# restore saved a0
336	wsr	a0, depc
337
338#ifdef KERNEL_STACK_OVERFLOW_CHECK
339
340	/*  Stack overflow check, for debugging  */
341	extui	a2, a1, TASK_SIZE_BITS,XX
342	movi	a3, SIZE??
343	_bge	a2, a3, out_of_stack_panic
344
345#endif
346
347/*
348 * This is the common exception handler.
349 * We get here from the user exception handler or simply by falling through
350 * from the kernel exception handler.
351 * Save the remaining special registers, switch to kernel mode, and jump
352 * to the second-level exception handler.
353 *
354 */
355
356common_exception:
357
358	/* Save some registers, disable loops and clear the syscall flag. */
359
360	rsr	a2, debugcause
361	rsr	a3, epc1
362	s32i	a2, a1, PT_DEBUGCAUSE
363	s32i	a3, a1, PT_PC
364
365	movi	a2, -1
366	rsr	a3, excvaddr
367	s32i	a2, a1, PT_SYSCALL
368	movi	a2, 0
369	s32i	a3, a1, PT_EXCVADDR
370#if XCHAL_HAVE_LOOPS
371	xsr	a2, lcount
372	s32i	a2, a1, PT_LCOUNT
373#endif
374
375	/* It is now save to restore the EXC_TABLE_FIXUP variable. */
376
377	rsr	a2, exccause
378	movi	a3, 0
379	rsr	a0, excsave1
380	s32i	a2, a1, PT_EXCCAUSE
381	s32i	a3, a0, EXC_TABLE_FIXUP
382
383	/* All unrecoverable states are saved on stack, now, and a1 is valid.
384	 * Now we can allow exceptions again. In case we've got an interrupt
385	 * PS.INTLEVEL is set to LOCKLEVEL disabling furhter interrupts,
386	 * otherwise it's left unchanged.
387	 *
388	 * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
389	 */
390
391	rsr	a3, ps
392	s32i	a3, a1, PT_PS		# save ps
393
394#if XTENSA_FAKE_NMI
395	/* Correct PS needs to be saved in the PT_PS:
396	 * - in case of exception or level-1 interrupt it's in the PS,
397	 *   and is already saved.
398	 * - in case of medium level interrupt it's in the excsave2.
399	 */
400	movi	a0, EXCCAUSE_MAPPED_NMI
401	extui	a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
402	beq	a2, a0, .Lmedium_level_irq
403	bnei	a2, EXCCAUSE_LEVEL1_INTERRUPT, .Lexception
404	beqz	a3, .Llevel1_irq	# level-1 IRQ sets ps.intlevel to 0
405
406.Lmedium_level_irq:
407	rsr	a0, excsave2
408	s32i	a0, a1, PT_PS		# save medium-level interrupt ps
409	bgei	a3, LOCKLEVEL, .Lexception
410
411.Llevel1_irq:
412	movi	a3, LOCKLEVEL
413
414.Lexception:
415	movi	a0, 1 << PS_WOE_BIT
416	or	a3, a3, a0
417#else
418	addi	a2, a2, -EXCCAUSE_LEVEL1_INTERRUPT
419	movi	a0, LOCKLEVEL
420	extui	a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
421					# a3 = PS.INTLEVEL
422	moveqz	a3, a0, a2		# a3 = LOCKLEVEL iff interrupt
423	movi	a2, 1 << PS_WOE_BIT
424	or	a3, a3, a2
425	rsr	a2, exccause
426#endif
427
428	/* restore return address (or 0 if return to userspace) */
429	rsr	a0, depc
430	wsr	a3, ps
431	rsync				# PS.WOE => rsync => overflow
432
433	/* Save lbeg, lend */
434#if XCHAL_HAVE_LOOPS
435	rsr	a4, lbeg
436	rsr	a3, lend
437	s32i	a4, a1, PT_LBEG
438	s32i	a3, a1, PT_LEND
439#endif
440
441	/* Save SCOMPARE1 */
442
443#if XCHAL_HAVE_S32C1I
444	rsr     a3, scompare1
445	s32i    a3, a1, PT_SCOMPARE1
446#endif
447
448	/* Save optional registers. */
449
450	save_xtregs_opt a1 a3 a4 a5 a6 a7 PT_XTREGS_OPT
451
452	/* Go to second-level dispatcher. Set up parameters to pass to the
453	 * exception handler and call the exception handler.
454	 */
455
456	rsr	a4, excsave1
457	mov	a6, a1			# pass stack frame
458	mov	a7, a2			# pass EXCCAUSE
459	addx4	a4, a2, a4
460	l32i	a4, a4, EXC_TABLE_DEFAULT		# load handler
461
462	/* Call the second-level handler */
463
464	callx4	a4
465
466	/* Jump here for exception exit */
467	.global common_exception_return
468common_exception_return:
469
470#if XTENSA_FAKE_NMI
471	l32i	a2, a1, PT_EXCCAUSE
472	movi	a3, EXCCAUSE_MAPPED_NMI
473	beq	a2, a3, .LNMIexit
474#endif
4751:
476	irq_save a2, a3
477#ifdef CONFIG_TRACE_IRQFLAGS
478	movi	a4, trace_hardirqs_off
479	callx4	a4
480#endif
481
482	/* Jump if we are returning from kernel exceptions. */
483
484	l32i	a3, a1, PT_PS
485	GET_THREAD_INFO(a2, a1)
486	l32i	a4, a2, TI_FLAGS
487	_bbci.l	a3, PS_UM_BIT, 6f
488
489	/* Specific to a user exception exit:
490	 * We need to check some flags for signal handling and rescheduling,
491	 * and have to restore WB and WS, extra states, and all registers
492	 * in the register file that were in use in the user task.
493	 * Note that we don't disable interrupts here.
494	 */
495
496	_bbsi.l	a4, TIF_NEED_RESCHED, 3f
497	_bbsi.l	a4, TIF_NOTIFY_RESUME, 2f
498	_bbci.l	a4, TIF_SIGPENDING, 5f
499
5002:	l32i	a4, a1, PT_DEPC
501	bgeui	a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
502
503	/* Call do_signal() */
504
505#ifdef CONFIG_TRACE_IRQFLAGS
506	movi	a4, trace_hardirqs_on
507	callx4	a4
508#endif
509	rsil	a2, 0
510	movi	a4, do_notify_resume	# int do_notify_resume(struct pt_regs*)
511	mov	a6, a1
512	callx4	a4
513	j	1b
514
5153:	/* Reschedule */
516
517#ifdef CONFIG_TRACE_IRQFLAGS
518	movi	a4, trace_hardirqs_on
519	callx4	a4
520#endif
521	rsil	a2, 0
522	movi	a4, schedule	# void schedule (void)
523	callx4	a4
524	j	1b
525
526#ifdef CONFIG_PREEMPT
5276:
528	_bbci.l	a4, TIF_NEED_RESCHED, 4f
529
530	/* Check current_thread_info->preempt_count */
531
532	l32i	a4, a2, TI_PRE_COUNT
533	bnez	a4, 4f
534	movi	a4, preempt_schedule_irq
535	callx4	a4
536	j	1b
537#endif
538
539#if XTENSA_FAKE_NMI
540.LNMIexit:
541	l32i	a3, a1, PT_PS
542	_bbci.l	a3, PS_UM_BIT, 4f
543#endif
544
5455:
546#ifdef CONFIG_DEBUG_TLB_SANITY
547	l32i	a4, a1, PT_DEPC
548	bgeui	a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
549	movi	a4, check_tlb_sanity
550	callx4	a4
551#endif
5526:
5534:
554#ifdef CONFIG_TRACE_IRQFLAGS
555	extui	a4, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
556	bgei	a4, LOCKLEVEL, 1f
557	movi	a4, trace_hardirqs_on
558	callx4	a4
5591:
560#endif
561	/* Restore optional registers. */
562
563	load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
564
565	/* Restore SCOMPARE1 */
566
567#if XCHAL_HAVE_S32C1I
568	l32i    a2, a1, PT_SCOMPARE1
569	wsr     a2, scompare1
570#endif
571	wsr	a3, ps		/* disable interrupts */
572
573	_bbci.l	a3, PS_UM_BIT, kernel_exception_exit
574
575user_exception_exit:
576
577	/* Restore the state of the task and return from the exception. */
578
579	/* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */
580
581	l32i	a2, a1, PT_WINDOWBASE
582	l32i	a3, a1, PT_WINDOWSTART
583	wsr	a1, depc		# use DEPC as temp storage
584	wsr	a3, windowstart		# restore WINDOWSTART
585	ssr	a2			# preserve user's WB in the SAR
586	wsr	a2, windowbase		# switch to user's saved WB
587	rsync
588	rsr	a1, depc		# restore stack pointer
589	l32i	a2, a1, PT_WMASK	# register frames saved (in bits 4...9)
590	rotw	-1			# we restore a4..a7
591	_bltui	a6, 16, 1f		# only have to restore current window?
592
593	/* The working registers are a0 and a3.  We are restoring to
594	 * a4..a7.  Be careful not to destroy what we have just restored.
595	 * Note: wmask has the format YYYYM:
596	 *       Y: number of registers saved in groups of 4
597	 *       M: 4 bit mask of first 16 registers
598	 */
599
600	mov	a2, a6
601	mov	a3, a5
602
6032:	rotw	-1			# a0..a3 become a4..a7
604	addi	a3, a7, -4*4		# next iteration
605	addi	a2, a6, -16		# decrementing Y in WMASK
606	l32i	a4, a3, PT_AREG_END + 0
607	l32i	a5, a3, PT_AREG_END + 4
608	l32i	a6, a3, PT_AREG_END + 8
609	l32i	a7, a3, PT_AREG_END + 12
610	_bgeui	a2, 16, 2b
611
612	/* Clear unrestored registers (don't leak anything to user-land */
613
6141:	rsr	a0, windowbase
615	rsr	a3, sar
616	sub	a3, a0, a3
617	beqz	a3, 2f
618	extui	a3, a3, 0, WBBITS
619
6201:	rotw	-1
621	addi	a3, a7, -1
622	movi	a4, 0
623	movi	a5, 0
624	movi	a6, 0
625	movi	a7, 0
626	bgei	a3, 1, 1b
627
628	/* We are back were we were when we started.
629	 * Note: a2 still contains WMASK (if we've returned to the original
630	 *	 frame where we had loaded a2), or at least the lower 4 bits
631	 *	 (if we have restored WSBITS-1 frames).
632	 */
633
6342:
635#if XCHAL_HAVE_THREADPTR
636	l32i	a3, a1, PT_THREADPTR
637	wur	a3, threadptr
638#endif
639
640	j	common_exception_exit
641
642	/* This is the kernel exception exit.
643	 * We avoided to do a MOVSP when we entered the exception, but we
644	 * have to do it here.
645	 */
646
647kernel_exception_exit:
648
649	/* Check if we have to do a movsp.
650	 *
651	 * We only have to do a movsp if the previous window-frame has
652	 * been spilled to the *temporary* exception stack instead of the
653	 * task's stack. This is the case if the corresponding bit in
654	 * WINDOWSTART for the previous window-frame was set before
655	 * (not spilled) but is zero now (spilled).
656	 * If this bit is zero, all other bits except the one for the
657	 * current window frame are also zero. So, we can use a simple test:
658	 * 'and' WINDOWSTART and WINDOWSTART-1:
659	 *
660	 *  (XXXXXX1[0]* - 1) AND XXXXXX1[0]* = XXXXXX0[0]*
661	 *
662	 * The result is zero only if one bit was set.
663	 *
664	 * (Note: We might have gone through several task switches before
665	 *        we come back to the current task, so WINDOWBASE might be
666	 *        different from the time the exception occurred.)
667	 */
668
669	/* Test WINDOWSTART before and after the exception.
670	 * We actually have WMASK, so we only have to test if it is 1 or not.
671	 */
672
673	l32i	a2, a1, PT_WMASK
674	_beqi	a2, 1, common_exception_exit	# Spilled before exception,jump
675
676	/* Test WINDOWSTART now. If spilled, do the movsp */
677
678	rsr     a3, windowstart
679	addi	a0, a3, -1
680	and     a3, a3, a0
681	_bnez	a3, common_exception_exit
682
683	/* Do a movsp (we returned from a call4, so we have at least a0..a7) */
684
685	addi    a0, a1, -16
686	l32i    a3, a0, 0
687	l32i    a4, a0, 4
688	s32i    a3, a1, PT_SIZE+0
689	s32i    a4, a1, PT_SIZE+4
690	l32i    a3, a0, 8
691	l32i    a4, a0, 12
692	s32i    a3, a1, PT_SIZE+8
693	s32i    a4, a1, PT_SIZE+12
694
695	/* Common exception exit.
696	 * We restore the special register and the current window frame, and
697	 * return from the exception.
698	 *
699	 * Note: We expect a2 to hold PT_WMASK
700	 */
701
702common_exception_exit:
703
704	/* Restore address registers. */
705
706	_bbsi.l	a2, 1, 1f
707	l32i	a4,  a1, PT_AREG4
708	l32i	a5,  a1, PT_AREG5
709	l32i	a6,  a1, PT_AREG6
710	l32i	a7,  a1, PT_AREG7
711	_bbsi.l	a2, 2, 1f
712	l32i	a8,  a1, PT_AREG8
713	l32i	a9,  a1, PT_AREG9
714	l32i	a10, a1, PT_AREG10
715	l32i	a11, a1, PT_AREG11
716	_bbsi.l	a2, 3, 1f
717	l32i	a12, a1, PT_AREG12
718	l32i	a13, a1, PT_AREG13
719	l32i	a14, a1, PT_AREG14
720	l32i	a15, a1, PT_AREG15
721
722	/* Restore PC, SAR */
723
7241:	l32i	a2, a1, PT_PC
725	l32i	a3, a1, PT_SAR
726	wsr	a2, epc1
727	wsr	a3, sar
728
729	/* Restore LBEG, LEND, LCOUNT */
730#if XCHAL_HAVE_LOOPS
731	l32i	a2, a1, PT_LBEG
732	l32i	a3, a1, PT_LEND
733	wsr	a2, lbeg
734	l32i	a2, a1, PT_LCOUNT
735	wsr	a3, lend
736	wsr	a2, lcount
737#endif
738
739	/* We control single stepping through the ICOUNTLEVEL register. */
740
741	l32i	a2, a1, PT_ICOUNTLEVEL
742	movi	a3, -2
743	wsr	a2, icountlevel
744	wsr	a3, icount
745
746	/* Check if it was double exception. */
747
748	l32i	a0, a1, PT_DEPC
749	l32i	a3, a1, PT_AREG3
750	l32i	a2, a1, PT_AREG2
751	_bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
752
753	/* Restore a0...a3 and return */
754
755	l32i	a0, a1, PT_AREG0
756	l32i	a1, a1, PT_AREG1
757	rfe
758
7591: 	wsr	a0, depc
760	l32i	a0, a1, PT_AREG0
761	l32i	a1, a1, PT_AREG1
762	rfde
763
764ENDPROC(kernel_exception)
765
766/*
767 * Debug exception handler.
768 *
769 * Currently, we don't support KGDB, so only user application can be debugged.
770 *
771 * When we get here,  a0 is trashed and saved to excsave[debuglevel]
772 */
773
774ENTRY(debug_exception)
775
776	rsr	a0, SREG_EPS + XCHAL_DEBUGLEVEL
777	bbsi.l	a0, PS_EXCM_BIT, 1f	# exception mode
778
779	/* Set EPC1 and EXCCAUSE */
780
781	wsr	a2, depc		# save a2 temporarily
782	rsr	a2, SREG_EPC + XCHAL_DEBUGLEVEL
783	wsr	a2, epc1
784
785	movi	a2, EXCCAUSE_MAPPED_DEBUG
786	wsr	a2, exccause
787
788	/* Restore PS to the value before the debug exc but with PS.EXCM set.*/
789
790	movi	a2, 1 << PS_EXCM_BIT
791	or	a2, a0, a2
792	movi	a0, debug_exception	# restore a3, debug jump vector
793	wsr	a2, ps
794	xsr	a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
795
796	/* Switch to kernel/user stack, restore jump vector, and save a0 */
797
798	bbsi.l	a2, PS_UM_BIT, 2f	# jump if user mode
799
800	addi	a2, a1, -16-PT_SIZE	# assume kernel stack
801	s32i	a0, a2, PT_AREG0
802	movi	a0, 0
803	s32i	a1, a2, PT_AREG1
804	s32i	a0, a2, PT_DEPC		# mark it as a regular exception
805	xsr	a0, depc
806	s32i	a3, a2, PT_AREG3
807	s32i	a0, a2, PT_AREG2
808	mov	a1, a2
809	j	_kernel_exception
810
8112:	rsr	a2, excsave1
812	l32i	a2, a2, EXC_TABLE_KSTK	# load kernel stack pointer
813	s32i	a0, a2, PT_AREG0
814	movi	a0, 0
815	s32i	a1, a2, PT_AREG1
816	s32i	a0, a2, PT_DEPC
817	xsr	a0, depc
818	s32i	a3, a2, PT_AREG3
819	s32i	a0, a2, PT_AREG2
820	mov	a1, a2
821	j	_user_exception
822
823	/* Debug exception while in exception mode. */
8241:	j	1b	// FIXME!!
825
826ENDPROC(debug_exception)
827
828/*
829 * We get here in case of an unrecoverable exception.
830 * The only thing we can do is to be nice and print a panic message.
831 * We only produce a single stack frame for panic, so ???
832 *
833 *
834 * Entry conditions:
835 *
836 *   - a0 contains the caller address; original value saved in excsave1.
837 *   - the original a0 contains a valid return address (backtrace) or 0.
838 *   - a2 contains a valid stackpointer
839 *
840 * Notes:
841 *
842 *   - If the stack pointer could be invalid, the caller has to setup a
843 *     dummy stack pointer (e.g. the stack of the init_task)
844 *
845 *   - If the return address could be invalid, the caller has to set it
846 *     to 0, so the backtrace would stop.
847 *
848 */
849	.align 4
850unrecoverable_text:
851	.ascii "Unrecoverable error in exception handler\0"
852
853ENTRY(unrecoverable_exception)
854
855	movi	a0, 1
856	movi	a1, 0
857
858	wsr	a0, windowstart
859	wsr	a1, windowbase
860	rsync
861
862	movi	a1, (1 << PS_WOE_BIT) | LOCKLEVEL
863	wsr	a1, ps
864	rsync
865
866	movi	a1, init_task
867	movi	a0, 0
868	addi	a1, a1, PT_REGS_OFFSET
869
870	movi	a4, panic
871	movi	a6, unrecoverable_text
872
873	callx4	a4
874
8751:	j	1b
876
877ENDPROC(unrecoverable_exception)
878
879/* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */
880
881/*
882 * Fast-handler for alloca exceptions
883 *
884 *  The ALLOCA handler is entered when user code executes the MOVSP
885 *  instruction and the caller's frame is not in the register file.
886 *
887 * This algorithm was taken from the Ross Morley's RTOS Porting Layer:
888 *
889 *    /home/ross/rtos/porting/XtensaRTOS-PortingLayer-20090507/xtensa_vectors.S
890 *
891 * It leverages the existing window spill/fill routines and their support for
892 * double exceptions. The 'movsp' instruction will only cause an exception if
893 * the next window needs to be loaded. In fact this ALLOCA exception may be
894 * replaced at some point by changing the hardware to do a underflow exception
895 * of the proper size instead.
896 *
897 * This algorithm simply backs out the register changes started by the user
898 * excpetion handler, makes it appear that we have started a window underflow
899 * by rotating the window back and then setting the old window base (OWB) in
900 * the 'ps' register with the rolled back window base. The 'movsp' instruction
901 * will be re-executed and this time since the next window frames is in the
902 * active AR registers it won't cause an exception.
903 *
904 * If the WindowUnderflow code gets a TLB miss the page will get mapped
905 * the the partial windeowUnderflow will be handeled in the double exception
906 * handler.
907 *
908 * Entry condition:
909 *
910 *   a0:	trashed, original value saved on stack (PT_AREG0)
911 *   a1:	a1
912 *   a2:	new stack pointer, original in DEPC
913 *   a3:	a3
914 *   depc:	a2, original value saved on stack (PT_DEPC)
915 *   excsave_1:	dispatch table
916 *
917 *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
918 *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
919 */
920
921ENTRY(fast_alloca)
922	rsr	a0, windowbase
923	rotw	-1
924	rsr	a2, ps
925	extui	a3, a2, PS_OWB_SHIFT, PS_OWB_WIDTH
926	xor	a3, a3, a4
927	l32i	a4, a6, PT_AREG0
928	l32i	a1, a6, PT_DEPC
929	rsr	a6, depc
930	wsr	a1, depc
931	slli	a3, a3, PS_OWB_SHIFT
932	xor	a2, a2, a3
933	wsr	a2, ps
934	rsync
935
936	_bbci.l	a4, 31, 4f
937	rotw	-1
938	_bbci.l	a8, 30, 8f
939	rotw	-1
940	j	_WindowUnderflow12
9418:	j	_WindowUnderflow8
9424:	j	_WindowUnderflow4
943ENDPROC(fast_alloca)
944
945/*
946 * fast system calls.
947 *
948 * WARNING:  The kernel doesn't save the entire user context before
949 * handling a fast system call.  These functions are small and short,
950 * usually offering some functionality not available to user tasks.
951 *
952 * BE CAREFUL TO PRESERVE THE USER'S CONTEXT.
953 *
954 * Entry condition:
955 *
956 *   a0:	trashed, original value saved on stack (PT_AREG0)
957 *   a1:	a1
958 *   a2:	new stack pointer, original in DEPC
959 *   a3:	a3
960 *   depc:	a2, original value saved on stack (PT_DEPC)
961 *   excsave_1:	dispatch table
962 */
963
964ENTRY(fast_syscall_kernel)
965
966	/* Skip syscall. */
967
968	rsr	a0, epc1
969	addi	a0, a0, 3
970	wsr	a0, epc1
971
972	l32i	a0, a2, PT_DEPC
973	bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
974
975	rsr	a0, depc			# get syscall-nr
976	_beqz	a0, fast_syscall_spill_registers
977	_beqi	a0, __NR_xtensa, fast_syscall_xtensa
978
979	j	kernel_exception
980
981ENDPROC(fast_syscall_kernel)
982
983ENTRY(fast_syscall_user)
984
985	/* Skip syscall. */
986
987	rsr	a0, epc1
988	addi	a0, a0, 3
989	wsr	a0, epc1
990
991	l32i	a0, a2, PT_DEPC
992	bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
993
994	rsr	a0, depc			# get syscall-nr
995	_beqz	a0, fast_syscall_spill_registers
996	_beqi	a0, __NR_xtensa, fast_syscall_xtensa
997
998	j	user_exception
999
1000ENDPROC(fast_syscall_user)
1001
1002ENTRY(fast_syscall_unrecoverable)
1003
1004	/* Restore all states. */
1005
1006	l32i    a0, a2, PT_AREG0        # restore a0
1007	xsr     a2, depc                # restore a2, depc
1008
1009	wsr     a0, excsave1
1010	movi    a0, unrecoverable_exception
1011	callx0  a0
1012
1013ENDPROC(fast_syscall_unrecoverable)
1014
1015/*
1016 * sysxtensa syscall handler
1017 *
1018 * int sysxtensa (SYS_XTENSA_ATOMIC_SET,     ptr, val,    unused);
1019 * int sysxtensa (SYS_XTENSA_ATOMIC_ADD,     ptr, val,    unused);
1020 * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val,    unused);
1021 * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
1022 *        a2            a6                   a3    a4      a5
1023 *
1024 * Entry condition:
1025 *
1026 *   a0:	a2 (syscall-nr), original value saved on stack (PT_AREG0)
1027 *   a1:	a1
1028 *   a2:	new stack pointer, original in a0 and DEPC
1029 *   a3:	a3
1030 *   a4..a15:	unchanged
1031 *   depc:	a2, original value saved on stack (PT_DEPC)
1032 *   excsave_1:	dispatch table
1033 *
1034 *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1035 *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
1036 *
1037 * Note: we don't have to save a2; a2 holds the return value
1038 *
1039 * We use the two macros TRY and CATCH:
1040 *
1041 * TRY	 adds an entry to the __ex_table fixup table for the immediately
1042 *	 following instruction.
1043 *
1044 * CATCH catches any exception that occurred at one of the preceding TRY
1045 *       statements and continues from there
1046 *
1047 * Usage TRY	l32i	a0, a1, 0
1048 *		<other code>
1049 *	 done:	rfe
1050 *	 CATCH	<set return code>
1051 *		j done
1052 */
1053
1054#ifdef CONFIG_FAST_SYSCALL_XTENSA
1055
1056#define TRY								\
1057	.section __ex_table, "a";					\
1058	.word	66f, 67f;						\
1059	.text;								\
106066:
1061
1062#define CATCH								\
106367:
1064
1065ENTRY(fast_syscall_xtensa)
1066
1067	s32i	a7, a2, PT_AREG7	# we need an additional register
1068	movi	a7, 4			# sizeof(unsigned int)
1069	access_ok a3, a7, a0, a2, .Leac	# a0: scratch reg, a2: sp
1070
1071	_bgeui	a6, SYS_XTENSA_COUNT, .Lill
1072	_bnei	a6, SYS_XTENSA_ATOMIC_CMP_SWP, .Lnswp
1073
1074	/* Fall through for ATOMIC_CMP_SWP. */
1075
1076.Lswp:	/* Atomic compare and swap */
1077
1078TRY	l32i	a0, a3, 0		# read old value
1079	bne	a0, a4, 1f		# same as old value? jump
1080TRY	s32i	a5, a3, 0		# different, modify value
1081	l32i	a7, a2, PT_AREG7	# restore a7
1082	l32i	a0, a2, PT_AREG0	# restore a0
1083	movi	a2, 1			# and return 1
1084	rfe
1085
10861:	l32i	a7, a2, PT_AREG7	# restore a7
1087	l32i	a0, a2, PT_AREG0	# restore a0
1088	movi	a2, 0			# return 0 (note that we cannot set
1089	rfe
1090
1091.Lnswp:	/* Atomic set, add, and exg_add. */
1092
1093TRY	l32i	a7, a3, 0		# orig
1094	addi	a6, a6, -SYS_XTENSA_ATOMIC_SET
1095	add	a0, a4, a7		# + arg
1096	moveqz	a0, a4, a6		# set
1097	addi	a6, a6, SYS_XTENSA_ATOMIC_SET
1098TRY	s32i	a0, a3, 0		# write new value
1099
1100	mov	a0, a2
1101	mov	a2, a7
1102	l32i	a7, a0, PT_AREG7	# restore a7
1103	l32i	a0, a0, PT_AREG0	# restore a0
1104	rfe
1105
1106CATCH
1107.Leac:	l32i	a7, a2, PT_AREG7	# restore a7
1108	l32i	a0, a2, PT_AREG0	# restore a0
1109	movi	a2, -EFAULT
1110	rfe
1111
1112.Lill:	l32i	a7, a2, PT_AREG7	# restore a7
1113	l32i	a0, a2, PT_AREG0	# restore a0
1114	movi	a2, -EINVAL
1115	rfe
1116
1117ENDPROC(fast_syscall_xtensa)
1118
1119#else /* CONFIG_FAST_SYSCALL_XTENSA */
1120
1121ENTRY(fast_syscall_xtensa)
1122
1123	l32i    a0, a2, PT_AREG0        # restore a0
1124	movi	a2, -ENOSYS
1125	rfe
1126
1127ENDPROC(fast_syscall_xtensa)
1128
1129#endif /* CONFIG_FAST_SYSCALL_XTENSA */
1130
1131
1132/* fast_syscall_spill_registers.
1133 *
1134 * Entry condition:
1135 *
1136 *   a0:	trashed, original value saved on stack (PT_AREG0)
1137 *   a1:	a1
1138 *   a2:	new stack pointer, original in DEPC
1139 *   a3:	a3
1140 *   depc:	a2, original value saved on stack (PT_DEPC)
1141 *   excsave_1:	dispatch table
1142 *
1143 * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
1144 */
1145
1146#ifdef CONFIG_FAST_SYSCALL_SPILL_REGISTERS
1147
1148ENTRY(fast_syscall_spill_registers)
1149
1150	/* Register a FIXUP handler (pass current wb as a parameter) */
1151
1152	xsr	a3, excsave1
1153	movi	a0, fast_syscall_spill_registers_fixup
1154	s32i	a0, a3, EXC_TABLE_FIXUP
1155	rsr	a0, windowbase
1156	s32i	a0, a3, EXC_TABLE_PARAM
1157	xsr	a3, excsave1		# restore a3 and excsave_1
1158
1159	/* Save a3, a4 and SAR on stack. */
1160
1161	rsr	a0, sar
1162	s32i	a3, a2, PT_AREG3
1163	s32i	a0, a2, PT_SAR
1164
1165	/* The spill routine might clobber a4, a7, a8, a11, a12, and a15. */
1166
1167	s32i	a4, a2, PT_AREG4
1168	s32i	a7, a2, PT_AREG7
1169	s32i	a8, a2, PT_AREG8
1170	s32i	a11, a2, PT_AREG11
1171	s32i	a12, a2, PT_AREG12
1172	s32i	a15, a2, PT_AREG15
1173
1174	/*
1175	 * Rotate ws so that the current windowbase is at bit 0.
1176	 * Assume ws = xxxwww1yy (www1 current window frame).
1177	 * Rotate ws right so that a4 = yyxxxwww1.
1178	 */
1179
1180	rsr	a0, windowbase
1181	rsr	a3, windowstart		# a3 = xxxwww1yy
1182	ssr	a0			# holds WB
1183	slli	a0, a3, WSBITS
1184	or	a3, a3, a0		# a3 = xxxwww1yyxxxwww1yy
1185	srl	a3, a3			# a3 = 00xxxwww1yyxxxwww1
1186
1187	/* We are done if there are no more than the current register frame. */
1188
1189	extui	a3, a3, 1, WSBITS-1	# a3 = 0yyxxxwww
1190	movi	a0, (1 << (WSBITS-1))
1191	_beqz	a3, .Lnospill		# only one active frame? jump
1192
1193	/* We want 1 at the top, so that we return to the current windowbase */
1194
1195	or	a3, a3, a0		# 1yyxxxwww
1196
1197	/* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
1198
1199	wsr	a3, windowstart		# save shifted windowstart
1200	neg	a0, a3
1201	and	a3, a0, a3		# first bit set from right: 000010000
1202
1203	ffs_ws	a0, a3			# a0: shifts to skip empty frames
1204	movi	a3, WSBITS
1205	sub	a0, a3, a0		# WSBITS-a0:number of 0-bits from right
1206	ssr	a0			# save in SAR for later.
1207
1208	rsr	a3, windowbase
1209	add	a3, a3, a0
1210	wsr	a3, windowbase
1211	rsync
1212
1213	rsr	a3, windowstart
1214	srl	a3, a3			# shift windowstart
1215
1216	/* WB is now just one frame below the oldest frame in the register
1217	   window. WS is shifted so the oldest frame is in bit 0, thus, WB
1218	   and WS differ by one 4-register frame. */
1219
1220	/* Save frames. Depending what call was used (call4, call8, call12),
1221	 * we have to save 4,8. or 12 registers.
1222	 */
1223
1224
1225.Lloop: _bbsi.l	a3, 1, .Lc4
1226	_bbci.l	a3, 2, .Lc12
1227
1228.Lc8:	s32e	a4, a13, -16
1229	l32e	a4, a5, -12
1230	s32e	a8, a4, -32
1231	s32e	a5, a13, -12
1232	s32e	a6, a13, -8
1233	s32e	a7, a13, -4
1234	s32e	a9, a4, -28
1235	s32e	a10, a4, -24
1236	s32e	a11, a4, -20
1237	srli	a11, a3, 2		# shift windowbase by 2
1238	rotw	2
1239	_bnei	a3, 1, .Lloop
1240	j	.Lexit
1241
1242.Lc4:	s32e	a4, a9, -16
1243	s32e	a5, a9, -12
1244	s32e	a6, a9, -8
1245	s32e	a7, a9, -4
1246
1247	srli	a7, a3, 1
1248	rotw	1
1249	_bnei	a3, 1, .Lloop
1250	j	.Lexit
1251
1252.Lc12:	_bbci.l	a3, 3, .Linvalid_mask	# bit 2 shouldn't be zero!
1253
1254	/* 12-register frame (call12) */
1255
1256	l32e	a0, a5, -12
1257	s32e	a8, a0, -48
1258	mov	a8, a0
1259
1260	s32e	a9, a8, -44
1261	s32e	a10, a8, -40
1262	s32e	a11, a8, -36
1263	s32e	a12, a8, -32
1264	s32e	a13, a8, -28
1265	s32e	a14, a8, -24
1266	s32e	a15, a8, -20
1267	srli	a15, a3, 3
1268
1269	/* The stack pointer for a4..a7 is out of reach, so we rotate the
1270	 * window, grab the stackpointer, and rotate back.
1271	 * Alternatively, we could also use the following approach, but that
1272	 * makes the fixup routine much more complicated:
1273	 * rotw	1
1274	 * s32e	a0, a13, -16
1275	 * ...
1276	 * rotw 2
1277	 */
1278
1279	rotw	1
1280	mov	a4, a13
1281	rotw	-1
1282
1283	s32e	a4, a8, -16
1284	s32e	a5, a8, -12
1285	s32e	a6, a8, -8
1286	s32e	a7, a8, -4
1287
1288	rotw	3
1289
1290	_beqi	a3, 1, .Lexit
1291	j	.Lloop
1292
1293.Lexit:
1294
1295	/* Done. Do the final rotation and set WS */
1296
1297	rotw	1
1298	rsr	a3, windowbase
1299	ssl	a3
1300	movi	a3, 1
1301	sll	a3, a3
1302	wsr	a3, windowstart
1303.Lnospill:
1304
1305	/* Advance PC, restore registers and SAR, and return from exception. */
1306
1307	l32i	a3, a2, PT_SAR
1308	l32i	a0, a2, PT_AREG0
1309	wsr	a3, sar
1310	l32i	a3, a2, PT_AREG3
1311
1312	/* Restore clobbered registers. */
1313
1314	l32i	a4, a2, PT_AREG4
1315	l32i	a7, a2, PT_AREG7
1316	l32i	a8, a2, PT_AREG8
1317	l32i	a11, a2, PT_AREG11
1318	l32i	a12, a2, PT_AREG12
1319	l32i	a15, a2, PT_AREG15
1320
1321	movi	a2, 0
1322	rfe
1323
1324.Linvalid_mask:
1325
1326	/* We get here because of an unrecoverable error in the window
1327	 * registers, so set up a dummy frame and kill the user application.
1328	 * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
1329	 */
1330
1331	movi	a0, 1
1332	movi	a1, 0
1333
1334	wsr	a0, windowstart
1335	wsr	a1, windowbase
1336	rsync
1337
1338	movi	a0, 0
1339
1340	rsr	a3, excsave1
1341	l32i	a1, a3, EXC_TABLE_KSTK
1342
1343	movi	a4, (1 << PS_WOE_BIT) | LOCKLEVEL
1344	wsr	a4, ps
1345	rsync
1346
1347	movi	a6, SIGSEGV
1348	movi	a4, do_exit
1349	callx4	a4
1350
1351	/* shouldn't return, so panic */
1352
1353	wsr	a0, excsave1
1354	movi	a0, unrecoverable_exception
1355	callx0	a0		# should not return
13561:	j	1b
1357
1358
1359ENDPROC(fast_syscall_spill_registers)
1360
1361/* Fixup handler.
1362 *
1363 * We get here if the spill routine causes an exception, e.g. tlb miss.
1364 * We basically restore WINDOWBASE and WINDOWSTART to the condition when
1365 * we entered the spill routine and jump to the user exception handler.
1366 *
1367 * Note that we only need to restore the bits in windowstart that have not
1368 * been spilled yet by the _spill_register routine. Luckily, a3 contains a
1369 * rotated windowstart with only those bits set for frames that haven't been
1370 * spilled yet. Because a3 is rotated such that bit 0 represents the register
1371 * frame for the current windowbase - 1, we need to rotate a3 left by the
1372 * value of the current windowbase + 1 and move it to windowstart.
1373 *
1374 * a0: value of depc, original value in depc
1375 * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
1376 * a3: exctable, original value in excsave1
1377 */
1378
1379ENTRY(fast_syscall_spill_registers_fixup)
1380
1381	rsr	a2, windowbase	# get current windowbase (a2 is saved)
1382	xsr	a0, depc	# restore depc and a0
1383	ssl	a2		# set shift (32 - WB)
1384
1385	/* We need to make sure the current registers (a0-a3) are preserved.
1386	 * To do this, we simply set the bit for the current window frame
1387	 * in WS, so that the exception handlers save them to the task stack.
1388	 *
1389	 * Note: we use a3 to set the windowbase, so we take a special care
1390	 * of it, saving it in the original _spill_registers frame across
1391	 * the exception handler call.
1392	 */
1393
1394	xsr	a3, excsave1	# get spill-mask
1395	slli	a3, a3, 1	# shift left by one
1396	addi	a3, a3, 1	# set the bit for the current window frame
1397
1398	slli	a2, a3, 32-WSBITS
1399	src	a2, a3, a2	# a2 = xxwww1yyxxxwww1yy......
1400	wsr	a2, windowstart	# set corrected windowstart
1401
1402	srli	a3, a3, 1
1403	rsr	a2, excsave1
1404	l32i	a2, a2, EXC_TABLE_DOUBLE_SAVE	# restore a2
1405	xsr	a2, excsave1
1406	s32i	a3, a2, EXC_TABLE_DOUBLE_SAVE	# save a3
1407	l32i	a3, a2, EXC_TABLE_PARAM	# original WB (in user task)
1408	xsr	a2, excsave1
1409
1410	/* Return to the original (user task) WINDOWBASE.
1411	 * We leave the following frame behind:
1412	 * a0, a1, a2	same
1413	 * a3:		trashed (saved in EXC_TABLE_DOUBLE_SAVE)
1414	 * depc:	depc (we have to return to that address)
1415	 * excsave_1:	exctable
1416	 */
1417
1418	wsr	a3, windowbase
1419	rsync
1420
1421	/* We are now in the original frame when we entered _spill_registers:
1422	 *  a0: return address
1423	 *  a1: used, stack pointer
1424	 *  a2: kernel stack pointer
1425	 *  a3: available
1426	 *  depc: exception address
1427	 *  excsave: exctable
1428	 * Note: This frame might be the same as above.
1429	 */
1430
1431	/* Setup stack pointer. */
1432
1433	addi	a2, a2, -PT_USER_SIZE
1434	s32i	a0, a2, PT_AREG0
1435
1436	/* Make sure we return to this fixup handler. */
1437
1438	movi	a3, fast_syscall_spill_registers_fixup_return
1439	s32i	a3, a2, PT_DEPC		# setup depc
1440
1441	/* Jump to the exception handler. */
1442
1443	rsr	a3, excsave1
1444	rsr	a0, exccause
1445	addx4	a0, a0, a3              	# find entry in table
1446	l32i	a0, a0, EXC_TABLE_FAST_USER     # load handler
1447	l32i	a3, a3, EXC_TABLE_DOUBLE_SAVE
1448	jx	a0
1449
1450ENDPROC(fast_syscall_spill_registers_fixup)
1451
1452ENTRY(fast_syscall_spill_registers_fixup_return)
1453
1454	/* When we return here, all registers have been restored (a2: DEPC) */
1455
1456	wsr	a2, depc		# exception address
1457
1458	/* Restore fixup handler. */
1459
1460	rsr	a2, excsave1
1461	s32i	a3, a2, EXC_TABLE_DOUBLE_SAVE
1462	movi	a3, fast_syscall_spill_registers_fixup
1463	s32i	a3, a2, EXC_TABLE_FIXUP
1464	rsr	a3, windowbase
1465	s32i	a3, a2, EXC_TABLE_PARAM
1466	l32i	a2, a2, EXC_TABLE_KSTK
1467
1468	/* Load WB at the time the exception occurred. */
1469
1470	rsr	a3, sar			# WB is still in SAR
1471	neg	a3, a3
1472	wsr	a3, windowbase
1473	rsync
1474
1475	rsr	a3, excsave1
1476	l32i	a3, a3, EXC_TABLE_DOUBLE_SAVE
1477
1478	rfde
1479
1480ENDPROC(fast_syscall_spill_registers_fixup_return)
1481
1482#else /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */
1483
1484ENTRY(fast_syscall_spill_registers)
1485
1486	l32i    a0, a2, PT_AREG0        # restore a0
1487	movi	a2, -ENOSYS
1488	rfe
1489
1490ENDPROC(fast_syscall_spill_registers)
1491
1492#endif /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */
1493
1494#ifdef CONFIG_MMU
1495/*
1496 * We should never get here. Bail out!
1497 */
1498
1499ENTRY(fast_second_level_miss_double_kernel)
1500
15011:	movi	a0, unrecoverable_exception
1502	callx0	a0		# should not return
15031:	j	1b
1504
1505ENDPROC(fast_second_level_miss_double_kernel)
1506
1507/* First-level entry handler for user, kernel, and double 2nd-level
1508 * TLB miss exceptions.  Note that for now, user and kernel miss
1509 * exceptions share the same entry point and are handled identically.
1510 *
1511 * An old, less-efficient C version of this function used to exist.
1512 * We include it below, interleaved as comments, for reference.
1513 *
1514 * Entry condition:
1515 *
1516 *   a0:	trashed, original value saved on stack (PT_AREG0)
1517 *   a1:	a1
1518 *   a2:	new stack pointer, original in DEPC
1519 *   a3:	a3
1520 *   depc:	a2, original value saved on stack (PT_DEPC)
1521 *   excsave_1:	dispatch table
1522 *
1523 *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1524 *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
1525 */
1526
1527ENTRY(fast_second_level_miss)
1528
1529	/* Save a1 and a3. Note: we don't expect a double exception. */
1530
1531	s32i	a1, a2, PT_AREG1
1532	s32i	a3, a2, PT_AREG3
1533
1534	/* We need to map the page of PTEs for the user task.  Find
1535	 * the pointer to that page.  Also, it's possible for tsk->mm
1536	 * to be NULL while tsk->active_mm is nonzero if we faulted on
1537	 * a vmalloc address.  In that rare case, we must use
1538	 * active_mm instead to avoid a fault in this handler.  See
1539	 *
1540	 * http://mail.nl.linux.org/linux-mm/2002-08/msg00258.html
1541	 *   (or search Internet on "mm vs. active_mm")
1542	 *
1543	 *	if (!mm)
1544	 *		mm = tsk->active_mm;
1545	 *	pgd = pgd_offset (mm, regs->excvaddr);
1546	 *	pmd = pmd_offset (pgd, regs->excvaddr);
1547	 *	pmdval = *pmd;
1548	 */
1549
1550	GET_CURRENT(a1,a2)
1551	l32i	a0, a1, TASK_MM		# tsk->mm
1552	beqz	a0, 9f
1553
15548:	rsr	a3, excvaddr		# fault address
1555	_PGD_OFFSET(a0, a3, a1)
1556	l32i	a0, a0, 0		# read pmdval
1557	beqz	a0, 2f
1558
1559	/* Read ptevaddr and convert to top of page-table page.
1560	 *
1561	 * 	vpnval = read_ptevaddr_register() & PAGE_MASK;
1562	 * 	vpnval += DTLB_WAY_PGTABLE;
1563	 *	pteval = mk_pte (virt_to_page(pmd_val(pmdval)), PAGE_KERNEL);
1564	 *	write_dtlb_entry (pteval, vpnval);
1565	 *
1566	 * The messy computation for 'pteval' above really simplifies
1567	 * into the following:
1568	 *
1569	 * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_DIRECTORY
1570	 */
1571
1572	movi	a1, (-PAGE_OFFSET) & 0xffffffff
1573	add	a0, a0, a1		# pmdval - PAGE_OFFSET
1574	extui	a1, a0, 0, PAGE_SHIFT	# ... & PAGE_MASK
1575	xor	a0, a0, a1
1576
1577	movi	a1, _PAGE_DIRECTORY
1578	or	a0, a0, a1		# ... | PAGE_DIRECTORY
1579
1580	/*
1581	 * We utilize all three wired-ways (7-9) to hold pmd translations.
1582	 * Memory regions are mapped to the DTLBs according to bits 28 and 29.
1583	 * This allows to map the three most common regions to three different
1584	 * DTLBs:
1585	 *  0,1 -> way 7	program (0040.0000) and virtual (c000.0000)
1586	 *  2   -> way 8	shared libaries (2000.0000)
1587	 *  3   -> way 0	stack (3000.0000)
1588	 */
1589
1590	extui	a3, a3, 28, 2		# addr. bit 28 and 29	0,1,2,3
1591	rsr	a1, ptevaddr
1592	addx2	a3, a3, a3		# ->			0,3,6,9
1593	srli	a1, a1, PAGE_SHIFT
1594	extui	a3, a3, 2, 2		# ->			0,0,1,2
1595	slli	a1, a1, PAGE_SHIFT	# ptevaddr & PAGE_MASK
1596	addi	a3, a3, DTLB_WAY_PGD
1597	add	a1, a1, a3		# ... + way_number
1598
15993:	wdtlb	a0, a1
1600	dsync
1601
1602	/* Exit critical section. */
1603
16044:	rsr	a3, excsave1
1605	movi	a0, 0
1606	s32i	a0, a3, EXC_TABLE_FIXUP
1607
1608	/* Restore the working registers, and return. */
1609
1610	l32i	a0, a2, PT_AREG0
1611	l32i	a1, a2, PT_AREG1
1612	l32i	a3, a2, PT_AREG3
1613	l32i	a2, a2, PT_DEPC
1614
1615	bgeui	a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
1616
1617	/* Restore excsave1 and return. */
1618
1619	rsr	a2, depc
1620	rfe
1621
1622	/* Return from double exception. */
1623
16241:	xsr	a2, depc
1625	esync
1626	rfde
1627
16289:	l32i	a0, a1, TASK_ACTIVE_MM	# unlikely case mm == 0
1629	bnez	a0, 8b
1630
1631	/* Even more unlikely case active_mm == 0.
1632	 * We can get here with NMI in the middle of context_switch that
1633	 * touches vmalloc area.
1634	 */
1635	movi	a0, init_mm
1636	j	8b
1637
1638#if (DCACHE_WAY_SIZE > PAGE_SIZE)
1639
16402:	/* Special case for cache aliasing.
1641	 * We (should) only get here if a clear_user_page, copy_user_page
1642	 * or the aliased cache flush functions got preemptively interrupted
1643	 * by another task. Re-establish temporary mapping to the
1644	 * TLBTEMP_BASE areas.
1645	 */
1646
1647	/* We shouldn't be in a double exception */
1648
1649	l32i	a0, a2, PT_DEPC
1650	bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 2f
1651
1652	/* Make sure the exception originated in the special functions */
1653
1654	movi	a0, __tlbtemp_mapping_start
1655	rsr	a3, epc1
1656	bltu	a3, a0, 2f
1657	movi	a0, __tlbtemp_mapping_end
1658	bgeu	a3, a0, 2f
1659
1660	/* Check if excvaddr was in one of the TLBTEMP_BASE areas. */
1661
1662	movi	a3, TLBTEMP_BASE_1
1663	rsr	a0, excvaddr
1664	bltu	a0, a3, 2f
1665
1666	addi	a1, a0, -TLBTEMP_SIZE
1667	bgeu	a1, a3, 2f
1668
1669	/* Check if we have to restore an ITLB mapping. */
1670
1671	movi	a1, __tlbtemp_mapping_itlb
1672	rsr	a3, epc1
1673	sub	a3, a3, a1
1674
1675	/* Calculate VPN */
1676
1677	movi	a1, PAGE_MASK
1678	and	a1, a1, a0
1679
1680	/* Jump for ITLB entry */
1681
1682	bgez	a3, 1f
1683
1684	/* We can use up to two TLBTEMP areas, one for src and one for dst. */
1685
1686	extui	a3, a0, PAGE_SHIFT + DCACHE_ALIAS_ORDER, 1
1687	add	a1, a3, a1
1688
1689	/* PPN is in a6 for the first TLBTEMP area and in a7 for the second. */
1690
1691	mov	a0, a6
1692	movnez	a0, a7, a3
1693	j	3b
1694
1695	/* ITLB entry. We only use dst in a6. */
1696
16971:	witlb	a6, a1
1698	isync
1699	j	4b
1700
1701
1702#endif	// DCACHE_WAY_SIZE > PAGE_SIZE
1703
1704
17052:	/* Invalid PGD, default exception handling */
1706
1707	rsr	a1, depc
1708	s32i	a1, a2, PT_AREG2
1709	mov	a1, a2
1710
1711	rsr	a2, ps
1712	bbsi.l	a2, PS_UM_BIT, 1f
1713	j	_kernel_exception
17141:	j	_user_exception
1715
1716ENDPROC(fast_second_level_miss)
1717
1718/*
1719 * StoreProhibitedException
1720 *
1721 * Update the pte and invalidate the itlb mapping for this pte.
1722 *
1723 * Entry condition:
1724 *
1725 *   a0:	trashed, original value saved on stack (PT_AREG0)
1726 *   a1:	a1
1727 *   a2:	new stack pointer, original in DEPC
1728 *   a3:	a3
1729 *   depc:	a2, original value saved on stack (PT_DEPC)
1730 *   excsave_1:	dispatch table
1731 *
1732 *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1733 *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
1734 */
1735
1736ENTRY(fast_store_prohibited)
1737
1738	/* Save a1 and a3. */
1739
1740	s32i	a1, a2, PT_AREG1
1741	s32i	a3, a2, PT_AREG3
1742
1743	GET_CURRENT(a1,a2)
1744	l32i	a0, a1, TASK_MM		# tsk->mm
1745	beqz	a0, 9f
1746
17478:	rsr	a1, excvaddr		# fault address
1748	_PGD_OFFSET(a0, a1, a3)
1749	l32i	a0, a0, 0
1750	beqz	a0, 2f
1751
1752	/*
1753	 * Note that we test _PAGE_WRITABLE_BIT only if PTE is present
1754	 * and is not PAGE_NONE. See pgtable.h for possible PTE layouts.
1755	 */
1756
1757	_PTE_OFFSET(a0, a1, a3)
1758	l32i	a3, a0, 0		# read pteval
1759	movi	a1, _PAGE_CA_INVALID
1760	ball	a3, a1, 2f
1761	bbci.l	a3, _PAGE_WRITABLE_BIT, 2f
1762
1763	movi	a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE
1764	or	a3, a3, a1
1765	rsr	a1, excvaddr
1766	s32i	a3, a0, 0
1767
1768	/* We need to flush the cache if we have page coloring. */
1769#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
1770	dhwb	a0, 0
1771#endif
1772	pdtlb	a0, a1
1773	wdtlb	a3, a0
1774
1775	/* Exit critical section. */
1776
1777	movi	a0, 0
1778	rsr	a3, excsave1
1779	s32i	a0, a3, EXC_TABLE_FIXUP
1780
1781	/* Restore the working registers, and return. */
1782
1783	l32i	a3, a2, PT_AREG3
1784	l32i	a1, a2, PT_AREG1
1785	l32i	a0, a2, PT_AREG0
1786	l32i	a2, a2, PT_DEPC
1787
1788	bgeui	a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
1789
1790	rsr	a2, depc
1791	rfe
1792
1793	/* Double exception. Restore FIXUP handler and return. */
1794
17951:	xsr	a2, depc
1796	esync
1797	rfde
1798
17999:	l32i	a0, a1, TASK_ACTIVE_MM	# unlikely case mm == 0
1800	j	8b
1801
18022:	/* If there was a problem, handle fault in C */
1803
1804	rsr	a3, depc	# still holds a2
1805	s32i	a3, a2, PT_AREG2
1806	mov	a1, a2
1807
1808	rsr	a2, ps
1809	bbsi.l	a2, PS_UM_BIT, 1f
1810	j	_kernel_exception
18111:	j	_user_exception
1812
1813ENDPROC(fast_store_prohibited)
1814
1815#endif /* CONFIG_MMU */
1816
1817/*
1818 * System Calls.
1819 *
1820 * void system_call (struct pt_regs* regs, int exccause)
1821 *                            a2                 a3
1822 */
1823
1824ENTRY(system_call)
1825
1826	entry	a1, 32
1827
1828	/* regs->syscall = regs->areg[2] */
1829
1830	l32i	a3, a2, PT_AREG2
1831	mov	a6, a2
1832	movi	a4, do_syscall_trace_enter
1833	s32i	a3, a2, PT_SYSCALL
1834	callx4	a4
1835
1836	/* syscall = sys_call_table[syscall_nr] */
1837
1838	movi	a4, sys_call_table;
1839	movi	a5, __NR_syscall_count
1840	movi	a6, -ENOSYS
1841	bgeu	a3, a5, 1f
1842
1843	addx4	a4, a3, a4
1844	l32i	a4, a4, 0
1845	movi	a5, sys_ni_syscall;
1846	beq	a4, a5, 1f
1847
1848	/* Load args: arg0 - arg5 are passed via regs. */
1849
1850	l32i	a6, a2, PT_AREG6
1851	l32i	a7, a2, PT_AREG3
1852	l32i	a8, a2, PT_AREG4
1853	l32i	a9, a2, PT_AREG5
1854	l32i	a10, a2, PT_AREG8
1855	l32i	a11, a2, PT_AREG9
1856
1857	/* Pass one additional argument to the syscall: pt_regs (on stack) */
1858	s32i	a2, a1, 0
1859
1860	callx4	a4
1861
18621:	/* regs->areg[2] = return_value */
1863
1864	s32i	a6, a2, PT_AREG2
1865	movi	a4, do_syscall_trace_leave
1866	mov	a6, a2
1867	callx4	a4
1868	retw
1869
1870ENDPROC(system_call)
1871
1872/*
1873 * Spill live registers on the kernel stack macro.
1874 *
1875 * Entry condition: ps.woe is set, ps.excm is cleared
1876 * Exit condition: windowstart has single bit set
1877 * May clobber: a12, a13
1878 */
1879	.macro	spill_registers_kernel
1880
1881#if XCHAL_NUM_AREGS > 16
1882	call12	1f
1883	_j	2f
1884	retw
1885	.align	4
18861:
1887	_entry	a1, 48
1888	addi	a12, a0, 3
1889#if XCHAL_NUM_AREGS > 32
1890	.rept	(XCHAL_NUM_AREGS - 32) / 12
1891	_entry	a1, 48
1892	mov	a12, a0
1893	.endr
1894#endif
1895	_entry	a1, 16
1896#if XCHAL_NUM_AREGS % 12 == 0
1897	mov	a8, a8
1898#elif XCHAL_NUM_AREGS % 12 == 4
1899	mov	a12, a12
1900#elif XCHAL_NUM_AREGS % 12 == 8
1901	mov	a4, a4
1902#endif
1903	retw
19042:
1905#else
1906	mov	a12, a12
1907#endif
1908	.endm
1909
1910/*
1911 * Task switch.
1912 *
1913 * struct task*  _switch_to (struct task* prev, struct task* next)
1914 *         a2                              a2                 a3
1915 */
1916
1917ENTRY(_switch_to)
1918
1919	entry	a1, 48
1920
1921	mov	a11, a3			# and 'next' (a3)
1922
1923	l32i	a4, a2, TASK_THREAD_INFO
1924	l32i	a5, a3, TASK_THREAD_INFO
1925
1926	save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
1927
1928#if THREAD_RA > 1020 || THREAD_SP > 1020
1929	addi	a10, a2, TASK_THREAD
1930	s32i	a0, a10, THREAD_RA - TASK_THREAD	# save return address
1931	s32i	a1, a10, THREAD_SP - TASK_THREAD	# save stack pointer
1932#else
1933	s32i	a0, a2, THREAD_RA	# save return address
1934	s32i	a1, a2, THREAD_SP	# save stack pointer
1935#endif
1936
1937	/* Disable ints while we manipulate the stack pointer. */
1938
1939	irq_save a14, a3
1940	rsync
1941
1942	/* Switch CPENABLE */
1943
1944#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
1945	l32i	a3, a5, THREAD_CPENABLE
1946	xsr	a3, cpenable
1947	s32i	a3, a4, THREAD_CPENABLE
1948#endif
1949
1950	/* Flush register file. */
1951
1952	spill_registers_kernel
1953
1954	/* Set kernel stack (and leave critical section)
1955	 * Note: It's save to set it here. The stack will not be overwritten
1956	 *       because the kernel stack will only be loaded again after
1957	 *       we return from kernel space.
1958	 */
1959
1960	rsr	a3, excsave1		# exc_table
1961	addi	a7, a5, PT_REGS_OFFSET
1962	s32i	a7, a3, EXC_TABLE_KSTK
1963
1964	/* restore context of the task 'next' */
1965
1966	l32i	a0, a11, THREAD_RA	# restore return address
1967	l32i	a1, a11, THREAD_SP	# restore stack pointer
1968
1969	load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
1970
1971	wsr	a14, ps
1972	rsync
1973
1974	retw
1975
1976ENDPROC(_switch_to)
1977
1978ENTRY(ret_from_fork)
1979
1980	/* void schedule_tail (struct task_struct *prev)
1981	 * Note: prev is still in a6 (return value from fake call4 frame)
1982	 */
1983	movi	a4, schedule_tail
1984	callx4	a4
1985
1986	movi	a4, do_syscall_trace_leave
1987	mov	a6, a1
1988	callx4	a4
1989
1990	j	common_exception_return
1991
1992ENDPROC(ret_from_fork)
1993
1994/*
1995 * Kernel thread creation helper
1996 * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg
1997 *           left from _switch_to: a6 = prev
1998 */
1999ENTRY(ret_from_kernel_thread)
2000
2001	call4	schedule_tail
2002	mov	a6, a3
2003	callx4	a2
2004	j	common_exception_return
2005
2006ENDPROC(ret_from_kernel_thread)
2007