1/*
2 * arch/v850/kernel/entry.S -- Low-level system-call handling, trap handlers,
3 *	and context-switching
4 *
5 *  Copyright (C) 2001,02,03  NEC Electronics Corporation
6 *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License.  See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * Written by Miles Bader <miles@gnu.org>
13 */
14
15#include <linux/sys.h>
16
17#include <asm/entry.h>
18#include <asm/current.h>
19#include <asm/thread_info.h>
20#include <asm/clinkage.h>
21#include <asm/processor.h>
22#include <asm/irq.h>
23#include <asm/errno.h>
24
25#include <asm/asm-offsets.h>
26
27
28/* Make a slightly more convenient alias for C_SYMBOL_NAME.  */
29#define CSYM	C_SYMBOL_NAME
30
31
32/* The offset of the struct pt_regs in a state-save-frame on the stack.  */
33#define PTO	STATE_SAVE_PT_OFFSET
34
35
36/* Save argument registers to the state-save-frame pointed to by EP.  */
37#define SAVE_ARG_REGS							      \
38	sst.w	r6, PTO+PT_GPR(6)[ep];					      \
39	sst.w	r7, PTO+PT_GPR(7)[ep];					      \
40	sst.w	r8, PTO+PT_GPR(8)[ep];					      \
41	sst.w	r9, PTO+PT_GPR(9)[ep]
42/* Restore argument registers from the state-save-frame pointed to by EP.  */
43#define RESTORE_ARG_REGS						      \
44	sld.w	PTO+PT_GPR(6)[ep], r6;					      \
45	sld.w	PTO+PT_GPR(7)[ep], r7;					      \
46	sld.w	PTO+PT_GPR(8)[ep], r8;					      \
47	sld.w	PTO+PT_GPR(9)[ep], r9
48
49/* Save value return registers to the state-save-frame pointed to by EP.  */
50#define SAVE_RVAL_REGS							      \
51	sst.w	r10, PTO+PT_GPR(10)[ep];				      \
52	sst.w	r11, PTO+PT_GPR(11)[ep]
53/* Restore value return registers from the state-save-frame pointed to by EP.  */
54#define RESTORE_RVAL_REGS						      \
55	sld.w	PTO+PT_GPR(10)[ep], r10;				      \
56	sld.w	PTO+PT_GPR(11)[ep], r11
57
58
59#define SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS				      \
60	sst.w	r1, PTO+PT_GPR(1)[ep];					      \
61	sst.w	r5, PTO+PT_GPR(5)[ep]
62#define SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL				      \
63	sst.w	r12, PTO+PT_GPR(12)[ep];				      \
64	sst.w	r13, PTO+PT_GPR(13)[ep];				      \
65	sst.w	r14, PTO+PT_GPR(14)[ep];				      \
66	sst.w	r15, PTO+PT_GPR(15)[ep];				      \
67	sst.w	r16, PTO+PT_GPR(16)[ep];				      \
68	sst.w	r17, PTO+PT_GPR(17)[ep];				      \
69	sst.w	r18, PTO+PT_GPR(18)[ep];				      \
70	sst.w	r19, PTO+PT_GPR(19)[ep]
71#define RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS				      \
72	sld.w	PTO+PT_GPR(1)[ep], r1;					      \
73	sld.w	PTO+PT_GPR(5)[ep], r5
74#define RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL				      \
75	sld.w	PTO+PT_GPR(12)[ep], r12;				      \
76	sld.w	PTO+PT_GPR(13)[ep], r13;				      \
77	sld.w	PTO+PT_GPR(14)[ep], r14;				      \
78	sld.w	PTO+PT_GPR(15)[ep], r15;				      \
79	sld.w	PTO+PT_GPR(16)[ep], r16;				      \
80	sld.w	PTO+PT_GPR(17)[ep], r17;				      \
81	sld.w	PTO+PT_GPR(18)[ep], r18;				      \
82	sld.w	PTO+PT_GPR(19)[ep], r19
83
84/* Save `call clobbered' registers to the state-save-frame pointed to by EP.  */
85#define SAVE_CALL_CLOBBERED_REGS					      \
86	SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS;				      \
87	SAVE_ARG_REGS;							      \
88	SAVE_RVAL_REGS;							      \
89	SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL
90/* Restore `call clobbered' registers from the state-save-frame pointed to
91   by EP.  */
92#define RESTORE_CALL_CLOBBERED_REGS					      \
93	RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS;			      \
94	RESTORE_ARG_REGS;						      \
95	RESTORE_RVAL_REGS;						      \
96	RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL
97
98/* Save `call clobbered' registers except for the return-value registers
99   to the state-save-frame pointed to by EP.  */
100#define SAVE_CALL_CLOBBERED_REGS_NO_RVAL				      \
101	SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS;				      \
102	SAVE_ARG_REGS;							      \
103	SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL
104/* Restore `call clobbered' registers except for the return-value registers
105   from the state-save-frame pointed to by EP.  */
106#define RESTORE_CALL_CLOBBERED_REGS_NO_RVAL				      \
107	RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS;			      \
108	RESTORE_ARG_REGS;						      \
109	RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL
110
111/* Save `call saved' registers to the state-save-frame pointed to by EP.  */
112#define SAVE_CALL_SAVED_REGS						      \
113	sst.w	r2, PTO+PT_GPR(2)[ep];					      \
114	sst.w	r20, PTO+PT_GPR(20)[ep];				      \
115	sst.w	r21, PTO+PT_GPR(21)[ep];				      \
116	sst.w	r22, PTO+PT_GPR(22)[ep];				      \
117	sst.w	r23, PTO+PT_GPR(23)[ep];				      \
118	sst.w	r24, PTO+PT_GPR(24)[ep];				      \
119	sst.w	r25, PTO+PT_GPR(25)[ep];				      \
120	sst.w	r26, PTO+PT_GPR(26)[ep];				      \
121	sst.w	r27, PTO+PT_GPR(27)[ep];				      \
122	sst.w	r28, PTO+PT_GPR(28)[ep];				      \
123	sst.w	r29, PTO+PT_GPR(29)[ep]
124/* Restore `call saved' registers from the state-save-frame pointed to by EP.  */
125#define RESTORE_CALL_SAVED_REGS						      \
126	sld.w	PTO+PT_GPR(2)[ep], r2;					      \
127	sld.w	PTO+PT_GPR(20)[ep], r20;				      \
128	sld.w	PTO+PT_GPR(21)[ep], r21;				      \
129	sld.w	PTO+PT_GPR(22)[ep], r22;				      \
130	sld.w	PTO+PT_GPR(23)[ep], r23;				      \
131	sld.w	PTO+PT_GPR(24)[ep], r24;				      \
132	sld.w	PTO+PT_GPR(25)[ep], r25;				      \
133	sld.w	PTO+PT_GPR(26)[ep], r26;				      \
134	sld.w	PTO+PT_GPR(27)[ep], r27;				      \
135	sld.w	PTO+PT_GPR(28)[ep], r28;				      \
136	sld.w	PTO+PT_GPR(29)[ep], r29
137
138
139/* Save the PC stored in the special register SAVEREG to the state-save-frame
140   pointed to by EP.  r19 is clobbered.  */
141#define SAVE_PC(savereg)						      \
142	stsr	SR_ ## savereg, r19;					      \
143	sst.w	r19, PTO+PT_PC[ep]
144/* Restore the PC from the state-save-frame pointed to by EP, to the special
145   register SAVEREG.  LP is clobbered (it is used as a scratch register
146   because the POP_STATE macro restores it, and this macro is usually used
147   inside POP_STATE).  */
148#define RESTORE_PC(savereg)						      \
149	sld.w	PTO+PT_PC[ep], lp;					      \
150	ldsr	lp, SR_ ## savereg
151/* Save the PSW register stored in the special register SAVREG to the
152   state-save-frame pointed to by EP.  r19 is clobbered.  */
153#define SAVE_PSW(savereg)						      \
154	stsr	SR_ ## savereg, r19;					      \
155	sst.w	r19, PTO+PT_PSW[ep]
156/* Restore the PSW register from the state-save-frame pointed to by EP, to
157   the special register SAVEREG.  LP is clobbered (it is used as a scratch
158   register because the POP_STATE macro restores it, and this macro is
159   usually used inside POP_STATE).  */
160#define RESTORE_PSW(savereg)						      \
161	sld.w	PTO+PT_PSW[ep], lp;					      \
162	ldsr	lp, SR_ ## savereg
163
164/* Save CTPC/CTPSW/CTBP registers to the state-save-frame pointed to by REG.
165   r19 is clobbered.  */
166#define SAVE_CT_REGS							      \
167	stsr	SR_CTPC, r19;						      \
168	sst.w	r19, PTO+PT_CTPC[ep];					      \
169	stsr	SR_CTPSW, r19;						      \
170	sst.w	r19, PTO+PT_CTPSW[ep];					      \
171	stsr	SR_CTBP, r19;						      \
172	sst.w	r19, PTO+PT_CTBP[ep]
173/* Restore CTPC/CTPSW/CTBP registers from the state-save-frame pointed to by EP.
174   LP is clobbered (it is used as a scratch register because the POP_STATE
175   macro restores it, and this macro is usually used inside POP_STATE).  */
176#define RESTORE_CT_REGS							      \
177	sld.w	PTO+PT_CTPC[ep], lp;					      \
178	ldsr	lp, SR_CTPC;						      \
179	sld.w	PTO+PT_CTPSW[ep], lp;					      \
180	ldsr	lp, SR_CTPSW;						      \
181	sld.w	PTO+PT_CTBP[ep], lp;					      \
182	ldsr	lp, SR_CTBP
183
184
185/* Push register state, except for the stack pointer, on the stack in the
186   form of a state-save-frame (plus some extra padding), in preparation for
187   a system call.  This macro makes sure that the EP, GP, and LP
188   registers are saved, and TYPE identifies the set of extra registers to
189   be saved as well.  Also copies (the new value of) SP to EP.  */
190#define PUSH_STATE(type)						      \
191	addi	-STATE_SAVE_SIZE, sp, sp; /* Make room on the stack.  */      \
192	st.w	ep, PTO+PT_GPR(GPR_EP)[sp];				      \
193	mov	sp, ep;							      \
194	sst.w	gp, PTO+PT_GPR(GPR_GP)[ep];				      \
195	sst.w	lp, PTO+PT_GPR(GPR_LP)[ep];				      \
196	type ## _STATE_SAVER
197/* Pop a register state pushed by PUSH_STATE, except for the stack pointer,
198   from the stack.  */
199#define POP_STATE(type)							      \
200	mov	sp, ep;							      \
201	type ## _STATE_RESTORER;					      \
202	sld.w	PTO+PT_GPR(GPR_GP)[ep], gp;				      \
203	sld.w	PTO+PT_GPR(GPR_LP)[ep], lp;				      \
204	sld.w	PTO+PT_GPR(GPR_EP)[ep], ep;				      \
205	addi	STATE_SAVE_SIZE, sp, sp /* Clean up our stack space.  */
206
207
208/* Switch to the kernel stack if necessary, and push register state on the
209   stack in the form of a state-save-frame.  Also load the current task
210   pointer if switching from user mode.  The stack-pointer (r3) should have
211   already been saved to the memory location SP_SAVE_LOC (the reason for
212   this is that the interrupt vectors may be beyond a 22-bit signed offset
213   jump from the actual interrupt handler, and this allows them to save the
214   stack-pointer and use that register to do an indirect jump).  This macro
215   makes sure that `special' registers, system registers, and the stack
216   pointer are saved; TYPE identifies the set of extra registers to be
217   saved as well.  SYSCALL_NUM is the register in which the system-call
218   number this state is for is stored (r0 if this isn't a system call).
219   Interrupts should already be disabled when calling this.  */
220#define SAVE_STATE(type, syscall_num, sp_save_loc)			      \
221	tst1	0, KM;			/* See if already in kernel mode.  */ \
222	bz	1f;							      \
223	ld.w	sp_save_loc, sp;	/* ... yes, use saved SP.  */	      \
224	br	2f;							      \
2251:	ld.w	KSP, sp;		/* ... no, switch to kernel stack. */ \
2262:	PUSH_STATE(type);						      \
227	ld.b	KM, r19;		/* Remember old kernel-mode.  */      \
228	sst.w	r19, PTO+PT_KERNEL_MODE[ep];				      \
229	ld.w	sp_save_loc, r19;	/* Remember old SP.  */		      \
230	sst.w	r19, PTO+PT_GPR(GPR_SP)[ep];				      \
231	mov	1, r19;			/* Now definitely in kernel-mode. */  \
232	st.b	r19, KM;						      \
233	GET_CURRENT_TASK(CURRENT_TASK);	/* Fetch the current task pointer. */ \
234	/* Save away the syscall number.  */				      \
235	sst.w	syscall_num, PTO+PT_CUR_SYSCALL[ep]
236
237
238/* Save register state not normally saved by PUSH_STATE for TYPE, to the
239   state-save-frame on the stack; also copies SP to EP.  r19 may be trashed. */
240#define SAVE_EXTRA_STATE(type)						      \
241	mov	sp, ep;							      \
242	type ## _EXTRA_STATE_SAVER
243/* Restore register state not normally restored by POP_STATE for TYPE,
244   from the state-save-frame on the stack; also copies SP to EP.
245   r19 may be trashed.  */
246#define RESTORE_EXTRA_STATE(type)					      \
247	mov	sp, ep;							      \
248	type ## _EXTRA_STATE_RESTORER
249
250/* Save any call-clobbered registers not normally saved by PUSH_STATE for
251   TYPE, to the state-save-frame on the stack.
252   EP may be trashed, but is not guaranteed to contain a copy of SP
253   (unlike after most SAVE_... macros).  r19 may be trashed.  */
254#define SAVE_EXTRA_STATE_FOR_SCHEDULE(type)				      \
255	type ## _SCHEDULE_EXTRA_STATE_SAVER
256/* Restore any call-clobbered registers not normally restored by
257   POP_STATE for TYPE, to the state-save-frame on the stack.
258   EP may be trashed, but is not guaranteed to contain a copy of SP
259   (unlike after most RESTORE_... macros).  r19 may be trashed.  */
260#define RESTORE_EXTRA_STATE_FOR_SCHEDULE(type)				      \
261	type ## _SCHEDULE_EXTRA_STATE_RESTORER
262
263
264/* These are extra_state_saver/restorer values for a user trap.  Note
265   that we save the argument registers so that restarted syscalls will
266   function properly (otherwise it wouldn't be necessary), and we must
267   _not_ restore the return-value registers (so that traps can return a
268   value!), but call-clobbered registers are not saved at all, as the
269   caller of the syscall function should have saved them.  */
270
271#define TRAP_RET reti
272/* Traps don't save call-clobbered registers (but do still save arg regs).
273   We preserve PSw to keep long-term state, namely interrupt status (for traps
274   from kernel-mode), and the single-step flag (for user traps).  */
275#define TRAP_STATE_SAVER						      \
276	SAVE_ARG_REGS;							      \
277	SAVE_PC(EIPC);							      \
278	SAVE_PSW(EIPSW)
279/* When traps return, they just leave call-clobbered registers (except for arg
280   regs) with whatever value they have from the kernel.  Traps don't preserve
281   the PSW, but we zero EIPSW to ensure it doesn't contain anything dangerous
282   (in particular, the single-step flag).  */
283#define TRAP_STATE_RESTORER						      \
284	RESTORE_ARG_REGS;						      \
285	RESTORE_PC(EIPC);						      \
286	RESTORE_PSW(EIPSW)
287/* Save registers not normally saved by traps.  We need to save r12, even
288   though it's nominally call-clobbered, because it's used when restarting
289   a system call (the signal-handling path uses SAVE_EXTRA_STATE, and
290   expects r12 to be restored when the trap returns).  */
291#define TRAP_EXTRA_STATE_SAVER						      \
292	SAVE_RVAL_REGS;							      \
293	sst.w	r12, PTO+PT_GPR(12)[ep];				      \
294	SAVE_CALL_SAVED_REGS;						      \
295	SAVE_CT_REGS
296#define TRAP_EXTRA_STATE_RESTORER					      \
297	RESTORE_RVAL_REGS;						      \
298	sld.w	PTO+PT_GPR(12)[ep], r12;				      \
299	RESTORE_CALL_SAVED_REGS;					      \
300	RESTORE_CT_REGS
301/* Save registers prior to calling scheduler (just before trap returns).
302   We have to save the return-value registers to preserve the trap's return
303   value.  Note that ..._SCHEDULE_EXTRA_STATE_SAVER, unlike most ..._SAVER
304   macros, is required to setup EP itself if EP is needed (this is because
305   in many cases, the macro is empty).  */
306#define TRAP_SCHEDULE_EXTRA_STATE_SAVER					      \
307	mov sp, ep;							      \
308	SAVE_RVAL_REGS
309/* Note that ..._SCHEDULE_EXTRA_STATE_RESTORER, unlike most ..._RESTORER
310   macros, is required to setup EP itself if EP is needed (this is because
311   in many cases, the macro is empty).  */
312#define TRAP_SCHEDULE_EXTRA_STATE_RESTORER				      \
313	mov sp, ep;							      \
314	RESTORE_RVAL_REGS
315
316/* Register saving/restoring for maskable interrupts.  */
317#define IRQ_RET reti
318#define IRQ_STATE_SAVER							      \
319	SAVE_CALL_CLOBBERED_REGS;					      \
320	SAVE_PC(EIPC);							      \
321	SAVE_PSW(EIPSW)
322#define IRQ_STATE_RESTORER						      \
323	RESTORE_CALL_CLOBBERED_REGS;					      \
324	RESTORE_PC(EIPC);						      \
325	RESTORE_PSW(EIPSW)
326#define IRQ_EXTRA_STATE_SAVER						      \
327	SAVE_CALL_SAVED_REGS;						      \
328	SAVE_CT_REGS
329#define IRQ_EXTRA_STATE_RESTORER					      \
330	RESTORE_CALL_SAVED_REGS;					      \
331	RESTORE_CT_REGS
332#define IRQ_SCHEDULE_EXTRA_STATE_SAVER	     /* nothing */
333#define IRQ_SCHEDULE_EXTRA_STATE_RESTORER    /* nothing */
334
335/* Register saving/restoring for non-maskable interrupts.  */
336#define NMI_RET reti
337#define NMI_STATE_SAVER							      \
338	SAVE_CALL_CLOBBERED_REGS;					      \
339	SAVE_PC(FEPC);							      \
340	SAVE_PSW(FEPSW);
341#define NMI_STATE_RESTORER						      \
342	RESTORE_CALL_CLOBBERED_REGS;					      \
343	RESTORE_PC(FEPC);						      \
344	RESTORE_PSW(FEPSW);
345#define NMI_EXTRA_STATE_SAVER						      \
346	SAVE_CALL_SAVED_REGS;						      \
347	SAVE_CT_REGS
348#define NMI_EXTRA_STATE_RESTORER					      \
349	RESTORE_CALL_SAVED_REGS;					      \
350	RESTORE_CT_REGS
351#define NMI_SCHEDULE_EXTRA_STATE_SAVER	     /* nothing */
352#define NMI_SCHEDULE_EXTRA_STATE_RESTORER    /* nothing */
353
354/* Register saving/restoring for debug traps.  */
355#define DBTRAP_RET .long 0x014607E0 /* `dbret', but gas doesn't support it. */
356#define DBTRAP_STATE_SAVER						      \
357	SAVE_CALL_CLOBBERED_REGS;					      \
358	SAVE_PC(DBPC);							      \
359	SAVE_PSW(DBPSW)
360#define DBTRAP_STATE_RESTORER						      \
361	RESTORE_CALL_CLOBBERED_REGS;					      \
362	RESTORE_PC(DBPC);						      \
363	RESTORE_PSW(DBPSW)
364#define DBTRAP_EXTRA_STATE_SAVER					      \
365	SAVE_CALL_SAVED_REGS;						      \
366	SAVE_CT_REGS
367#define DBTRAP_EXTRA_STATE_RESTORER					      \
368	RESTORE_CALL_SAVED_REGS;					      \
369	RESTORE_CT_REGS
370#define DBTRAP_SCHEDULE_EXTRA_STATE_SAVER	/* nothing */
371#define DBTRAP_SCHEDULE_EXTRA_STATE_RESTORER	/* nothing */
372
373/* Register saving/restoring for a context switch.  We don't need to save
374   too many registers, because context-switching looks like a function call
375   (via the function `switch_thread'), so callers will save any
376   call-clobbered registers themselves.  We do need to save the CT regs, as
377   they're normally not saved during kernel entry (the kernel doesn't use
378   them).  We save PSW so that interrupt-status state will correctly follow
379   each thread (mostly NMI vs. normal-IRQ/trap), though for the most part
380   it doesn't matter since threads are always in almost exactly the same
381   processor state during a context switch.  The stack pointer and return
382   value are handled by switch_thread itself.  */
383#define SWITCH_STATE_SAVER						      \
384	SAVE_CALL_SAVED_REGS;						      \
385	SAVE_PSW(PSW);							      \
386	SAVE_CT_REGS
387#define SWITCH_STATE_RESTORER						      \
388	RESTORE_CALL_SAVED_REGS;					      \
389	RESTORE_PSW(PSW);						      \
390	RESTORE_CT_REGS
391
392
393/* Restore register state from the state-save-frame on the stack, switch back
394   to the user stack if necessary, and return from the trap/interrupt.
395   EXTRA_STATE_RESTORER is a sequence of assembly language statements to
396   restore anything not restored by this macro.  Only registers not saved by
397   the C compiler are restored (that is, R3(sp), R4(gp), R31(lp), and
398   anything restored by EXTRA_STATE_RESTORER).  */
399#define RETURN(type)							      \
400	ld.b	PTO+PT_KERNEL_MODE[sp], r19;				      \
401	di;				/* Disable interrupts */	      \
402	cmp	r19, r0;		/* See if returning to kernel mode, */\
403	bne	2f;			/* ... if so, skip resched &c.  */    \
404									      \
405	/* We're returning to user mode, so check for various conditions that \
406	   trigger rescheduling. */					      \
407	GET_CURRENT_THREAD(r18);					      \
408	ld.w	TI_FLAGS[r18], r19;					      \
409	andi	_TIF_NEED_RESCHED, r19, r0;				      \
410	bnz	3f;			/* Call the scheduler.  */	      \
4115:	andi	_TIF_SIGPENDING, r19, r18;				      \
412	ld.w	TASK_PTRACE[CURRENT_TASK], r19; /* ptrace flags */	      \
413	or	r18, r19;		/* see if either is non-zero */	      \
414	bnz	4f;			/* if so, handle them */	      \
415									      \
416/* Return to user state.  */						      \
4171:	st.b	r0, KM;			/* Now officially in user state. */   \
418									      \
419/* Final return.  The stack-pointer fiddling is not needed when returning     \
420   to kernel-mode, but they don't hurt, and this way we can share the	      \
421   (sometimes rather lengthy) POP_STATE macro.  */			      \
4222:	POP_STATE(type);						      \
423	st.w	sp, KSP;		/* Save the kernel stack pointer. */  \
424	ld.w	PT_GPR(GPR_SP)-PT_SIZE[sp], sp; /* Restore stack pointer. */  \
425	type ## _RET;			/* Return from the trap/interrupt. */ \
426									      \
427/* Call the scheduler before returning from a syscall/trap. */		      \
4283:	SAVE_EXTRA_STATE_FOR_SCHEDULE(type); /* Prepare to call scheduler. */ \
429	jarl	call_scheduler, lp;	/* Call scheduler */		      \
430	di;				/* The scheduler enables interrupts */\
431	RESTORE_EXTRA_STATE_FOR_SCHEDULE(type);				      \
432	GET_CURRENT_THREAD(r18);					      \
433	ld.w	TI_FLAGS[r18], r19;					      \
434	br	5b;			/* Continue with return path. */      \
435									      \
436/* Handle a signal or ptraced process return.				      \
437   r18 should be non-zero if there are pending signals.  */		      \
4384:	/* Not all registers are saved by the normal trap/interrupt entry     \
439	   points (for instance, call-saved registers (because the normal     \
440	   C-compiler calling sequence in the kernel makes sure they're	      \
441	   preserved), and call-clobbered registers in the case of	      \
442	   traps), but signal handlers may want to examine or change the      \
443	   complete register state.  Here we save anything not saved by	      \
444	   the normal entry sequence, so that it may be safely restored	      \
445	   (in a possibly modified form) after do_signal returns.  */	      \
446	SAVE_EXTRA_STATE(type);		/* Save state not saved by entry. */  \
447	jarl	handle_signal_or_ptrace_return, lp;			      \
448	RESTORE_EXTRA_STATE(type);	/* Restore extra regs.  */	      \
449	br	1b
450
451
452/* Jump to the appropriate function for the system call number in r12
453   (r12 is not preserved), or return an error if r12 is not valid.  The
454   LP register should point to the location where the called function
455   should return.  [note that MAKE_SYS_CALL uses label 1]  */
456#define MAKE_SYS_CALL							      \
457	/* Figure out which function to use for this system call.  */	      \
458	shl	2, r12;							      \
459	/* See if the system call number is valid.  */			      \
460	addi	lo(CSYM(sys_call_table) - sys_call_table_end), r12, r0;	      \
461	bnh	1f;							      \
462	mov	hilo(CSYM(sys_call_table)), r19;			      \
463	add	r19, r12;						      \
464	ld.w	0[r12], r12;						      \
465	/* Make the system call.  */					      \
466	jmp	[r12];							      \
467	/* The syscall number is invalid, return an error.  */		      \
4681:	addi	-ENOSYS, r0, r10;					      \
469	jmp	[lp]
470
471
472	.text
473
474/*
475 * User trap.
476 *
477 * Trap 0 system calls are also handled here.
478 *
479 * The stack-pointer (r3) should have already been saved to the memory
480 * location ENTRY_SP (the reason for this is that the interrupt vectors may be
481 * beyond a 22-bit signed offset jump from the actual interrupt handler, and
482 * this allows them to save the stack-pointer and use that register to do an
483 * indirect jump).
484 *
485 * Syscall protocol:
486 *   Syscall number in r12, args in r6-r9
487 *   Return value in r10
488 */
489G_ENTRY(trap):
490	SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers.
491	stsr	SR_ECR, r19		// Find out which trap it was.
492	ei				// Enable interrupts.
493	mov	hilo(ret_from_trap), lp	// where the trap should return
494
495	// The following two shifts (1) clear out extraneous NMI data in the
496	// upper 16-bits, (2) convert the 0x40 - 0x5f range of trap ECR
497	// numbers into the (0-31) << 2 range we want, (3) set the flags.
498	shl	27, r19			// chop off all high bits
499	shr	25, r19			// scale back down and then << 2
500	bnz	2f			// See if not trap 0.
501
502	// Trap 0 is a `short' system call, skip general trap table.
503	MAKE_SYS_CALL			// Jump to the syscall function.
504
5052:	// For other traps, use a table lookup.
506	mov	hilo(CSYM(trap_table)), r18
507	add	r19, r18
508	ld.w	0[r18], r18
509	jmp	[r18]			// Jump to the trap handler.
510END(trap)
511
512/* This is just like ret_from_trap, but first restores extra registers
513   saved by some wrappers.  */
514L_ENTRY(restore_extra_regs_and_ret_from_trap):
515	RESTORE_EXTRA_STATE(TRAP)
516	// fall through
517END(restore_extra_regs_and_ret_from_trap)
518
519/* Entry point used to return from a syscall/trap.  */
520L_ENTRY(ret_from_trap):
521	RETURN(TRAP)
522END(ret_from_trap)
523
524
525/* This the initial entry point for a new child thread, with an appropriate
526   stack in place that makes it look that the child is in the middle of an
527   syscall.  This function is actually `returned to' from switch_thread
528   (copy_thread makes ret_from_fork the return address in each new thread's
529   saved context).  */
530C_ENTRY(ret_from_fork):
531	mov	r10, r6			// switch_thread returns the prev task.
532	jarl	CSYM(schedule_tail), lp	// ...which is schedule_tail's arg
533	mov	r0, r10			// Child's fork call should return 0.
534	br	ret_from_trap		// Do normal trap return.
535C_END(ret_from_fork)
536
537
538/*
539 * Trap 1: `long' system calls
540 * `Long' syscall protocol:
541 *   Syscall number in r12, args in r6-r9, r13-r14
542 *   Return value in r10
543 */
544L_ENTRY(syscall_long):
545	// Push extra arguments on the stack.  Note that by default, the trap
546	// handler reserves enough stack space for 6 arguments, so we don't
547	// have to make any additional room.
548	st.w	r13, 16[sp]		// arg 5
549	st.w	r14, 20[sp]		// arg 6
550
551	// Make sure r13 and r14 are preserved, in case we have to restart a
552	// system call because of a signal (ep has already been set by caller).
553	st.w	r13, PTO+PT_GPR(13)[sp]
554	st.w	r14, PTO+PT_GPR(13)[sp]
555	mov	hilo(ret_from_long_syscall), lp
556
557	MAKE_SYS_CALL			// Jump to the syscall function.
558END(syscall_long)
559
560/* Entry point used to return from a long syscall.  Only needed to restore
561   r13/r14 if the general trap mechanism doesnt' do so.  */
562L_ENTRY(ret_from_long_syscall):
563	ld.w	PTO+PT_GPR(13)[sp], r13 // Restore the extra registers
564	ld.w	PTO+PT_GPR(13)[sp], r14
565	br	ret_from_trap		// The rest is the same as other traps
566END(ret_from_long_syscall)
567
568
569/* These syscalls need access to the struct pt_regs on the stack, so we
570   implement them in assembly (they're basically all wrappers anyway).  */
571
572L_ENTRY(sys_fork_wrapper):
573#ifdef CONFIG_MMU
574	addi	SIGCHLD, r0, r6		   // Arg 0: flags
575	ld.w	PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
576	movea	PTO, sp, r8		   // Arg 2: parent context
577	mov	r0, r9			   // Arg 3/4/5: 0
578	st.w	r0, 16[sp]
579	st.w	r0, 20[sp]
580	mov	hilo(CSYM(do_fork)), r18   // Where the real work gets done
581	br	save_extra_state_tramp	   // Save state and go there
582#else
583	// fork almost works, enough to trick you into looking elsewhere :-(
584	addi	-EINVAL, r0, r10
585	jmp	[lp]
586#endif
587END(sys_fork_wrapper)
588
589L_ENTRY(sys_vfork_wrapper):
590	addi	CLONE_VFORK | CLONE_VM | SIGCHLD, r0, r6 // Arg 0: flags
591	ld.w	PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
592	movea	PTO, sp, r8		   // Arg 2: parent context
593	mov	r0, r9			   // Arg 3/4/5: 0
594	st.w	r0, 16[sp]
595	st.w	r0, 20[sp]
596	mov	hilo(CSYM(do_fork)), r18   // Where the real work gets done
597	br	save_extra_state_tramp	   // Save state and go there
598END(sys_vfork_wrapper)
599
600L_ENTRY(sys_clone_wrapper):
601	ld.w	PTO+PT_GPR(GPR_SP)[sp], r19// parent's stack pointer
602	cmp	r7, r0			   // See if child SP arg (arg 1) is 0.
603	cmov	z, r19, r7, r7		   // ... and use the parent's if so.
604	movea	PTO, sp, r8		   // Arg 2: parent context
605	mov	r0, r9			   // Arg 3/4/5: 0
606	st.w	r0, 16[sp]
607	st.w	r0, 20[sp]
608	mov	hilo(CSYM(do_fork)), r18   // Where the real work gets done
609	br	save_extra_state_tramp	   // Save state and go there
610END(sys_clone_wrapper)
611
612
613L_ENTRY(sys_execve_wrapper):
614	movea	PTO, sp, r9		// add user context as 4th arg
615	jr	CSYM(sys_execve)	// Do real work (tail-call).
616END(sys_execve_wrapper)
617
618
619L_ENTRY(sys_sigsuspend_wrapper):
620	movea	PTO, sp, r7		// add user context as 2nd arg
621	mov	hilo(CSYM(sys_sigsuspend)), r18	// syscall function
622	jarl	save_extra_state_tramp, lp	// Save state and do it
623	br	restore_extra_regs_and_ret_from_trap
624END(sys_sigsuspend_wrapper)
625L_ENTRY(sys_rt_sigsuspend_wrapper):
626	movea	PTO, sp, r8		// add user context as 3rd arg
627	mov	hilo(CSYM(sys_rt_sigsuspend)), r18 // syscall function
628	jarl	save_extra_state_tramp, lp	   // Save state and do it
629	br	restore_extra_regs_and_ret_from_trap
630END(sys_rt_sigsuspend_wrapper)
631
632L_ENTRY(sys_sigreturn_wrapper):
633	movea	PTO, sp, r6		// add user context as 1st arg
634	mov	hilo(CSYM(sys_sigreturn)), r18	// syscall function
635	jarl	save_extra_state_tramp, lp	// Save state and do it
636	br	restore_extra_regs_and_ret_from_trap
637END(sys_sigreturn_wrapper)
638L_ENTRY(sys_rt_sigreturn_wrapper):
639	movea	PTO, sp, r6		// add user context as 1st arg
640	mov	hilo(CSYM(sys_rt_sigreturn)), r18// syscall function
641	jarl	save_extra_state_tramp, lp	 // Save state and do it
642	br	restore_extra_regs_and_ret_from_trap
643END(sys_rt_sigreturn_wrapper)
644
645
646/* Save any state not saved by SAVE_STATE(TRAP), and jump to r18.
647   It's main purpose is to share the rather lengthy code sequence that
648   SAVE_STATE expands into among the above wrapper functions.  */
649L_ENTRY(save_extra_state_tramp):
650	SAVE_EXTRA_STATE(TRAP)		// Save state not saved by entry.
651	jmp	[r18]			// Do the work the caller wants
652END(save_extra_state_tramp)
653
654
655/*
656 * Hardware maskable interrupts.
657 *
658 * The stack-pointer (r3) should have already been saved to the memory
659 * location ENTRY_SP (the reason for this is that the interrupt vectors may be
660 * beyond a 22-bit signed offset jump from the actual interrupt handler, and
661 * this allows them to save the stack-pointer and use that register to do an
662 * indirect jump).
663 */
664G_ENTRY(irq):
665	SAVE_STATE (IRQ, r0, ENTRY_SP)	// Save registers.
666
667	stsr	SR_ECR, r6		// Find out which interrupt it was.
668	movea	PTO, sp, r7		// User regs are arg2
669
670	// All v850 implementations I know about encode their interrupts as
671	// multiples of 0x10, starting at 0x80 (after NMIs and software
672	// interrupts).  Convert this number into a simple IRQ index for the
673	// rest of the kernel.  We also clear the upper 16 bits, which hold
674	// NMI info, and don't appear to be cleared when a NMI returns.
675	shl	16, r6			// clear upper 16 bits
676	shr	20, r6			// shift back, and remove lower nibble
677	add	-8, r6			// remove bias for irqs
678
679	// Call the high-level interrupt handling code.
680	jarl	CSYM(handle_irq), lp
681
682	RETURN(IRQ)
683END(irq)
684
685
686/*
687 * Debug trap / illegal-instruction exception
688 *
689 * The stack-pointer (r3) should have already been saved to the memory
690 * location ENTRY_SP (the reason for this is that the interrupt vectors may be
691 * beyond a 22-bit signed offset jump from the actual interrupt handler, and
692 * this allows them to save the stack-pointer and use that register to do an
693 * indirect jump).
694 */
695G_ENTRY(dbtrap):
696	SAVE_STATE (DBTRAP, r0, ENTRY_SP)// Save registers.
697
698	/* First see if we came from kernel mode; if so, the dbtrap
699	   instruction has a special meaning, to set the DIR (`debug
700	   information register') register.  This is because the DIR register
701	   can _only_ be manipulated/read while in `debug mode,' and debug
702	   mode is only active while we're inside the dbtrap handler.  The
703	   exact functionality is:  { DIR = (DIR | r6) & ~r7; return DIR; }. */
704	ld.b	PTO+PT_KERNEL_MODE[sp], r19
705	cmp	r19, r0
706	bz	1f
707
708	stsr	SR_DIR, r10
709	or	r6, r10
710	not	r7, r7
711	and	r7, r10
712	ldsr	r10, SR_DIR
713	stsr	SR_DIR, r10		// Confirm the value we set
714	st.w	r10, PTO+PT_GPR(10)[sp]	// return it
715	br	3f
716
7171:	ei				// Enable interrupts.
718
719	/* The default signal type we raise.  */
720	mov	SIGTRAP, r6
721
722	/* See if it's a single-step trap.  */
723	stsr	SR_DBPSW, r19
724	andi	0x0800, r19, r19
725	bnz	2f
726
727	/* Look to see if the preceding instruction was is a dbtrap or not,
728	   to decide which signal we should use.  */
729	stsr	SR_DBPC, r19		// PC following trapping insn
730	ld.hu	-2[r19], r19
731	ori	0xf840, r0, r20		// DBTRAP insn
732	cmp	r19, r20		// Was this trap caused by DBTRAP?
733	cmov	ne, SIGILL, r6, r6	// Choose signal appropriately
734
735	/* Raise the desired signal.  */
7362:	mov	CURRENT_TASK, r7	// Arg 1: task
737	jarl	CSYM(send_sig), lp	// tail call
738
7393:	RETURN(DBTRAP)
740END(dbtrap)
741
742
743/*
744 * Hardware non-maskable interrupts.
745 *
746 * The stack-pointer (r3) should have already been saved to the memory
747 * location ENTRY_SP (the reason for this is that the interrupt vectors may be
748 * beyond a 22-bit signed offset jump from the actual interrupt handler, and
749 * this allows them to save the stack-pointer and use that register to do an
750 * indirect jump).
751 */
752G_ENTRY(nmi):
753	SAVE_STATE (NMI, r0, NMI_ENTRY_SP); /* Save registers.  */
754
755	stsr	SR_ECR, r6;		/* Find out which nmi it was.  */
756	shr	20, r6;			/* Extract NMI code in bits 20-24. */
757	movea	PTO, sp, r7;		/* User regs are arg2.  */
758
759	/* Non-maskable interrupts always lie right after maskable interrupts.
760	   Call the generic IRQ handler, with two arguments, the IRQ number,
761	   and a pointer to the user registers, to handle the specifics.
762	   (we subtract one because the first NMI has code 1).  */
763	addi	FIRST_NMI - 1, r6, r6
764	jarl	CSYM(handle_irq), lp
765
766	RETURN(NMI)
767END(nmi)
768
769
770/*
771 * Trap with no handler
772 */
773L_ENTRY(bad_trap_wrapper):
774	mov	r19, r6			// Arg 0: trap number
775	movea	PTO, sp, r7		// Arg 1: user regs
776	jr	CSYM(bad_trap)		// tail call handler
777END(bad_trap_wrapper)
778
779
780/*
781 * Invoke the scheduler, called from the trap/irq kernel exit path.
782 *
783 * This basically just calls `schedule', but also arranges for extra
784 * registers to be saved for ptrace'd processes, so ptrace can modify them.
785 */
786L_ENTRY(call_scheduler):
787	ld.w	TASK_PTRACE[CURRENT_TASK], r19	// See if task is ptrace'd
788	cmp	r19, r0
789	bnz	1f			// ... yes, do special stuff
790	jr	CSYM(schedule)		// ... no, just tail-call scheduler
791
792	// Save extra regs for ptrace'd task.  We want to save anything
793	// that would otherwise only be `implicitly' saved by the normal
794	// compiler calling-convention.
7951:	mov	sp, ep			// Setup EP for SAVE_CALL_SAVED_REGS
796	SAVE_CALL_SAVED_REGS		// Save call-saved registers to stack
797	mov	lp, r20			// Save LP in a callee-saved register
798
799	jarl	CSYM(schedule), lp	// Call scheduler
800
801	mov	r20, lp
802	mov	sp, ep			// We can't rely on EP after return
803	RESTORE_CALL_SAVED_REGS		// Restore (possibly modified) regs
804	jmp	[lp]			// Return to the return path
805END(call_scheduler)
806
807
808/*
809 * This is an out-of-line handler for two special cases during the kernel
810 * trap/irq exit sequence:
811 *
812 *  (1) If r18 is non-zero then a signal needs to be handled, which is
813 *	done, and then the caller returned to.
814 *
815 *  (2) If r18 is non-zero then we're returning to a ptraced process, which
816 *	has several special cases -- single-stepping and trap tracing, both
817 *	of which require using the `dbret' instruction to exit the kernel
818 *	instead of the normal `reti' (this is because the CPU not correctly
819 *	single-step after a reti).  In this case, of course, this handler
820 *	never returns to the caller.
821 *
822 * In either case, all registers should have been saved to the current
823 * state-save-frame on the stack, except for callee-saved registers.
824 *
825 * [These two different cases are combined merely to avoid bloating the
826 * macro-inlined code, not because they really make much sense together!]
827 */
828L_ENTRY(handle_signal_or_ptrace_return):
829	cmp	r18, r0			// See if handling a signal
830	bz	1f			// ... nope, go do ptrace return
831
832	// Handle a signal
833	mov	lp, r20			// Save link-pointer
834	mov	r10, r21		// Save return-values (for trap)
835	mov	r11, r22
836
837	movea	PTO, sp, r6		// Arg 1: struct pt_regs *regs
838	mov	r0, r7			// Arg 2: sigset_t *oldset
839	jarl	CSYM(do_signal), lp	// Handle the signal
840	di				// sig handling enables interrupts
841
842	mov	r20, lp			// Restore link-pointer
843	mov	r21, r10		// Restore return-values (for trap)
844	mov	r22, r11
845	ld.w	TASK_PTRACE[CURRENT_TASK], r19  // check ptrace flags too
846	cmp	r19, r0
847	bnz	1f			// ... some set, so look more
8482:	jmp	[lp]			// ... none set, so return normally
849
850	// ptrace return
8511:	ld.w	PTO+PT_PSW[sp], r19	// Look at user-processes's flags
852	andi	0x0800, r19, r19	// See if single-step flag is set
853	bz	2b			// ... nope, return normally
854
855	// Return as if from a dbtrap insn
856	st.b	r0, KM			// Now officially in user state.
857	POP_STATE(DBTRAP)		// Restore regs
858	st.w	sp, KSP			// Save the kernel stack pointer.
859	ld.w	PT_GPR(GPR_SP)-PT_SIZE[sp], sp // Restore user stack pointer.
860	DBTRAP_RET			// Return from the trap/interrupt.
861END(handle_signal_or_ptrace_return)
862
863
864/*
865 * This is where we switch between two threads.  The arguments are:
866 *   r6 -- pointer to the struct thread for the `current' process
867 *   r7 -- pointer to the struct thread for the `new' process.
868 * when this function returns, it will return to the new thread.
869 */
870C_ENTRY(switch_thread):
871	// Return the previous task (r10 is not clobbered by restore below)
872	mov	CURRENT_TASK, r10
873	// First, push the current processor state on the stack
874	PUSH_STATE(SWITCH)
875	// Now save the location of the kernel stack pointer for this thread;
876	// since we've pushed all other state on the stack, this is enough to
877	// restore it all later.
878	st.w	sp, THREAD_KSP[r6]
879	// Now restore the stack pointer from the new process
880	ld.w	THREAD_KSP[r7], sp
881	// ... and restore all state from that
882	POP_STATE(SWITCH)
883	// Update the current task pointer
884	GET_CURRENT_TASK(CURRENT_TASK)
885	// Now return into the new thread
886	jmp	[lp]
887C_END(switch_thread)
888
889
890	.data
891
892	.align 4
893C_DATA(trap_table):
894	.long bad_trap_wrapper		// trap 0, doesn't use trap table.
895	.long syscall_long		// trap 1, `long' syscall.
896	.long bad_trap_wrapper
897	.long bad_trap_wrapper
898	.long bad_trap_wrapper
899	.long bad_trap_wrapper
900	.long bad_trap_wrapper
901	.long bad_trap_wrapper
902	.long bad_trap_wrapper
903	.long bad_trap_wrapper
904	.long bad_trap_wrapper
905	.long bad_trap_wrapper
906	.long bad_trap_wrapper
907	.long bad_trap_wrapper
908	.long bad_trap_wrapper
909	.long bad_trap_wrapper
910C_END(trap_table)
911
912
913	.section .rodata
914
915	.align 4
916C_DATA(sys_call_table):
917	.long CSYM(sys_restart_syscall)	// 0
918	.long CSYM(sys_exit)
919	.long sys_fork_wrapper
920	.long CSYM(sys_read)
921	.long CSYM(sys_write)
922	.long CSYM(sys_open)		// 5
923	.long CSYM(sys_close)
924	.long CSYM(sys_waitpid)
925	.long CSYM(sys_creat)
926	.long CSYM(sys_link)
927	.long CSYM(sys_unlink)		// 10
928	.long sys_execve_wrapper
929	.long CSYM(sys_chdir)
930	.long CSYM(sys_time)
931	.long CSYM(sys_mknod)
932	.long CSYM(sys_chmod)		// 15
933	.long CSYM(sys_chown)
934	.long CSYM(sys_ni_syscall)	// was: break
935	.long CSYM(sys_ni_syscall)	// was: oldstat (aka stat)
936	.long CSYM(sys_lseek)
937	.long CSYM(sys_getpid)		// 20
938	.long CSYM(sys_mount)
939	.long CSYM(sys_oldumount)
940	.long CSYM(sys_setuid)
941	.long CSYM(sys_getuid)
942	.long CSYM(sys_stime)		// 25
943	.long CSYM(sys_ptrace)
944	.long CSYM(sys_alarm)
945	.long CSYM(sys_ni_syscall)	// was: oldfstat (aka fstat)
946	.long CSYM(sys_pause)
947	.long CSYM(sys_utime)		// 30
948	.long CSYM(sys_ni_syscall)	// was: stty
949	.long CSYM(sys_ni_syscall)	// was: gtty
950	.long CSYM(sys_access)
951	.long CSYM(sys_nice)
952	.long CSYM(sys_ni_syscall)	// 35, was: ftime
953	.long CSYM(sys_sync)
954	.long CSYM(sys_kill)
955	.long CSYM(sys_rename)
956	.long CSYM(sys_mkdir)
957	.long CSYM(sys_rmdir)		// 40
958	.long CSYM(sys_dup)
959	.long CSYM(sys_pipe)
960	.long CSYM(sys_times)
961	.long CSYM(sys_ni_syscall)	// was: prof
962	.long CSYM(sys_brk)		// 45
963	.long CSYM(sys_setgid)
964	.long CSYM(sys_getgid)
965	.long CSYM(sys_signal)
966	.long CSYM(sys_geteuid)
967	.long CSYM(sys_getegid)		// 50
968	.long CSYM(sys_acct)
969	.long CSYM(sys_umount)		// recycled never used phys()
970	.long CSYM(sys_ni_syscall)	// was: lock
971	.long CSYM(sys_ioctl)
972	.long CSYM(sys_fcntl)		// 55
973	.long CSYM(sys_ni_syscall)	// was: mpx
974	.long CSYM(sys_setpgid)
975	.long CSYM(sys_ni_syscall)	// was: ulimit
976	.long CSYM(sys_ni_syscall)
977	.long CSYM(sys_umask)		// 60
978	.long CSYM(sys_chroot)
979	.long CSYM(sys_ustat)
980	.long CSYM(sys_dup2)
981	.long CSYM(sys_getppid)
982	.long CSYM(sys_getpgrp)		// 65
983	.long CSYM(sys_setsid)
984	.long CSYM(sys_sigaction)
985	.long CSYM(sys_sgetmask)
986	.long CSYM(sys_ssetmask)
987	.long CSYM(sys_setreuid)	// 70
988	.long CSYM(sys_setregid)
989	.long sys_sigsuspend_wrapper
990	.long CSYM(sys_sigpending)
991	.long CSYM(sys_sethostname)
992	.long CSYM(sys_setrlimit)	// 75
993	.long CSYM(sys_getrlimit)
994	.long CSYM(sys_getrusage)
995	.long CSYM(sys_gettimeofday)
996	.long CSYM(sys_settimeofday)
997	.long CSYM(sys_getgroups)	// 80
998	.long CSYM(sys_setgroups)
999	.long CSYM(sys_select)
1000	.long CSYM(sys_symlink)
1001	.long CSYM(sys_ni_syscall)	// was: oldlstat (aka lstat)
1002	.long CSYM(sys_readlink)	// 85
1003	.long CSYM(sys_uselib)
1004	.long CSYM(sys_swapon)
1005	.long CSYM(sys_reboot)
1006	.long CSYM(old_readdir)
1007	.long CSYM(sys_mmap)		// 90
1008	.long CSYM(sys_munmap)
1009	.long CSYM(sys_truncate)
1010	.long CSYM(sys_ftruncate)
1011	.long CSYM(sys_fchmod)
1012	.long CSYM(sys_fchown)		// 95
1013	.long CSYM(sys_getpriority)
1014	.long CSYM(sys_setpriority)
1015	.long CSYM(sys_ni_syscall)	// was: profil
1016	.long CSYM(sys_statfs)
1017	.long CSYM(sys_fstatfs)		// 100
1018	.long CSYM(sys_ni_syscall)	// i386: ioperm
1019	.long CSYM(sys_socketcall)
1020	.long CSYM(sys_syslog)
1021	.long CSYM(sys_setitimer)
1022	.long CSYM(sys_getitimer)	// 105
1023	.long CSYM(sys_newstat)
1024	.long CSYM(sys_newlstat)
1025	.long CSYM(sys_newfstat)
1026	.long CSYM(sys_ni_syscall)	// was: olduname (aka uname)
1027	.long CSYM(sys_ni_syscall)	// 110, i386: iopl
1028	.long CSYM(sys_vhangup)
1029	.long CSYM(sys_ni_syscall)	// was: idle
1030	.long CSYM(sys_ni_syscall)	// i386: vm86old
1031	.long CSYM(sys_wait4)
1032	.long CSYM(sys_swapoff)		// 115
1033	.long CSYM(sys_sysinfo)
1034	.long CSYM(sys_ipc)
1035	.long CSYM(sys_fsync)
1036	.long sys_sigreturn_wrapper
1037	.long sys_clone_wrapper		// 120
1038	.long CSYM(sys_setdomainname)
1039	.long CSYM(sys_newuname)
1040	.long CSYM(sys_ni_syscall)	// i386: modify_ldt, m68k: cacheflush
1041	.long CSYM(sys_adjtimex)
1042	.long CSYM(sys_ni_syscall)	// 125 - sys_mprotect
1043	.long CSYM(sys_sigprocmask)
1044	.long CSYM(sys_ni_syscall)	// sys_create_module
1045	.long CSYM(sys_init_module)
1046	.long CSYM(sys_delete_module)
1047	.long CSYM(sys_ni_syscall)	// 130 - sys_get_kernel_syms
1048	.long CSYM(sys_quotactl)
1049	.long CSYM(sys_getpgid)
1050	.long CSYM(sys_fchdir)
1051	.long CSYM(sys_bdflush)
1052	.long CSYM(sys_sysfs)		// 135
1053	.long CSYM(sys_personality)
1054	.long CSYM(sys_ni_syscall)	// for afs_syscall
1055	.long CSYM(sys_setfsuid)
1056	.long CSYM(sys_setfsgid)
1057	.long CSYM(sys_llseek)		// 140
1058	.long CSYM(sys_getdents)
1059	.long CSYM(sys_select)		// for backward compat; remove someday
1060	.long CSYM(sys_flock)
1061	.long CSYM(sys_ni_syscall)	// sys_msync
1062	.long CSYM(sys_readv)		// 145
1063	.long CSYM(sys_writev)
1064	.long CSYM(sys_getsid)
1065	.long CSYM(sys_fdatasync)
1066	.long CSYM(sys_sysctl)
1067	.long CSYM(sys_ni_syscall)	// 150 - sys_mlock
1068	.long CSYM(sys_ni_syscall)	// sys_munlock
1069	.long CSYM(sys_ni_syscall)	// sys_mlockall
1070	.long CSYM(sys_ni_syscall)	// sys_munlockall
1071	.long CSYM(sys_sched_setparam)
1072	.long CSYM(sys_sched_getparam)	// 155
1073	.long CSYM(sys_sched_setscheduler)
1074	.long CSYM(sys_sched_getscheduler)
1075	.long CSYM(sys_sched_yield)
1076	.long CSYM(sys_sched_get_priority_max)
1077	.long CSYM(sys_sched_get_priority_min)	// 160
1078	.long CSYM(sys_sched_rr_get_interval)
1079	.long CSYM(sys_nanosleep)
1080	.long CSYM(sys_ni_syscall)	// sys_mremap
1081	.long CSYM(sys_setresuid)
1082	.long CSYM(sys_getresuid)	// 165
1083	.long CSYM(sys_ni_syscall)	// for vm86
1084	.long CSYM(sys_ni_syscall)	// sys_query_module
1085	.long CSYM(sys_poll)
1086	.long CSYM(sys_nfsservctl)
1087	.long CSYM(sys_setresgid)	// 170
1088	.long CSYM(sys_getresgid)
1089	.long CSYM(sys_prctl)
1090	.long sys_rt_sigreturn_wrapper
1091	.long CSYM(sys_rt_sigaction)
1092	.long CSYM(sys_rt_sigprocmask)	// 175
1093	.long CSYM(sys_rt_sigpending)
1094	.long CSYM(sys_rt_sigtimedwait)
1095	.long CSYM(sys_rt_sigqueueinfo)
1096	.long sys_rt_sigsuspend_wrapper
1097	.long CSYM(sys_pread64)		// 180
1098	.long CSYM(sys_pwrite64)
1099	.long CSYM(sys_lchown)
1100	.long CSYM(sys_getcwd)
1101	.long CSYM(sys_capget)
1102	.long CSYM(sys_capset)		// 185
1103	.long CSYM(sys_sigaltstack)
1104	.long CSYM(sys_sendfile)
1105	.long CSYM(sys_ni_syscall)	// streams1
1106	.long CSYM(sys_ni_syscall)	// streams2
1107	.long sys_vfork_wrapper		// 190
1108	.long CSYM(sys_ni_syscall)
1109	.long CSYM(sys_mmap2)
1110	.long CSYM(sys_truncate64)
1111	.long CSYM(sys_ftruncate64)
1112	.long CSYM(sys_stat64)		// 195
1113	.long CSYM(sys_lstat64)
1114	.long CSYM(sys_fstat64)
1115	.long CSYM(sys_fcntl64)
1116	.long CSYM(sys_getdents64)
1117	.long CSYM(sys_pivot_root)	// 200
1118	.long CSYM(sys_gettid)
1119	.long CSYM(sys_tkill)
1120sys_call_table_end:
1121C_END(sys_call_table)
1122