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