1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License.  See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1994 - 2000, 2001 by Ralf Baechle
7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8 * Copyright (C) 2001 MIPS Technologies, Inc.
9 */
10#include <linux/config.h>
11#include <linux/init.h>
12#include <linux/sys.h>
13
14#include <asm/addrspace.h>
15#include <asm/asm.h>
16#include <asm/cacheops.h>
17#include <asm/current.h>
18#include <asm/errno.h>
19#include <asm/mipsregs.h>
20#include <asm/page.h>
21#include <asm/pgtable-bits.h>
22#include <asm/stackframe.h>
23#include <asm/processor.h>
24#include <asm/regdef.h>
25#include <asm/fpregdef.h>
26#include <asm/unistd.h>
27#include <asm/isadep.h>
28
29
30		.text
31		.align	5
32		.set	push
33		.set	reorder
34FEXPORT(ret_from_irq)
35FEXPORT(ret_from_exception)
36		lw	t0, PT_STATUS(sp)	# returning to kernel mode?
37		andi	t0, t0, KU_USER
38		beqz	t0, restore_all
39
40FEXPORT(ret_from_sys_call)		# here to prevent code duplication
41ret_from_schedule:
42		mfc0	t0, CP0_STATUS	# need_resched and signals atomic test
43		ori	t0, t0, 1
44		xori	t0, t0, 1
45		mtc0	t0, CP0_STATUS
46		SSNOP; SSNOP; SSNOP
47
48		lw	v0, TASK_NEED_RESCHED($28)
49		lw	v1, TASK_SIGPENDING($28)
50		bnez	v0, reschedule
51		bnez	v1, signal_return
52restore_all:	.set	noat
53		RESTORE_ALL_AND_RET
54		.set	at
55
56/* Put this behind restore_all for the sake of the branch prediction.  */
57signal_return:
58		.type	signal_return, @function
59
60		mfc0	t0, CP0_STATUS
61		ori	t0, t0, 1
62		mtc0	t0, CP0_STATUS
63
64		move	a0, zero
65		move	a1, sp
66		jal	do_signal
67		b	restore_all
68
69reschedule:
70		jal	schedule
71		b	ret_from_schedule
72
73/*
74 * Common spurious interrupt handler.
75 */
76		.text
77		.align  5
78LEAF(spurious_interrupt)
79		/*
80		 * Someone tried to fool us by sending an interrupt but we
81		 * couldn't find a cause for it.
82		 */
83		lui     t1,%hi(irq_err_count)
84		lw      t0,%lo(irq_err_count)(t1)
85		addiu   t0,1
86		sw      t0,%lo(irq_err_count)(t1)
87		j	ret_from_irq
88END(spurious_interrupt)
89
90		__INIT
91
92		.set	reorder
93
94NESTED(except_vec1_generic, 0, sp)
95		PANIC("Exception vector 1 called")
96END(except_vec1_generic)
97
98		/*
99		 * General exception vector.  Used for all CPUs except R4000
100		 * and R4400 SC and MC versions.
101		 */
102NESTED(except_vec3_generic, 0, sp)
103#if R5432_CP0_INTERRUPT_WAR
104		mfc0	k0, CP0_INDEX
105#endif
106		mfc0	k1, CP0_CAUSE
107		la	k0, exception_handlers
108		andi	k1, k1, 0x7c
109		addu	k0, k0, k1
110		lw	k0, (k0)
111		jr	k0
112END(except_vec3_generic)
113		.set	at
114
115		/* General exception vector R4000 version. */
116NESTED(except_vec3_r4000, 0, sp)
117		.set	push
118		.set    mips3
119		.set	noat
120		mfc0	k1, CP0_CAUSE
121		li	k0, 31<<2
122		andi	k1, k1, 0x7c
123		.set	noreorder
124		beq	k1, k0, handle_vced
125		 li	k0, 14<<2
126		beq	k1, k0, handle_vcei
127		 la	k0, exception_handlers
128		.set	reorder
129		addu	k0, k0, k1
130		lw	k0, (k0)
131		jr	k0
132
133		/*
134		 * Big shit, we now may have two dirty primary cache lines for
135		 * the same physical address.  We can savely invalidate the
136		 * line pointed to by c0_badvaddr because after return from
137		 * this exception handler the load / store will be re-executed.
138		 */
139handle_vced:
140		mfc0	k0, CP0_BADVADDR
141		li	k1, -4
142		and	k0, k1
143		mtc0	zero, CP0_TAGLO
144		cache	Index_Store_Tag_D,(k0)
145		cache	Hit_Writeback_Inv_SD,(k0)
146#ifdef CONFIG_PROC_FS
147		lui	k0, %hi(vced_count)
148		lw	k1, %lo(vced_count)(k0)
149		addiu	k1, 1
150		sw	k1, %lo(vced_count)(k0)
151#endif
152		eret
153
154handle_vcei:
155		mfc0	k0, CP0_BADVADDR
156		cache	Hit_Writeback_Inv_SD, (k0)	# also cleans pi
157#ifdef CONFIG_PROC_FS
158		lui	k0, %hi(vcei_count)
159		lw	k1, %lo(vcei_count)(k0)
160		addiu	k1, 1
161		sw	k1, %lo(vcei_count)(k0)
162#endif
163		eret
164		.set    pop
165END(except_vec3_r4000)
166
167		__FINIT
168
169/*
170 * Build a default exception handler for the exceptions that don't need
171 * special handlers.  If you didn't know yet - I *like* playing games with
172 * the C preprocessor ...
173 */
174#define __BUILD_clear_none(exception)
175#define __BUILD_clear_sti(exception)                                    \
176		STI
177#define __BUILD_clear_cli(exception)                                    \
178		CLI
179#define __BUILD_clear_fpe(exception)                                    \
180		cfc1	a1,fcr31;                                       \
181		li	a2,~(0x3f<<12);                                 \
182		and	a2,a1;                                          \
183		ctc1	a2,fcr31;                                       \
184		STI
185#define __BUILD_clear_ade(exception)                                    \
186		.set	reorder;					\
187		MFC0	t0,CP0_BADVADDR;                                \
188		.set	noreorder;					\
189		REG_S	t0,PT_BVADDR(sp);                               \
190		KMODE
191#define __BUILD_silent(exception)
192
193#define fmt "Got %s at %08lx.\n"
194
195#define __BUILD_verbose(exception)                                      \
196		la	a1,8f;                                          \
197		TEXT	(#exception);                                   \
198		REG_L	a2,PT_EPC(sp);                                  \
199		PRINT(fmt)
200#define __BUILD_count(exception)                                        \
201		.set	reorder;                                        \
202		lw	t0,exception_count_##exception;                 \
203		.set	noreorder;                                      \
204		addiu	t0, 1;                                          \
205		sw	t0,exception_count_##exception;                 \
206		.data;                                                  \
207EXPORT(exception_count_##exception);                                    \
208		.word	0;                                              \
209		.previous;
210#define BUILD_HANDLER(exception,handler,clear,verbose)                  \
211		.align	5;                                              \
212NESTED(handle_##exception, PT_SIZE, sp);		                \
213		.set	noat;                                           \
214		SAVE_ALL;                                               \
215FEXPORT(handle_##exception##_int);					\
216		__BUILD_clear_##clear(exception);                       \
217		.set	at;                                             \
218		__BUILD_##verbose(exception);                           \
219		jal	do_##handler;                                   \
220		 move	a0, sp;                                         \
221		j	ret_from_exception;                             \
222		 nop;                                                   \
223END(handle_##exception)
224
225		BUILD_HANDLER(adel,ade,ade,silent)		/* #4  */
226		BUILD_HANDLER(ades,ade,ade,silent)		/* #5  */
227		BUILD_HANDLER(ibe,be,cli,silent)		/* #6  */
228		BUILD_HANDLER(dbe,be,cli,silent)		/* #7  */
229		BUILD_HANDLER(bp,bp,sti,silent)			/* #9  */
230		BUILD_HANDLER(ri,ri,sti,silent)			/* #10 */
231		BUILD_HANDLER(cpu,cpu,sti,silent)		/* #11 */
232		BUILD_HANDLER(ov,ov,sti,silent)			/* #12 */
233		BUILD_HANDLER(tr,tr,sti,silent)			/* #13 */
234		BUILD_HANDLER(fpe,fpe,fpe,silent)		/* #15 */
235		BUILD_HANDLER(mdmx,mdmx,sti,silent)		/* #22 */
236		BUILD_HANDLER(watch,watch,sti,silent)		/* #23 */
237		BUILD_HANDLER(mcheck,mcheck,cli,silent)		/* #24 */
238		BUILD_HANDLER(reserved,reserved,sti,silent)	/* others */
239
240		.set	pop
241
242/*
243 * Table of syscalls
244 */
245		.data
246		.align	PTRLOG
247EXPORT(sys_call_table)
248#define SYS(call, narg) PTR call
249
250		/* Reserved space for all SVR4 syscalls. */
251		.space	(1000)*PTRSIZE
252
253#ifdef CONFIG_BINFMT_IRIX
254		/* 32bit IRIX5 system calls. */
255#include "irix5sys.h"
256#else
257		.space	(1000)*PTRSIZE		/* No IRIX syscalls */
258#endif
259
260		/* Reserved space for all the BSD43 and POSIX syscalls. */
261		.space	(2000)*PTRSIZE
262
263		/* Linux flavoured syscalls. */
264#include "syscalls.h"
265
266/*
267 * Number of arguments of each syscall
268 */
269EXPORT(sys_narg_table)
270#undef SYS
271#define SYS(call, narg) .byte narg
272
273		/* Reserved space for all SVR4 flavoured syscalls. */
274		.space	(1000)
275
276#ifdef CONFIG_BINFMT_IRIX
277		/* 32bit IRIX5 system calls. */
278#include "irix5sys.h"
279#else
280		.space	(1000)			/* No IRIX syscalls */
281#endif
282
283		/* Reserved space for all the BSD43 and POSIX syscalls. */
284		.space	(2000)
285
286		/* Linux flavoured syscalls. */
287#include "syscalls.h"
288