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#if defined(CONFIG_BCM4710) || defined(CONFIG_BCM4704)
107		nop
108		nop
109#endif
110		mfc0	k1, CP0_CAUSE
111		la	k0, exception_handlers
112		andi	k1, k1, 0x7c
113		addu	k0, k0, k1
114		lw	k0, (k0)
115		jr	k0
116END(except_vec3_generic)
117		.set	at
118
119		/* General exception vector R4000 version. */
120NESTED(except_vec3_r4000, 0, sp)
121		.set	push
122		.set    mips3
123		.set	noat
124		mfc0	k1, CP0_CAUSE
125		li	k0, 31<<2
126		andi	k1, k1, 0x7c
127		.set	noreorder
128		beq	k1, k0, handle_vced
129		 li	k0, 14<<2
130		beq	k1, k0, handle_vcei
131		 la	k0, exception_handlers
132		.set	reorder
133		addu	k0, k0, k1
134		lw	k0, (k0)
135		jr	k0
136
137		/*
138		 * Big shit, we now may have two dirty primary cache lines for
139		 * the same physical address.  We can savely invalidate the
140		 * line pointed to by c0_badvaddr because after return from
141		 * this exception handler the load / store will be re-executed.
142		 */
143handle_vced:
144		mfc0	k0, CP0_BADVADDR
145		li	k1, -4
146		and	k0, k1
147		mtc0	zero, CP0_TAGLO
148		cache	Index_Store_Tag_D,(k0)
149		cache	Hit_Writeback_Inv_SD,(k0)
150#ifdef CONFIG_PROC_FS
151		lui	k0, %hi(vced_count)
152		lw	k1, %lo(vced_count)(k0)
153		addiu	k1, 1
154		sw	k1, %lo(vced_count)(k0)
155#endif
156		eret
157
158handle_vcei:
159		mfc0	k0, CP0_BADVADDR
160		cache	Hit_Writeback_Inv_SD, (k0)	# also cleans pi
161#ifdef CONFIG_PROC_FS
162		lui	k0, %hi(vcei_count)
163		lw	k1, %lo(vcei_count)(k0)
164		addiu	k1, 1
165		sw	k1, %lo(vcei_count)(k0)
166#endif
167		eret
168		.set    pop
169END(except_vec3_r4000)
170
171		__FINIT
172
173/*
174 * Build a default exception handler for the exceptions that don't need
175 * special handlers.  If you didn't know yet - I *like* playing games with
176 * the C preprocessor ...
177 */
178#define __BUILD_clear_none(exception)
179#define __BUILD_clear_sti(exception)                                    \
180		STI
181#define __BUILD_clear_cli(exception)                                    \
182		CLI
183#define __BUILD_clear_fpe(exception)                                    \
184		cfc1	a1,fcr31;                                       \
185		li	a2,~(0x3f<<12);                                 \
186		and	a2,a1;                                          \
187		ctc1	a2,fcr31;                                       \
188		STI
189#define __BUILD_clear_ade(exception)                                    \
190		.set	reorder;					\
191		MFC0	t0,CP0_BADVADDR;                                \
192		.set	noreorder;					\
193		REG_S	t0,PT_BVADDR(sp);                               \
194		KMODE
195#define __BUILD_silent(exception)
196
197#define fmt "Got %s at %08lx.\n"
198
199#define __BUILD_verbose(exception)                                      \
200		la	a1,8f;                                          \
201		TEXT	(#exception);                                   \
202		REG_L	a2,PT_EPC(sp);                                  \
203		PRINT(fmt)
204#define __BUILD_count(exception)                                        \
205		.set	reorder;                                        \
206		lw	t0,exception_count_##exception;                 \
207		.set	noreorder;                                      \
208		addiu	t0, 1;                                          \
209		sw	t0,exception_count_##exception;                 \
210		.data;                                                  \
211EXPORT(exception_count_##exception);                                    \
212		.word	0;                                              \
213		.previous;
214#define BUILD_HANDLER(exception,handler,clear,verbose)                  \
215		.align	5;                                              \
216NESTED(handle_##exception, PT_SIZE, sp);		                \
217		.set	noat;                                           \
218		SAVE_ALL;                                               \
219FEXPORT(handle_##exception##_int);					\
220		__BUILD_clear_##clear(exception);                       \
221		.set	at;                                             \
222		__BUILD_##verbose(exception);                           \
223		jal	do_##handler;                                   \
224		 move	a0, sp;                                         \
225		j	ret_from_exception;                             \
226		 nop;                                                   \
227END(handle_##exception)
228
229		BUILD_HANDLER(adel,ade,ade,silent)		/* #4  */
230		BUILD_HANDLER(ades,ade,ade,silent)		/* #5  */
231		BUILD_HANDLER(ibe,be,cli,silent)		/* #6  */
232		BUILD_HANDLER(dbe,be,cli,silent)		/* #7  */
233		BUILD_HANDLER(bp,bp,sti,silent)			/* #9  */
234		BUILD_HANDLER(ri,ri,sti,silent)			/* #10 */
235		BUILD_HANDLER(cpu,cpu,sti,silent)		/* #11 */
236		BUILD_HANDLER(ov,ov,sti,silent)			/* #12 */
237		BUILD_HANDLER(tr,tr,sti,silent)			/* #13 */
238		BUILD_HANDLER(fpe,fpe,fpe,silent)		/* #15 */
239		BUILD_HANDLER(mdmx,mdmx,sti,silent)		/* #22 */
240		BUILD_HANDLER(watch,watch,sti,silent)		/* #23 */
241		BUILD_HANDLER(mcheck,mcheck,cli,silent)		/* #24 */
242		BUILD_HANDLER(reserved,reserved,sti,silent)	/* others */
243
244		.set	pop
245
246/*
247 * Table of syscalls
248 */
249		.data
250		.align	PTRLOG
251EXPORT(sys_call_table)
252#define SYS(call, narg) PTR call
253
254		/* Reserved space for all SVR4 syscalls. */
255		.space	(1000)*PTRSIZE
256
257#ifdef CONFIG_BINFMT_IRIX
258		/* 32bit IRIX5 system calls. */
259#include "irix5sys.h"
260#else
261		.space	(1000)*PTRSIZE		/* No IRIX syscalls */
262#endif
263
264		/* Reserved space for all the BSD43 and POSIX syscalls. */
265		.space	(2000)*PTRSIZE
266
267		/* Linux flavoured syscalls. */
268#include "syscalls.h"
269
270/*
271 * Number of arguments of each syscall
272 */
273EXPORT(sys_narg_table)
274#undef SYS
275#define SYS(call, narg) .byte narg
276
277		/* Reserved space for all SVR4 flavoured syscalls. */
278		.space	(1000)
279
280#ifdef CONFIG_BINFMT_IRIX
281		/* 32bit IRIX5 system calls. */
282#include "irix5sys.h"
283#else
284		.space	(1000)			/* No IRIX syscalls */
285#endif
286
287		/* Reserved space for all the BSD43 and POSIX syscalls. */
288		.space	(2000)
289
290		/* Linux flavoured syscalls. */
291#include "syscalls.h"
292