1/* $Id: entry.S,v 1.1.1.1 2008/10/15 03:26:01 james26_jang Exp $
2 *
3 *  linux/arch/cris/entry.S
4 *
5 *  Copyright (C) 2000, 2001, 2002 Axis Communications AB
6 *
7 *  Authors:	Bjorn Wesen (bjornw@axis.com)
8 *
9 *  $Log: entry.S,v $
10 *  Revision 1.1.1.1  2008/10/15 03:26:01  james26_jang
11 *  Initial.
12 *
13 *  Revision 1.1.1.1  2008/07/21 09:14:23  james26_jang
14 *  New UI, New QoS, New wireless driver(4.151.10.29), ipmonitor.
15 *
16 *  Revision 1.1.1.1  2008/07/02 14:38:30  james26_jang
17 *  4.100.10.29, New QoS and New UI.
18 *
19 *  Revision 1.1.1.1  2007/02/15 12:10:52  jiahao
20 *  initial update
21 *
22 *  Revision 1.1.1.1  2007/01/25 12:51:48  jiahao_jhou
23 *
24 *
25 *  Revision 1.1.1.1  2003/02/03 22:37:20  mhuang
26 *  LINUX_2_4 branch snapshot from linux-mips.org CVS
27 *
28 *  Revision 1.39  2002/04/24 00:46:45  bjornw
29 *  Added sys_tkill
30 *
31 *  Revision 1.38  2002/01/16 15:15:30  bjornw
32 *  Use a C-code compatible watchdog reset when NICE_DOGGY is enabled
33 *
34 *  Revision 1.37  2001/12/07 17:03:55  bjornw
35 *  Call a c-hook called watchdog_bite_hook instead of show_registers directly
36 *
37 *  Revision 1.36  2001/11/22 13:36:36  bjornw
38 *  * In ret_from_intr, check regs->dccr for usermode reentrance instead of
39 *    DCCR explicitely (because the latter might not reflect current reality)
40 *  * In mmu_bus_fault, set $r9 _after_ calling the C-code instead of before
41 *    since $r9 is call-clobbered and is potentially needed afterwards
42 *
43 *  Revision 1.35  2001/10/30 17:10:15  bjornw
44 *  Add some syscalls
45 *
46 *  Revision 1.34  2001/10/01 14:45:03  bjornw
47 *  Removed underscores and added register prefixes
48 *
49 *  Revision 1.33  2001/08/21 13:48:01  jonashg
50 *  Added fix by HP to avoid oops when doing a hard_reset_now.
51 *
52 *  Revision 1.32  2001/08/14 04:32:02  hp
53 *  In _resume, add comment why R9 is saved; don't sound like it's call-saved.
54 *
55 *  Revision 1.31  2001/07/25 16:07:42  bjornw
56 *  softirq_active/mask -> softirq_pending only
57 *
58 *  Revision 1.30  2001/07/05 01:03:32  hp
59 *  - include asm/errno.h to get ENOSYS.
60 *  - Use ENOSYS, not local constant LENOSYS; tweak comments.
61 *  - Explain why .include, not #include is used.
62 *  - Make oops-register-dump if watchdog bits and it's not expected.
63 *  - Don't jsr, use jump _hard_reset_now, and skip spurious nop.
64 *  - Use correct section attribute for section .rodata.
65 *  - Adjust sys_ni_syscall fill number.
66 *
67 *  Revision 1.29  2001/06/25 14:07:00  hp
68 *  	Fix review comment.
69 *  	* head.S: Use IO_STATE, IO_FIELD and IO_MASK constructs instead of
70 *  	magic numbers.  Add comment that -traditional must not be used.
71 *  	* entry.S (SYMBOL_NAME): Change redefinition to use ## concatenation.
72 *  	Correct and update comment.
73 *  	* Makefile (.S.o): Don't use -traditional.  Add comment why the
74 *  	toplevel rule can't be used (now that there's a reason).
75 *
76 *  Revision 1.28  2001/06/21 02:00:40  hp
77 *  	* entry.S: Include asm/unistd.h.
78 *  	(_sys_call_table): Use section .rodata, not .data.
79 *  	(_kernel_thread): Move from...
80 *  	* process.c: ... here.
81 *  	* entryoffsets.c (VAL): Break out from...
82 *  	(OF): Use VAL.
83 *  	(LCLONE_VM): New asmified value from CLONE_VM.
84 *
85 *  Revision 1.27  2001/05/29 11:25:27  markusl
86 *  In case of "spurious_interrupt", do hard_reset instead of hanging system in a loop...
87 *
88 *  Revision 1.26  2001/05/15 15:46:03  bjornw
89 *  Include config.h now that we use some CONFIG_ options
90 *
91 *  Revision 1.25  2001/05/15 05:38:47  hp
92 *  Tweaked code in _ret_from_sys_call
93 *
94 *  Revision 1.24  2001/05/15 05:27:49  hp
95 *  Save r9 in r1 over function call rather than on stack.
96 *
97 *  Revision 1.23  2001/05/15 05:10:00  hp
98 *  Generate entry.S structure offsets from C
99 *
100 *  Revision 1.22  2001/04/17 13:58:39  orjanf
101 *  * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB.
102 *
103 *  Revision 1.21  2001/04/17 11:33:29  orjanf
104 *  Updated according to review:
105 *  * Included asm/sv_addr_ag.h to get macro for internal register.
106 *  * Corrected comment regarding system call argument passing.
107 *  * Removed comment about instruction being in a delay slot.
108 *  * Added comment about SYMBOL_NAME macro.
109 *
110 *  Revision 1.20  2001/04/12 08:51:07  hp
111 *  - Add entry for sys_fcntl64.  In fact copy last piece from i386 including ...
112 *  - .rept to fill table to safe state with sys_ni_syscall.
113 *
114 *  Revision 1.19  2001/04/04 09:43:32  orjanf
115 *  * Moved do_sigtrap from traps.c to entry.S.
116 *  * LTASK_PID need not be global anymore.
117 *
118 *  Revision 1.18  2001/03/26 09:25:02  markusl
119 *  Updated after review, should now handle USB interrupts correctly.
120 *
121 *  Revision 1.17  2001/03/21 16:12:55  bjornw
122 *  * Always make room for the cpu status record in the frame, in order to
123 *    use the same framelength and layout for both mmu busfaults and normal
124 *    irqs. No need to check for the explicit CRIS_FRAME_FIXUP type anymore.
125 *  * Fixed bug with using addq for popping the stack in the epilogue - it
126 *    destroyed the flag register. Use instructions that don't affect the
127 *    flag register instead.
128 *  * Removed write to R_PORT_PA_DATA during spurious_interrupt
129 *
130 *  Revision 1.16  2001/03/20 19:43:02  bjornw
131 *  * Get rid of esp0 setting
132 *  * Give a 7th argument to a systemcall - the stackframe
133 *
134 *  Revision 1.15  2001/03/05 13:14:30  bjornw
135 *  Spelling fix
136 *
137 *  Revision 1.14  2001/02/23 08:36:36  perf
138 *  New ABI; syscallnr=r9, arg5=mof, arg6=srp.
139 *  Corrected tracesys call check.
140 *
141 *  Revision 1.13  2001/02/15 08:40:55  perf
142 *  H-P by way of perf;
143 *  - (_system_call): Don't read system call function address into r1.
144 *  - (RBFExit): There is no such thing as a null pop.  Adjust sp by addq.
145 *  - (_system_call): Don't use r10 and don't save and restore it.
146 *  - (THREAD_ESP0): New constant.
147 *  - (_system_call): Inline set_esp0.
148 *
149 *  Revision 1.12  2001/01/31 17:56:25  orjanf
150 *  Added definition of LTASK_PID and made it global.
151 *
152 *  Revision 1.11  2001/01/10 21:13:29  bjornw
153 *  SYMBOL_NAME is defined incorrectly for the compiler options we currently use
154 *
155 *  Revision 1.10  2000/12/18 23:47:56  bjornw
156 *  * Added syscall trace support (ptrace), completely untested of course
157 *  * Removed redundant check for NULL entries in syscall_table
158 *
159 *  Revision 1.9  2000/11/21 16:40:51  bjornw
160 *  * New frame type used when an SBFS frame needs to be popped without
161 *    actually restarting the instruction
162 *  * Enable interrupts in signal_return (they did so in x86, I hope it's a good
163 *    idea)
164 *
165 *  Revision 1.8  2000/11/17 16:53:35  bjornw
166 *  Added detection of frame-type in Rexit, so that mmu_bus_fault can
167 *  use ret_from_intr in the return-path to check for signals (like SEGV)
168 *  and other foul things that might have occurred during the fault.
169 *
170 *  Revision 1.7  2000/10/06 15:04:28  bjornw
171 *  Include mof in register savings
172 *
173 *  Revision 1.6  2000/09/12 16:02:44  bjornw
174 *  Linux-2.4.0-test7 derived updates
175 *
176 *  Revision 1.5  2000/08/17 15:35:15  bjornw
177 *  2.4.0-test6 changed local_irq_count and friends API
178 *
179 *  Revision 1.4  2000/08/02 13:59:30  bjornw
180 *  Removed olduname and uname from the syscall list
181 *
182 *  Revision 1.3  2000/07/31 13:32:58  bjornw
183 *  * Export ret_from_intr
184 *  * _resume updated (prev/last tjohejsan)
185 *  * timer_interrupt obsolete
186 *  * SIGSEGV detection in mmu_bus_fault temporarily disabled
187 *
188 *
189 */
190
191/*
192 * entry.S contains the system-call and fault low-level handling routines.
193 *
194 * NOTE: This code handles signal-recognition, which happens every time
195 * after a timer-interrupt and after each system call.
196 *
197 * Stack layout in 'ret_from_system_call':
198 * 	ptrace needs to have all regs on the stack.
199 *	if the order here is changed, it needs to be
200 *	updated in fork.c:copy_process, signal.c:do_signal,
201 *	ptrace.c and ptrace.h
202 *
203 */
204
205#include <linux/config.h>
206#include <linux/linkage.h>
207#include <linux/sys.h>
208#include <asm/unistd.h>
209#include <asm/sv_addr_ag.h>
210#include <asm/errno.h>
211
212	;; functions exported from this file
213
214	.globl system_call
215	.globl ret_from_intr
216	.globl ret_from_sys_call
217	.globl resume
218	.globl multiple_interrupt
219	.globl hwbreakpoint
220	.globl IRQ1_interrupt
221	.globl timer_interrupt
222	.globl timer_shortcut
223	.globl spurious_interrupt
224	.globl hw_bp_trigs
225	.globl mmu_bus_fault
226	.globl do_sigtrap
227	.globl gdb_handle_breakpoint
228
229	.globl sys_call_table
230
231	;; Get values and offsets into various structs.  The file isn't
232	;; suitable for consumption by the preprocessor, so don't use
233	;; #include.
234	.include "entryoffsets.s"
235
236	;; process bits for ptrace.  FIXME: Should be in a header file.
237
238PT_TRACESYS_BIT	  = 1
239
240	;; below are various parts of system_call which are not in the fast-path
241
242	;; handle software irqs
243
244_handle_softirq:
245	move.d	$r9, $r1
246	jsr	do_softirq	; call the C routine for softirq handling
247	move.d	$r1, $r9
248
249	;; fall-through
250
251ret_from_intr:
252	;; check for resched only if we're going back to user-mode
253	;; this test matches the user_regs(regs) macro
254	;; we cannot simply test $dccr, because that does not necessarily
255	;; reflect what mode we'll return into.
256
257	move.d	[$sp + LDCCR], $r0; regs->dccr
258	btstq	8, $r0		; U-flag
259	bpl	_Rexit		; go back directly
260	nop
261	ba	_ret_with_reschedule  ; go back but check schedule and signals first
262	nop
263
264_reschedule:
265	;; keep r9 intact
266	move.d	$r9, $r1
267	jsr	schedule
268	ba	ret_from_sys_call
269	move.d	$r1, $r9
270
271	;; return but call do_signal first
272_signal_return:
273	ei			; we can get here from an interrupt
274	move.d	$r9, $r10	; do_signals syscall/irq param
275	moveq	0, $r11		; oldset param - 0 in this case
276	move.d	$sp, $r12	; another argument to do_signal (the regs param)
277	jsr	do_signal	; arch/cris/kernel/signal.c
278	ba	_Rexit
279	nop
280
281	;; The system_call is called by a BREAK instruction, which works like
282	;; an interrupt call but it stores the return PC in BRP instead of IRP.
283	;; Since we dont really want to have two epilogues (one for system calls
284	;; and one for interrupts) we push the contents of BRP instead of IRP in the
285	;; system call prologue, to make it look like an ordinary interrupt on the
286	;; stackframe.
287	;;
288	;; Since we can't have system calls inside interrupts, it should not matter
289	;; that we don't stack IRP.
290	;;
291	;; In r9 we have the wanted syscall number. Arguments come in r10,r11,r12,r13,mof,srp
292	;;
293	;; This function looks on the _surface_ like spaghetti programming, but it's
294	;; really designed so that the fast-path does not force cache-loading of non-used
295	;; instructions. Only the non-common cases cause the outlined code to run..
296
297system_call:
298	;; stack-frame similar to the irq heads, which is reversed in ret_from_sys_call
299	move	$brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame
300	push	$srp
301	push	$dccr
302	push	$mof
303	subq	14*4, $sp		; make room for r0-r13
304	movem	$r13, [$sp]	; push r0-r13
305	push	$r10		; push orig_r10
306	clear.d [$sp=$sp-4]	; frametype == 0, normal stackframe
307
308	movs.w	-ENOSYS, $r0
309	move.d	$r0, [$sp+LR10]	; put the default return value in r10 in the frame
310
311	;; check if this process is syscall-traced
312
313	movs.w	-8192, $r0	; THREAD_SIZE == 8192
314	and.d	$sp, $r0
315
316	move.d	[$r0+LTASK_PTRACE], $r0
317	btstq	PT_TRACESYS_BIT, $r0
318	bmi	_tracesys
319	nop
320
321	;; check for sanity in the requested syscall number
322
323	cmpu.w	NR_syscalls, $r9
324	bcc	ret_from_sys_call
325	lslq	2, $r9		;  multiply by 4, in the delay slot
326
327	;; as a bonus 7th parameter, we give the location on the stack
328	;; of the register structure itself. some syscalls need this.
329
330	push	$sp
331
332	;; the parameter carrying registers r10, r11, r12 and 13 are intact.
333	;; the fifth and sixth parameters (if any) was in mof and srp
334	;; respectively, and we need to put them on the stack.
335
336	push	$srp
337	push	$mof
338
339	jsr	[$r9+sys_call_table]	; actually do the system call
340	addq	3*4, $sp		; pop the mof, srp and regs parameters
341	move.d	$r10, [$sp+LR10]	; save the return value
342
343	moveq	1, $r9		; "parameter" to ret_from_sys_call to show it was a sys call
344
345	;; fall through into ret_from_sys_call to return
346
347ret_from_sys_call:
348	;; r9 is a parameter - if 1, we came from a syscall, if 0, from an irq
349
350	;; check if any bottom halves need service
351
352	test.d	[irq_stat]	       ; softirq_pending
353	bne	_handle_softirq
354	nop
355
356_ret_with_reschedule:
357	;; first get the current task-struct pointer (see top for defs)
358
359	move.d	$sp, $r0
360	and.d	-8192, $r0	; THREAD_SIZE == 8192
361
362	;; see if we want to reschedule into another process
363
364	test.d	[$r0+LTASK_NEEDRESCHED]
365	bne	_reschedule
366	nop
367
368	;; see if we need to run signal checks (important that r9 is intact here)
369
370	test.d	[$r0+LTASK_SIGPENDING]
371	bne	_signal_return
372	nop
373
374_Rexit:
375	;; this epilogue MUST match the prologues in multiple_interrupt, irq.h and ptregs.h
376	pop	$r10		; frametype
377	bne	_RBFexit	; was not CRIS_FRAME_NORMAL, handle otherwise
378	addq	4, $sp		; skip orig_r10, in delayslot
379	movem	[$sp+], $r13	; registers r0-r13
380	pop	$mof		; multiply overflow register
381	pop	$dccr		; condition codes
382	pop	$srp		; subroutine return pointer
383	;; now we have a 4-word SBFS frame which we do not want to restore
384	;; using RBF since it was not stacked with SBFS. instead we would like to
385	;; just get the PC value to restart it with, and skip the rest of
386	;; the frame.
387	;; Also notice that it's important to use instructions here that
388	;; keep the interrupts disabled (since we've already popped DCCR)
389	move	[$sp=$sp+16], $p8; pop the SBFS frame from the sp
390	jmpu	[$sp-16]	; return through the irp field in the sbfs frame
391
392_RBFexit:
393	movem	[$sp+], $r13	; registers r0-r13, in delay slot
394	pop	$mof		; multiply overflow register
395	pop	$dccr		; condition codes
396	pop	$srp		; subroutine return pointer
397	rbf	[$sp+]		; return by popping the CPU status
398
399_tracesys:
400	;; this first invocation of syscall_trace _requires_ that
401	;; LR10 in the frame contains -ENOSYS (as is set in the beginning
402	;; of system_call).
403
404	jsr	syscall_trace
405
406	;; now we should more or less do the same things as in the system_call
407	;; but since our argument regs got clobbered during syscall_trace and
408	;; because syscall_trace might want to alter them, we need to reload them
409	;; from the stack-frame as we use them.
410
411	;; check for sanity in the requested syscall number
412
413	move.d	[$sp+LR9], $r9
414	movs.w	-ENOSYS, $r10
415	cmpu.w	NR_syscalls, $r9
416	bcc	1f
417	lslq	2, $r9		;  multiply by 4, in the delay slot
418
419	;; read the system call vector entry into r9
420
421	move.d	[$r9+sys_call_table], $r9
422
423	;; restore r10, r11, r12, r13, mof and srp into the needed registers
424
425	move.d	[$sp+LORIG_R10], $r10  ; LR10 is already filled with -ENOSYS.
426	move.d	[$sp+LR11],      $r11
427	move.d	[$sp+LR12],      $r12
428	move.d	[$sp+LR13],      $r13
429	move	[$sp+LMOF],      $mof
430	move	[$sp+LSRP],      $srp
431
432	;; as a bonus 7th parameter, we give the location on the stack
433	;; of the register structure itself. some syscalls need this.
434
435	push	$sp
436
437	;; the fifth and sixth parameters needs to be put on the stack for
438	;; the system call to find them
439
440	push	$srp
441	push	$mof
442
443	jsr	$r9		; actually call the system-call
444	addq	3*4, $sp	; pop the srp, mof and regs parameters
445
4461:	move.d	$r10, [$sp+LR10]; save the return value
447
448	;; second call of syscall_trace, to let it grab the results
449
450	jsr	syscall_trace
451
452	moveq	1, $r9		; "parameter" to ret_from_sys_call to show it was a sys call
453	ba	ret_from_sys_call
454	nop
455
456	;; resume performs the actual task-switching, by switching stack pointers
457	;; input arguments: r10 = prev, r11 = next, r12 = thread offset in task struct
458	;; returns old current in r10
459	;;
460	;; TODO:  see the i386 version. The switch_to which calls resume in our version
461	;;        could really be an inline asm of this.
462
463resume:
464	push	$srp		         ; we keep the old/new PC on the stack
465	add.d	$r12, $r10		 ; r10 = current tasks tss
466	move	$dccr, [$r10+LTHREAD_DCCR] ; save irq enable state
467	di
468
469	move	$usp, [$r10+LTHREAD_USP] ; save user-mode stackpointer
470
471	;; See copy_thread for the reason why register R9 is saved.
472	subq	10*4, $sp
473	movem	$r9, [$sp]		 ; save non-scratch registers and R9.
474
475	move.d	$sp, [$r10+LTHREAD_KSP]	 ; save the kernel stack pointer for the old task
476	move.d	$sp, $r10		 ; return last running task in r10
477	and.d   -8192, $r10	         ; get task ptr from stackpointer
478	add.d	$r12, $r11		 ; find the new tasks tss
479	move.d	[$r11+LTHREAD_KSP], $sp	 ; switch into the new stackframe by restoring kernel sp
480
481	movem	[$sp+], $r9		 ; restore non-scratch registers and R9.
482
483	move	[$r11+LTHREAD_USP], $usp ; restore user-mode stackpointer
484
485	move	[$r11+LTHREAD_DCCR], $dccr ; restore irq enable status
486	jump	[$sp+]		         ; restore PC
487
488	;; This is the MMU bus fault handler.
489	;; It needs to stack the CPU status and overall is different
490	;; from the other interrupt handlers.
491
492mmu_bus_fault:
493	sbfs	[$sp=$sp-16]	; push the internal CPU status
494	;; the first longword in the sbfs frame was the interrupted PC
495	;; which fits nicely with the "IRP" slot in pt_regs normally used to
496	;; contain the return address. used by Oops to print kernel errors..
497	push	$srp		; make a stackframe similar to pt_regs
498	push	$dccr
499	push	$mof
500	di
501	subq	14*4, $sp
502	movem	$r13, [$sp]
503	push	$r10		; dummy orig_r10
504	moveq	1, $r10
505	push	$r10		; frametype == 1, BUSFAULT frame type
506
507	move.d	$sp, $r10	; pt_regs argument to handle_mmu_bus_fault
508
509	jsr	handle_mmu_bus_fault  ; in arch/cris/mm/fault.c
510
511	;; now we need to return through the normal path, we cannot just
512	;; do the RBFexit since we might have killed off the running
513	;; process due to a SEGV, scheduled due to a page blocking or
514	;; whatever.
515
516	moveq	0, $r9		; busfault is equivalent to an irq
517
518	ba	ret_from_intr
519	nop
520
521	;; special handlers for breakpoint and NMI
522hwbreakpoint:
523	push	$dccr
524	di
525	push	$r10
526	push	$r11
527	move.d	[hw_bp_trig_ptr],$r10
528	move.d	[$r10],$r11
529	cmp.d	42,$r11
530	beq	1f
531	nop
532	move	$brp,$r11
533	move.d	$r11,[$r10+]
534	move.d	$r10,[hw_bp_trig_ptr]
5351:	pop	$r11
536	pop	$r10
537	pop	$dccr
538	retb
539	nop
540
541IRQ1_interrupt:
542
543#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
544;; If we receive a watchdog interrupt while it is not expected, then set
545;; up a canonical frame and dump register contents before dying.
546
547	;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!
548	move	$brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame
549	push	$srp
550	push	$dccr
551	push	$mof
552	di
553	subq	14*4, $sp
554	movem	$r13, [$sp]
555	push	$r10		; push orig_r10
556	clear.d [$sp=$sp-4]	; frametype == 0, normal frame
557
558;; We don't check that we actually were bit by the watchdog as opposed to
559;; an external NMI, since there is currently no handler for external NMI.
560
561;; Check if we're waiting for reset to happen, as signalled by
562;; hard_reset_now setting cause_of_death to a magic value.  If so, just
563;; get stuck until reset happens.
564	.comm	cause_of_death, 4	;; Don't declare this anywhere.
565	move.d	[cause_of_death], $r10
566	cmp.d	0xbedead, $r10
567_killed_by_death:
568	beq	_killed_by_death
569	nop
570
571;; We'll see this in ksymoops dumps.
572Watchdog_bite:
573
574#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
575	;; We just restart the watchdog here to be sure we dont get
576	;; hit while printing the watchdogmsg below
577	;; This restart is compatible with the rest of the C-code, so
578	;; the C-code can keep restarting the watchdog after this point.
579	;; The non-NICE_DOGGY code below though, disables the possibility
580	;; to restart since it changes the watchdog key, to avoid any
581	;; buggy loops etc. keeping the watchdog alive after this.
582	jsr	reset_watchdog
583#else
584;; We need to extend the 3.3ms after the NMI at watchdog bite, so we have
585;; time for an oops-dump over a 115k2 serial wire.  Another 100ms should do.
586
587;; Change the watchdog key to an arbitrary 3-bit value and restart the
588;; watchdog.
589#define WD_INIT 2
590	moveq	  IO_FIELD (R_WATCHDOG, key, WD_INIT), $r10
591	move.d	R_WATCHDOG, $r11
592
593	move.d	$r10, [$r11]
594	moveq	  IO_FIELD (R_WATCHDOG, key,				\
595			    IO_EXTRACT (R_WATCHDOG, key,		\
596					IO_MASK (R_WATCHDOG, key))	\
597			    ^ WD_INIT)					\
598		| IO_STATE (R_WATCHDOG, enable, start), $r10
599	move.d	$r10, [$r11]
600#endif
601
602;; Note that we don't do "setf m" here (or after two necessary NOPs),
603;; since *not* doing that saves us from re-entrancy checks.  We don't want
604;; to get here again due to possible subsequent NMIs; we want the watchdog
605;; to reset us.
606
607	move.d	_watchdogmsg,$r10
608	jsr	printk
609
610	move.d	$sp, $r10
611	jsr	watchdog_bite_hook
612
613;; This nop is here so we see the "Watchdog_bite" label in ksymoops dumps
614;; rather than "spurious_interrupt".
615	nop
616;; At this point we drop down into spurious_interrupt, which will do a
617;; hard reset.
618
619	.section .rodata,"a"
620_watchdogmsg:
621	.ascii	"Oops: bitten by watchdog\n\0"
622	.previous
623
624#endif /* CONFIG_ETRAX_WATCHDOG and not CONFIG_SVINTO_SIM */
625
626spurious_interrupt:
627	di
628	jump hard_reset_now
629
630	;; this handles the case when multiple interrupts arrive at the same time
631	;; we jump to the first set interrupt bit in a priority fashion
632	;; the hardware will call the unserved interrupts after the handler finishes
633
634multiple_interrupt:
635	;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!
636	move	$irp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame
637	push	$srp
638	push	$dccr
639	push	$mof
640	di
641	subq	14*4, $sp
642	movem	$r13, [$sp]
643	push	$r10		; push orig_r10
644	clear.d [$sp=$sp-4]	; frametype == 0, normal frame
645
646	move.d	irq_shortcuts + 8, $r1
647	moveq	2, $r2		; first bit we care about is the timer0 irq
648	move.d	[R_VECT_MASK_RD], $r0; read the irq bits that triggered the multiple irq
6491:
650	btst	$r2, $r0	; check for the irq given by bit r2
651	bmi	_do_shortcut	; actually do the shortcut
652	nop
653	addq	1, $r2		; next vector bit
654	addq	4, $r1		; next vector
655	cmp.b	32, $r2
656	bne	1b	; process all irq's up to and including number 31
657	nop
658
659	;; strange, we didn't get any set vector bits.. oh well, just return
660
661	ba	_Rexit
662	nop
663
664_do_shortcut:
665	test.d	[$r1]
666	beq	_Rexit
667	nop
668	jump	[$r1]		; jump to the irq handlers shortcut
669
670do_sigtrap:
671	;;
672	;; SIGTRAP the process that executed the break instruction.
673	;; Make a frame that Rexit in entry.S expects.
674	;;
675	move	$brp, [$sp=$sp-16]	; Push BRP while faking a cpu status record.
676	push	$srp			; Push subroutine return pointer.
677	push	$dccr			; Push condition codes.
678	push	$mof			; Push multiply overflow reg.
679	di				; Need to disable irq's at this point.
680	subq	14*4, $sp		; Make room for r0-r13.
681	movem	$r13, [$sp]		; Push the r0-r13 registers.
682	push	$r10			; Push orig_r10.
683	clear.d	[$sp=$sp-4]		; Frametype - this is a normal stackframe.
684
685	movs.w	-8192,$r9		; THREAD_SIZE == 8192
686	and.d	$sp, $r9
687	move.d	[$r9+LTASK_PID], $r10	; current->pid as arg1.
688	moveq	5, $r11			; SIGTRAP as arg2.
689	jsr	sys_kill
690	jump	ret_from_intr		; Use the return routine for interrupts.
691
692gdb_handle_breakpoint:
693	push	$dccr
694	push	$r0
695#ifdef CONFIG_ETRAX_KGDB
696	move	$dccr, $r0		; U-flag not affected by previous insns.
697	btstq	8, $r0			; Test the U-flag.
698	bmi	_ugdb_handle_breakpoint	; Go to user mode debugging.
699	nop				; Empty delay slot (cannot pop r0 here).
700	pop	$r0			; Restore r0.
701	ba	kgdb_handle_breakpoint	; Go to kernel debugging.
702	pop	$dccr			; Restore dccr in delay slot.
703#endif
704
705_ugdb_handle_breakpoint:
706	move	$brp, $r0		; Use r0 temporarily for calculation.
707	subq	2, $r0			; Set to address of previous instruction.
708	move	$r0, $brp
709	pop	$r0			; Restore r0.
710	ba	do_sigtrap		; SIGTRAP the offending process.
711	pop	$dccr			; Restore dccr in delay slot.
712
713	.data
714
715hw_bp_trigs:
716	.space 64*4
717hw_bp_trig_ptr:
718	.dword hw_bp_trigs
719
720/*
721 * This is the mechanism for creating a new kernel thread.
722 *
723 * NOTE! Only a kernel-only process (i.e. the swapper or direct descendants
724 * who haven't done an "execve()") should use this: it will work within
725 * a system call from a "real" process, but the process memory space will
726 * not be free'd until both the parent and the child have exited.
727 *
728 * This *can* be done in C with an single-asm-wrapped-in-a-function, but you
729 * get more or less gross code.  The safer you make the asm-constraints,
730 * the grosser the code, at least with the gcc version in cris-dist-1.13.
731 */
732
733/* int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */
734/*                   r10                r11         r12  */
735
736	.text
737	.global kernel_thread
738kernel_thread:
739
740	/* Save ARG for later.  */
741	move.d $r11, $r13
742
743	/* r11 is argument 2 to clone, the flags */
744	move.d  $r12, $r11
745	or.w	LCLONE_VM, $r11
746
747	/* Save FN for later.  */
748	move.d	$r10, $r12
749
750	/* r9 contains syscall number, to sys_clone */
751	movu.w	__NR_clone, $r9
752
753	/* r10 is argument 1 to clone */
754	clear.d	$r10
755
756	/* call sys_clone, this will fork */
757	break	13
758
759	/* parent or child? child returns 0 here. */
760	test.d	$r10
761
762	/* jump if parent */
763	bne	1f
764	nop              /* delay slot */
765
766	/* set argument to function to call */
767	move.d	$r13, $r10
768
769	/* call specified function */
770	jsr	$r12
771	/* If we ever return from the function, something bad has happened.  */
772
773	/* r9 is sys_exit syscall number */
774	movu.w	__NR_exit, $r9
775
776	/* Give a really bad exit-value */
777	moveq	-1, $r10
778
779	/* call sys_exit, killing the child */
780	break	13
7811:
782	ret
783	nop              /* delay slot */
784
785	.section .rodata,"a"
786sys_call_table:
787	.long SYMBOL_NAME(sys_ni_syscall)	/* 0  -  old "setup()" system call*/
788	.long SYMBOL_NAME(sys_exit)
789	.long SYMBOL_NAME(sys_fork)
790	.long SYMBOL_NAME(sys_read)
791	.long SYMBOL_NAME(sys_write)
792	.long SYMBOL_NAME(sys_open)		/* 5 */
793	.long SYMBOL_NAME(sys_close)
794	.long SYMBOL_NAME(sys_waitpid)
795	.long SYMBOL_NAME(sys_creat)
796	.long SYMBOL_NAME(sys_link)
797	.long SYMBOL_NAME(sys_unlink)		/* 10 */
798	.long SYMBOL_NAME(sys_execve)
799	.long SYMBOL_NAME(sys_chdir)
800	.long SYMBOL_NAME(sys_time)
801	.long SYMBOL_NAME(sys_mknod)
802	.long SYMBOL_NAME(sys_chmod)		/* 15 */
803	.long SYMBOL_NAME(sys_lchown16)
804	.long SYMBOL_NAME(sys_ni_syscall)	/* old break syscall holder */
805	.long SYMBOL_NAME(sys_stat)
806	.long SYMBOL_NAME(sys_lseek)
807	.long SYMBOL_NAME(sys_getpid)		/* 20 */
808	.long SYMBOL_NAME(sys_mount)
809	.long SYMBOL_NAME(sys_oldumount)
810	.long SYMBOL_NAME(sys_setuid16)
811	.long SYMBOL_NAME(sys_getuid16)
812	.long SYMBOL_NAME(sys_stime)		/* 25 */
813	.long SYMBOL_NAME(sys_ptrace)
814	.long SYMBOL_NAME(sys_alarm)
815	.long SYMBOL_NAME(sys_fstat)
816	.long SYMBOL_NAME(sys_pause)
817	.long SYMBOL_NAME(sys_utime)		/* 30 */
818	.long SYMBOL_NAME(sys_ni_syscall)	/* old stty syscall holder */
819	.long SYMBOL_NAME(sys_ni_syscall)	/* old gtty syscall holder */
820	.long SYMBOL_NAME(sys_access)
821	.long SYMBOL_NAME(sys_nice)
822	.long SYMBOL_NAME(sys_ni_syscall)	/* 35  old ftime syscall holder */
823	.long SYMBOL_NAME(sys_sync)
824	.long SYMBOL_NAME(sys_kill)
825	.long SYMBOL_NAME(sys_rename)
826	.long SYMBOL_NAME(sys_mkdir)
827	.long SYMBOL_NAME(sys_rmdir)		/* 40 */
828	.long SYMBOL_NAME(sys_dup)
829	.long SYMBOL_NAME(sys_pipe)
830	.long SYMBOL_NAME(sys_times)
831	.long SYMBOL_NAME(sys_ni_syscall)	/* old prof syscall holder */
832	.long SYMBOL_NAME(sys_brk)		/* 45 */
833	.long SYMBOL_NAME(sys_setgid16)
834	.long SYMBOL_NAME(sys_getgid16)
835	.long SYMBOL_NAME(sys_signal)
836	.long SYMBOL_NAME(sys_geteuid16)
837	.long SYMBOL_NAME(sys_getegid16)	/* 50 */
838	.long SYMBOL_NAME(sys_acct)
839	.long SYMBOL_NAME(sys_umount)		/* recycled never used phys() */
840	.long SYMBOL_NAME(sys_ni_syscall)	/* old lock syscall holder */
841	.long SYMBOL_NAME(sys_ioctl)
842	.long SYMBOL_NAME(sys_fcntl)		/* 55 */
843	.long SYMBOL_NAME(sys_ni_syscall)	/* old mpx syscall holder */
844	.long SYMBOL_NAME(sys_setpgid)
845	.long SYMBOL_NAME(sys_ni_syscall)	/* old ulimit syscall holder */
846	.long SYMBOL_NAME(sys_ni_syscall)       /* old sys_olduname holder */
847	.long SYMBOL_NAME(sys_umask)		/* 60 */
848	.long SYMBOL_NAME(sys_chroot)
849	.long SYMBOL_NAME(sys_ustat)
850	.long SYMBOL_NAME(sys_dup2)
851	.long SYMBOL_NAME(sys_getppid)
852	.long SYMBOL_NAME(sys_getpgrp)		/* 65 */
853	.long SYMBOL_NAME(sys_setsid)
854	.long SYMBOL_NAME(sys_sigaction)
855	.long SYMBOL_NAME(sys_sgetmask)
856	.long SYMBOL_NAME(sys_ssetmask)
857	.long SYMBOL_NAME(sys_setreuid16)	/* 70 */
858	.long SYMBOL_NAME(sys_setregid16)
859	.long SYMBOL_NAME(sys_sigsuspend)
860	.long SYMBOL_NAME(sys_sigpending)
861	.long SYMBOL_NAME(sys_sethostname)
862	.long SYMBOL_NAME(sys_setrlimit)	/* 75 */
863	.long SYMBOL_NAME(sys_old_getrlimit)
864	.long SYMBOL_NAME(sys_getrusage)
865	.long SYMBOL_NAME(sys_gettimeofday)
866	.long SYMBOL_NAME(sys_settimeofday)
867	.long SYMBOL_NAME(sys_getgroups16)	/* 80 */
868	.long SYMBOL_NAME(sys_setgroups16)
869	.long SYMBOL_NAME(sys_select)           /* was old_select in Linux/E100 */
870	.long SYMBOL_NAME(sys_symlink)
871	.long SYMBOL_NAME(sys_lstat)
872	.long SYMBOL_NAME(sys_readlink)		/* 85 */
873	.long SYMBOL_NAME(sys_uselib)
874	.long SYMBOL_NAME(sys_swapon)
875	.long SYMBOL_NAME(sys_reboot)
876	.long SYMBOL_NAME(old_readdir)
877	.long SYMBOL_NAME(old_mmap)		/* 90 */
878	.long SYMBOL_NAME(sys_munmap)
879	.long SYMBOL_NAME(sys_truncate)
880	.long SYMBOL_NAME(sys_ftruncate)
881	.long SYMBOL_NAME(sys_fchmod)
882	.long SYMBOL_NAME(sys_fchown16)		/* 95 */
883	.long SYMBOL_NAME(sys_getpriority)
884	.long SYMBOL_NAME(sys_setpriority)
885	.long SYMBOL_NAME(sys_ni_syscall)	/* old profil syscall holder */
886	.long SYMBOL_NAME(sys_statfs)
887	.long SYMBOL_NAME(sys_fstatfs)		/* 100 */
888	.long SYMBOL_NAME(sys_ni_syscall)       /* sys_ioperm in i386 */
889	.long SYMBOL_NAME(sys_socketcall)
890	.long SYMBOL_NAME(sys_syslog)
891	.long SYMBOL_NAME(sys_setitimer)
892	.long SYMBOL_NAME(sys_getitimer)	/* 105 */
893	.long SYMBOL_NAME(sys_newstat)
894	.long SYMBOL_NAME(sys_newlstat)
895	.long SYMBOL_NAME(sys_newfstat)
896	.long SYMBOL_NAME(sys_ni_syscall)	/* old sys_uname holder */
897	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_iopl in i386 */
898	.long SYMBOL_NAME(sys_vhangup)
899	.long SYMBOL_NAME(sys_ni_syscall)	/* old "idle" system call */
900	.long SYMBOL_NAME(sys_ni_syscall)	/* vm86old in i386 */
901	.long SYMBOL_NAME(sys_wait4)
902	.long SYMBOL_NAME(sys_swapoff)		/* 115 */
903	.long SYMBOL_NAME(sys_sysinfo)
904	.long SYMBOL_NAME(sys_ipc)
905	.long SYMBOL_NAME(sys_fsync)
906	.long SYMBOL_NAME(sys_sigreturn)
907	.long SYMBOL_NAME(sys_clone)		/* 120 */
908	.long SYMBOL_NAME(sys_setdomainname)
909	.long SYMBOL_NAME(sys_newuname)
910	.long SYMBOL_NAME(sys_ni_syscall)	/* TODO sys_modify_ldt - do something ?*/
911	.long SYMBOL_NAME(sys_adjtimex)
912	.long SYMBOL_NAME(sys_mprotect)		/* 125 */
913	.long SYMBOL_NAME(sys_sigprocmask)
914	.long SYMBOL_NAME(sys_create_module)
915	.long SYMBOL_NAME(sys_init_module)
916	.long SYMBOL_NAME(sys_delete_module)
917	.long SYMBOL_NAME(sys_get_kernel_syms)	/* 130 */
918	.long SYMBOL_NAME(sys_quotactl)
919	.long SYMBOL_NAME(sys_getpgid)
920	.long SYMBOL_NAME(sys_fchdir)
921	.long SYMBOL_NAME(sys_bdflush)
922	.long SYMBOL_NAME(sys_sysfs)		/* 135 */
923	.long SYMBOL_NAME(sys_personality)
924	.long SYMBOL_NAME(sys_ni_syscall)	/* for afs_syscall */
925	.long SYMBOL_NAME(sys_setfsuid16)
926	.long SYMBOL_NAME(sys_setfsgid16)
927	.long SYMBOL_NAME(sys_llseek)		/* 140 */
928	.long SYMBOL_NAME(sys_getdents)
929	.long SYMBOL_NAME(sys_select)
930	.long SYMBOL_NAME(sys_flock)
931	.long SYMBOL_NAME(sys_msync)
932	.long SYMBOL_NAME(sys_readv)		/* 145 */
933	.long SYMBOL_NAME(sys_writev)
934	.long SYMBOL_NAME(sys_getsid)
935	.long SYMBOL_NAME(sys_fdatasync)
936	.long SYMBOL_NAME(sys_sysctl)
937	.long SYMBOL_NAME(sys_mlock)		/* 150 */
938	.long SYMBOL_NAME(sys_munlock)
939	.long SYMBOL_NAME(sys_mlockall)
940	.long SYMBOL_NAME(sys_munlockall)
941	.long SYMBOL_NAME(sys_sched_setparam)
942	.long SYMBOL_NAME(sys_sched_getparam)   /* 155 */
943	.long SYMBOL_NAME(sys_sched_setscheduler)
944	.long SYMBOL_NAME(sys_sched_getscheduler)
945	.long SYMBOL_NAME(sys_sched_yield)
946	.long SYMBOL_NAME(sys_sched_get_priority_max)
947	.long SYMBOL_NAME(sys_sched_get_priority_min)  /* 160 */
948	.long SYMBOL_NAME(sys_sched_rr_get_interval)
949	.long SYMBOL_NAME(sys_nanosleep)
950	.long SYMBOL_NAME(sys_mremap)
951	.long SYMBOL_NAME(sys_setresuid16)
952	.long SYMBOL_NAME(sys_getresuid16)	/* 165 */
953	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_vm86 */
954	.long SYMBOL_NAME(sys_query_module)
955	.long SYMBOL_NAME(sys_poll)
956	.long SYMBOL_NAME(sys_nfsservctl)
957	.long SYMBOL_NAME(sys_setresgid16)	/* 170 */
958	.long SYMBOL_NAME(sys_getresgid16)
959	.long SYMBOL_NAME(sys_prctl)
960	.long SYMBOL_NAME(sys_rt_sigreturn)
961	.long SYMBOL_NAME(sys_rt_sigaction)
962	.long SYMBOL_NAME(sys_rt_sigprocmask)	/* 175 */
963	.long SYMBOL_NAME(sys_rt_sigpending)
964	.long SYMBOL_NAME(sys_rt_sigtimedwait)
965	.long SYMBOL_NAME(sys_rt_sigqueueinfo)
966	.long SYMBOL_NAME(sys_rt_sigsuspend)
967	.long SYMBOL_NAME(sys_pread)		/* 180 */
968	.long SYMBOL_NAME(sys_pwrite)
969	.long SYMBOL_NAME(sys_chown16)
970	.long SYMBOL_NAME(sys_getcwd)
971	.long SYMBOL_NAME(sys_capget)
972	.long SYMBOL_NAME(sys_capset)           /* 185 */
973	.long SYMBOL_NAME(sys_sigaltstack)
974	.long SYMBOL_NAME(sys_sendfile)
975	.long SYMBOL_NAME(sys_ni_syscall)	/* streams1 */
976	.long SYMBOL_NAME(sys_ni_syscall)	/* streams2 */
977	.long SYMBOL_NAME(sys_vfork)            /* 190 */
978	.long SYMBOL_NAME(sys_getrlimit)
979	.long SYMBOL_NAME(sys_mmap2)
980	.long SYMBOL_NAME(sys_truncate64)
981	.long SYMBOL_NAME(sys_ftruncate64)
982	.long SYMBOL_NAME(sys_stat64)		/* 195 */
983	.long SYMBOL_NAME(sys_lstat64)
984	.long SYMBOL_NAME(sys_fstat64)
985	.long SYMBOL_NAME(sys_lchown)
986	.long SYMBOL_NAME(sys_getuid)
987	.long SYMBOL_NAME(sys_getgid)		/* 200 */
988	.long SYMBOL_NAME(sys_geteuid)
989	.long SYMBOL_NAME(sys_getegid)
990	.long SYMBOL_NAME(sys_setreuid)
991	.long SYMBOL_NAME(sys_setregid)
992	.long SYMBOL_NAME(sys_getgroups)	/* 205 */
993	.long SYMBOL_NAME(sys_setgroups)
994	.long SYMBOL_NAME(sys_fchown)
995	.long SYMBOL_NAME(sys_setresuid)
996	.long SYMBOL_NAME(sys_getresuid)
997	.long SYMBOL_NAME(sys_setresgid)	/* 210 */
998	.long SYMBOL_NAME(sys_getresgid)
999	.long SYMBOL_NAME(sys_chown)
1000	.long SYMBOL_NAME(sys_setuid)
1001	.long SYMBOL_NAME(sys_setgid)
1002	.long SYMBOL_NAME(sys_setfsuid)		/* 215 */
1003	.long SYMBOL_NAME(sys_setfsgid)
1004	.long SYMBOL_NAME(sys_pivot_root)
1005	.long SYMBOL_NAME(sys_mincore)
1006	.long SYMBOL_NAME(sys_madvise)
1007	.long SYMBOL_NAME(sys_getdents64)       /* 220 */
1008	.long SYMBOL_NAME(sys_fcntl64)
1009	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved for TUX */
1010        .long SYMBOL_NAME(sys_ni_syscall)       /* Reserved for Security */
1011        .long SYMBOL_NAME(sys_gettid)
1012        .long SYMBOL_NAME(sys_readahead)        /* 225 */
1013	.long SYMBOL_NAME(sys_tkill)
1014
1015        /*
1016         * NOTE!! This doesn't have to be exact - we just have
1017         * to make sure we have _enough_ of the "sys_ni_syscall"
1018         * entries. Don't panic if you notice that this hasn't
1019         * been shrunk every time we add a new system call.
1020         */
1021
1022	.rept NR_syscalls-(.-sys_call_table)/4
1023		.long SYMBOL_NAME(sys_ni_syscall)
1024	.endr
1025
1026