1/*
2 *  linux/arch/m32r/kernel/entry.S
3 *
4 *  Copyright (c) 2001, 2002  Hirokazu Takata, Hitoshi Yamamoto, H. Kondo
5 *  Copyright (c) 2003  Hitoshi Yamamoto
6 *  Copyright (c) 2004  Hirokazu Takata <takata at linux-m32r.org>
7 *
8 *  Taken from i386 version.
9 *    Copyright (C) 1991, 1992  Linus Torvalds
10 */
11
12/*
13 * entry.S contains the system-call and fault low-level handling routines.
14 * This also contains the timer-interrupt handler, as well as all interrupts
15 * and faults that can result in a task-switch.
16 *
17 * NOTE: This code handles signal-recognition, which happens every time
18 * after a timer-interrupt and after each system call.
19 *
20 * Stack layout in 'ret_from_system_call':
21 * 	ptrace needs to have all regs on the stack.
22 *	if the order here is changed, it needs to be
23 *	updated in fork.c:copy_thread, signal.c:do_signal,
24 *	ptrace.c and ptrace.h
25 *
26 * M32R/M32Rx/M32R2
27 *       @(sp)      - r4
28 *       @(0x04,sp) - r5
29 *       @(0x08,sp) - r6
30 *       @(0x0c,sp) - *pt_regs
31 *       @(0x10,sp) - r0
32 *       @(0x14,sp) - r1
33 *       @(0x18,sp) - r2
34 *       @(0x1c,sp) - r3
35 *       @(0x20,sp) - r7
36 *       @(0x24,sp) - r8
37 *       @(0x28,sp) - r9
38 *       @(0x2c,sp) - r10
39 *       @(0x30,sp) - r11
40 *       @(0x34,sp) - r12
41 *       @(0x38,sp) - syscall_nr
42 *       @(0x3c,sp) - acc0h
43 *       @(0x40,sp) - acc0l
44 *       @(0x44,sp) - acc1h		; ISA_DSP_LEVEL2 only
45 *       @(0x48,sp) - acc1l		; ISA_DSP_LEVEL2 only
46 *       @(0x4c,sp) - psw
47 *       @(0x50,sp) - bpc
48 *       @(0x54,sp) - bbpsw
49 *       @(0x58,sp) - bbpc
50 *       @(0x5c,sp) - spu (cr3)
51 *       @(0x60,sp) - fp (r13)
52 *       @(0x64,sp) - lr (r14)
53 *       @(0x68,sp) - spi (cr2)
54 *       @(0x6c,sp) - orig_r0
55 */
56
57#include <linux/linkage.h>
58#include <asm/irq.h>
59#include <asm/unistd.h>
60#include <asm/assembler.h>
61#include <asm/thread_info.h>
62#include <asm/errno.h>
63#include <asm/segment.h>
64#include <asm/smp.h>
65#include <asm/page.h>
66#include <asm/m32r.h>
67#include <asm/mmu_context.h>
68
69#if !defined(CONFIG_MMU)
70#define sys_madvise		sys_ni_syscall
71#define sys_readahead		sys_ni_syscall
72#define sys_mprotect		sys_ni_syscall
73#define sys_msync		sys_ni_syscall
74#define sys_mlock		sys_ni_syscall
75#define sys_munlock		sys_ni_syscall
76#define sys_mlockall		sys_ni_syscall
77#define sys_munlockall		sys_ni_syscall
78#define sys_mremap		sys_ni_syscall
79#define sys_mincore		sys_ni_syscall
80#define sys_remap_file_pages	sys_ni_syscall
81#endif /* CONFIG_MMU */
82
83#define R4(reg)			@reg
84#define R5(reg)			@(0x04,reg)
85#define R6(reg)			@(0x08,reg)
86#define PTREGS(reg)		@(0x0C,reg)
87#define R0(reg)			@(0x10,reg)
88#define R1(reg)			@(0x14,reg)
89#define R2(reg)			@(0x18,reg)
90#define R3(reg)			@(0x1C,reg)
91#define R7(reg)			@(0x20,reg)
92#define R8(reg)			@(0x24,reg)
93#define R9(reg)			@(0x28,reg)
94#define R10(reg)		@(0x2C,reg)
95#define R11(reg)		@(0x30,reg)
96#define R12(reg)		@(0x34,reg)
97#define SYSCALL_NR(reg)		@(0x38,reg)
98#define ACC0H(reg)		@(0x3C,reg)
99#define ACC0L(reg)		@(0x40,reg)
100#define ACC1H(reg)		@(0x44,reg)
101#define ACC1L(reg)		@(0x48,reg)
102#define PSW(reg)		@(0x4C,reg)
103#define BPC(reg)		@(0x50,reg)
104#define BBPSW(reg)		@(0x54,reg)
105#define BBPC(reg)		@(0x58,reg)
106#define SPU(reg)		@(0x5C,reg)
107#define FP(reg)			@(0x60,reg)  /* FP = R13 */
108#define LR(reg)			@(0x64,reg)
109#define SP(reg)			@(0x68,reg)
110#define ORIG_R0(reg)		@(0x6C,reg)
111
112CF_MASK		= 0x00000001
113TF_MASK		= 0x00000100
114IF_MASK		= 0x00000200
115DF_MASK		= 0x00000400
116NT_MASK		= 0x00004000
117VM_MASK		= 0x00020000
118
119#ifdef CONFIG_PREEMPT
120#define preempt_stop(x)		CLI(x)
121#else
122#define preempt_stop(x)
123#define resume_kernel		restore_all
124#endif
125
126ENTRY(ret_from_fork)
127	pop	r0
128	bl	schedule_tail
129	GET_THREAD_INFO(r8)
130	bra	syscall_exit
131
132/*
133 * Return to user mode is not as complex as all this looks,
134 * but we want the default path for a system call return to
135 * go as quickly as possible which is why some of this is
136 * less clear than it otherwise should be.
137 */
138
139	; userspace resumption stub bypassing syscall exit tracing
140	ALIGN
141ret_from_exception:
142	preempt_stop(r4)
143ret_from_intr:
144	ld	r4, PSW(sp)
145#ifdef CONFIG_ISA_M32R2
146	and3	r4, r4, #0x8800		; check BSM and BPM bits
147#else
148	and3	r4, r4, #0x8000		; check BSM bit
149#endif
150	beqz	r4, resume_kernel
151ENTRY(resume_userspace)
152	CLI(r4)				; make sure we don't miss an interrupt
153					; setting need_resched or sigpending
154					; between sampling and the iret
155	GET_THREAD_INFO(r8)
156	ld	r9, @(TI_FLAGS, r8)
157	and3	r4, r9, #_TIF_WORK_MASK	; is there any work to be done on
158					; int/exception return?
159	bnez	r4, work_pending
160	bra	restore_all
161
162#ifdef CONFIG_PREEMPT
163ENTRY(resume_kernel)
164	GET_THREAD_INFO(r8)
165	ld	r9, @(TI_PRE_COUNT, r8)	; non-zero preempt_count ?
166	bnez	r9, restore_all
167need_resched:
168	ld	r9, @(TI_FLAGS, r8)	; need_resched set ?
169	and3	r4, r9, #_TIF_NEED_RESCHED
170	beqz	r4, restore_all
171	ld	r4, PSW(sp)		; interrupts off (exception path) ?
172	and3	r4, r4, #0x4000
173	beqz	r4, restore_all
174	LDIMM	(r4, PREEMPT_ACTIVE)
175	st	r4, @(TI_PRE_COUNT, r8)
176	STI(r4)
177	bl	schedule
178	ldi	r4, #0
179	st	r4, @(TI_PRE_COUNT, r8)
180	CLI(r4)
181	bra	need_resched
182#endif
183
184	; system call handler stub
185ENTRY(system_call)
186	SWITCH_TO_KERNEL_STACK
187	SAVE_ALL
188	STI(r4)				; Enable interrupt
189	st	sp, PTREGS(sp)		; implicit pt_regs parameter
190	cmpui	r7, #NR_syscalls
191	bnc	syscall_badsys
192	st	r7, SYSCALL_NR(sp)	; syscall_nr
193					; system call tracing in operation
194	GET_THREAD_INFO(r8)
195	ld	r9, @(TI_FLAGS, r8)
196	and3	r4, r9, #_TIF_SYSCALL_TRACE
197	bnez	r4, syscall_trace_entry
198syscall_call:
199	slli	r7, #2			; table jump for the system call
200	LDIMM	(r4, sys_call_table)
201	add	r7, r4
202	ld	r7, @r7
203	jl	r7			; execute system call
204	st	r0, R0(sp)		; save the return value
205syscall_exit:
206	CLI(r4)				; make sure we don't miss an interrupt
207					; setting need_resched or sigpending
208					; between sampling and the iret
209	ld	r9, @(TI_FLAGS, r8)
210	and3	r4, r9, #_TIF_ALLWORK_MASK	; current->work
211	bnez	r4, syscall_exit_work
212restore_all:
213	RESTORE_ALL
214
215	# perform work that needs to be done immediately before resumption
216	# r9 : flags
217	ALIGN
218work_pending:
219	and3	r4, r9, #_TIF_NEED_RESCHED
220	beqz	r4, work_notifysig
221work_resched:
222	bl	schedule
223	CLI(r4)				; make sure we don't miss an interrupt
224					; setting need_resched or sigpending
225					; between sampling and the iret
226	ld	r9, @(TI_FLAGS, r8)
227	and3	r4, r9, #_TIF_WORK_MASK	; is there any work to be done other
228					; than syscall tracing?
229	beqz	r4, restore_all
230	and3	r4, r4, #_TIF_NEED_RESCHED
231	bnez	r4, work_resched
232
233work_notifysig:				; deal with pending signals and
234					; notify-resume requests
235	mv	r0, sp			; arg1 : struct pt_regs *regs
236	ldi	r1, #0			; arg2 : sigset_t *oldset
237	mv	r2, r9			; arg3 : __u32 thread_info_flags
238	bl	do_notify_resume
239	bra	restore_all
240
241	; perform syscall exit tracing
242	ALIGN
243syscall_trace_entry:
244	ldi	r4, #-ENOSYS
245	st	r4, R0(sp)
246	bl	do_syscall_trace
247	ld	r0, ORIG_R0(sp)
248	ld	r1, R1(sp)
249	ld	r2, R2(sp)
250	ld	r3, R3(sp)
251	ld	r4, R4(sp)
252	ld	r5, R5(sp)
253	ld	r6, R6(sp)
254	ld	r7, SYSCALL_NR(sp)
255	cmpui	r7, #NR_syscalls
256	bc	syscall_call
257	bra	syscall_exit
258
259	; perform syscall exit tracing
260	ALIGN
261syscall_exit_work:
262	ld	r9, @(TI_FLAGS, r8)
263	and3	r4, r9, #_TIF_SYSCALL_TRACE
264	beqz	r4, work_pending
265	STI(r4)				; could let do_syscall_trace() call
266					; schedule() instead
267	bl	do_syscall_trace
268	bra	resume_userspace
269
270	ALIGN
271syscall_fault:
272	SAVE_ALL
273	GET_THREAD_INFO(r8)
274	ldi	r4, #-EFAULT
275	st	r4, R0(sp)
276	bra	resume_userspace
277
278	ALIGN
279syscall_badsys:
280	ldi	r4, #-ENOSYS
281	st	r4, R0(sp)
282	bra	resume_userspace
283
284	.global	eit_vector
285
286	.equ ei_vec_table, eit_vector + 0x0200
287
288/*
289 * EI handler routine
290 */
291ENTRY(ei_handler)
292#if defined(CONFIG_CHIP_M32700)
293	SWITCH_TO_KERNEL_STACK
294	; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
295#endif
296	SAVE_ALL
297	mv	r1, sp			; arg1(regs)
298#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) || \
299	defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_OPSP) \
300	|| defined(CONFIG_CHIP_M32104)
301
302;    GET_ICU_STATUS;
303	seth	r0, #shigh(M32R_ICU_ISTS_ADDR)
304	ld	r0, @(low(M32R_ICU_ISTS_ADDR),r0)
305	push	r0
306#if defined(CONFIG_SMP)
307	/*
308	 * If IRQ == 0      --> Nothing to do,  Not write IMASK
309	 * If IRQ == IPI    --> Do IPI handler, Not write IMASK
310	 * If IRQ != 0, IPI --> Do do_IRQ(),    Write IMASK
311	 */
312	slli	r0, #4
313	srli	r0, #24			; r0(irq_num<<2)
314	;; IRQ exist check
315#if defined(CONFIG_CHIP_M32700)
316	beqz	r0, 3f			; if (!irq_num) goto exit
317#else
318	beqz	r0, 1f			; if (!irq_num) goto exit
319#endif
320	;; IPI check
321	cmpi	r0, #(M32R_IRQ_IPI0<<2)	; ISN < IPI0 check
322	bc	2f
323	cmpi	r0, #((M32R_IRQ_IPI7+1)<<2)	; ISN > IPI7 check
324	bnc	2f
325	LDIMM	(r2, ei_vec_table)
326	add	r2, r0
327	ld	r2, @r2
328	beqz	r2, 1f			; if (no IPI handler) goto exit
329	mv	r0, r1			; arg0(regs)
330	jl	r2
331	.fillinsn
3321:
333	addi	sp, #4
334	bra	ret_to_intr
335#if defined(CONFIG_CHIP_M32700)
336	.fillinsn
3373:
338	ld24	r14, #0x00070000
339	seth	r0, #shigh(M32R_ICU_IMASK_ADDR)
340	st	r14, @(low(M32R_ICU_IMASK_ADDR), r0)
341	addi	sp, #4
342	bra	ret_to_intr
343#endif
344	;; do_IRQ
345	.fillinsn
3462:
347	srli	r0, #2
348#if defined(CONFIG_PLAT_USRV)
349	add3	r2, r0, #-(M32R_IRQ_INT1)	; INT1# interrupt
350	bnez	r2, 9f
351	; read ICU status register of PLD
352	seth	r0, #high(PLD_ICUISTS)
353	or3	r0, r0, #low(PLD_ICUISTS)
354	lduh	r0, @r0
355	slli	r0, #21
356	srli	r0, #27				; ISN
357	addi	r0, #(M32700UT_PLD_IRQ_BASE)
358	.fillinsn
3599:
360#elif defined(CONFIG_PLAT_M32700UT)
361	add3	r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
362	bnez	r2, check_int0
363	; read ICU status register of PLD
364	seth	r0, #high(PLD_ICUISTS)
365	or3	r0, r0, #low(PLD_ICUISTS)
366	lduh	r0, @r0
367	slli	r0, #21
368	srli	r0, #27                         ; ISN
369	addi	r0, #(M32700UT_PLD_IRQ_BASE)
370	bra	check_end
371	.fillinsn
372check_int0:
373	add3	r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
374	bnez	r2, check_int2
375	; read ICU status of LAN-board
376	seth	r0, #high(M32700UT_LAN_ICUISTS)
377	or3	r0, r0, #low(M32700UT_LAN_ICUISTS)
378	lduh	r0, @r0
379	slli	r0, #21
380	srli	r0, #27                         ; ISN
381	add3	r0, r0, #(M32700UT_LAN_PLD_IRQ_BASE)
382	bra	check_end
383	.fillinsn
384check_int2:
385	add3	r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
386	bnez	r2, check_end
387	; read ICU status of LCD-board
388	seth	r0, #high(M32700UT_LCD_ICUISTS)
389	or3	r0, r0, #low(M32700UT_LCD_ICUISTS)
390	lduh	r0, @r0
391	slli	r0, #21
392	srli	r0, #27                         ; ISN
393	add3	r0, r0, #(M32700UT_LCD_PLD_IRQ_BASE)
394	bra	check_end
395	.fillinsn
396check_end:
397#elif defined(CONFIG_PLAT_OPSPUT)
398	add3	r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
399	bnez	r2, check_int0
400	; read ICU status register of PLD
401	seth	r0, #high(PLD_ICUISTS)
402	or3	r0, r0, #low(PLD_ICUISTS)
403	lduh	r0, @r0
404	slli	r0, #21
405	srli	r0, #27                         ; ISN
406	addi	r0, #(OPSPUT_PLD_IRQ_BASE)
407	bra	check_end
408	.fillinsn
409check_int0:
410	add3	r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
411	bnez	r2, check_int2
412	; read ICU status of LAN-board
413	seth	r0, #high(OPSPUT_LAN_ICUISTS)
414	or3	r0, r0, #low(OPSPUT_LAN_ICUISTS)
415	lduh	r0, @r0
416	slli	r0, #21
417	srli	r0, #27                         ; ISN
418	add3	r0, r0, #(OPSPUT_LAN_PLD_IRQ_BASE)
419	bra	check_end
420	.fillinsn
421check_int2:
422	add3	r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
423	bnez	r2, check_end
424	; read ICU status of LCD-board
425	seth	r0, #high(OPSPUT_LCD_ICUISTS)
426	or3	r0, r0, #low(OPSPUT_LCD_ICUISTS)
427	lduh	r0, @r0
428	slli	r0, #21
429	srli	r0, #27                         ; ISN
430	add3	r0, r0, #(OPSPUT_LCD_PLD_IRQ_BASE)
431	bra	check_end
432	.fillinsn
433check_end:
434#endif  /* CONFIG_PLAT_OPSPUT */
435	bl	do_IRQ			; r0(irq), r1(regs)
436#else  /* not CONFIG_SMP */
437	srli	r0, #22			; r0(irq)
438#if defined(CONFIG_PLAT_USRV)
439	add3	r2, r0, #-(M32R_IRQ_INT1)	; INT1# interrupt
440	bnez	r2, 1f
441	; read ICU status register of PLD
442	seth	r0, #high(PLD_ICUISTS)
443	or3	r0, r0, #low(PLD_ICUISTS)
444	lduh	r0, @r0
445	slli	r0, #21
446	srli	r0, #27				; ISN
447	addi	r0, #(M32700UT_PLD_IRQ_BASE)
448	.fillinsn
4491:
450#elif defined(CONFIG_PLAT_M32700UT)
451	add3	r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
452	bnez	r2, check_int0
453	; read ICU status register of PLD
454	seth	r0, #high(PLD_ICUISTS)
455	or3	r0, r0, #low(PLD_ICUISTS)
456	lduh	r0, @r0
457	slli	r0, #21
458	srli	r0, #27                         ; ISN
459	addi	r0, #(M32700UT_PLD_IRQ_BASE)
460	bra	check_end
461	.fillinsn
462check_int0:
463	add3	r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
464	bnez	r2, check_int2
465	; read ICU status of LAN-board
466	seth	r0, #high(M32700UT_LAN_ICUISTS)
467	or3	r0, r0, #low(M32700UT_LAN_ICUISTS)
468	lduh	r0, @r0
469	slli	r0, #21
470	srli	r0, #27                         ; ISN
471	add3	r0, r0, #(M32700UT_LAN_PLD_IRQ_BASE)
472	bra	check_end
473	.fillinsn
474check_int2:
475	add3	r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
476	bnez	r2, check_end
477	; read ICU status of LCD-board
478	seth	r0, #high(M32700UT_LCD_ICUISTS)
479	or3	r0, r0, #low(M32700UT_LCD_ICUISTS)
480	lduh	r0, @r0
481	slli	r0, #21
482	srli	r0, #27                         ; ISN
483	add3	r0, r0, #(M32700UT_LCD_PLD_IRQ_BASE)
484	bra	check_end
485	.fillinsn
486check_end:
487#elif defined(CONFIG_PLAT_OPSPUT)
488	add3	r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
489	bnez	r2, check_int0
490	; read ICU status register of PLD
491	seth	r0, #high(PLD_ICUISTS)
492	or3	r0, r0, #low(PLD_ICUISTS)
493	lduh	r0, @r0
494	slli	r0, #21
495	srli	r0, #27                         ; ISN
496	addi	r0, #(OPSPUT_PLD_IRQ_BASE)
497	bra	check_end
498	.fillinsn
499check_int0:
500	add3	r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
501	bnez	r2, check_int2
502	; read ICU status of LAN-board
503	seth	r0, #high(OPSPUT_LAN_ICUISTS)
504	or3	r0, r0, #low(OPSPUT_LAN_ICUISTS)
505	lduh	r0, @r0
506	slli	r0, #21
507	srli	r0, #27                         ; ISN
508	add3	r0, r0, #(OPSPUT_LAN_PLD_IRQ_BASE)
509	bra	check_end
510	.fillinsn
511check_int2:
512	add3	r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
513	bnez	r2, check_end
514	; read ICU status of LCD-board
515	seth	r0, #high(OPSPUT_LCD_ICUISTS)
516	or3	r0, r0, #low(OPSPUT_LCD_ICUISTS)
517	lduh	r0, @r0
518	slli	r0, #21
519	srli	r0, #27                         ; ISN
520	add3	r0, r0, #(OPSPUT_LCD_PLD_IRQ_BASE)
521	bra	check_end
522	.fillinsn
523check_end:
524#elif defined(CONFIG_PLAT_M32104UT)
525	add3	r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
526	bnez	r2, check_end
527	; read ICU status register of PLD
528	seth	r0, #high(PLD_ICUISTS)
529	or3	r0, r0, #low(PLD_ICUISTS)
530	lduh	r0, @r0
531	slli	r0, #21
532	srli	r0, #27                         ; ISN
533	addi	r0, #(M32104UT_PLD_IRQ_BASE)
534	bra	check_end
535	.fillinsn
536check_end:
537#endif  /* CONFIG_PLAT_M32104UT */
538	bl	do_IRQ
539#endif  /* CONFIG_SMP */
540	pop	r14
541	seth	r0, #shigh(M32R_ICU_IMASK_ADDR)
542	st	r14, @(low(M32R_ICU_IMASK_ADDR),r0)
543#else
544#error no chip configuration
545#endif
546ret_to_intr:
547	bra  ret_from_intr
548
549/*
550 * Default EIT handler
551 */
552	ALIGN
553int_msg:
554	.asciz  "Unknown interrupt\n"
555	.byte	0
556
557ENTRY(default_eit_handler)
558	push	r0
559	mvfc	r0, psw
560	push	r1
561	push	r2
562	push	r3
563	push	r0
564	LDIMM	(r0, __KERNEL_DS)
565	mv	r0, r1
566	mv	r0, r2
567	LDIMM	(r0, int_msg)
568	bl	printk
569	pop	r0
570	pop	r3
571	pop	r2
572	pop	r1
573	mvtc	r0, psw
574	pop	r0
575infinit:
576	bra	infinit
577
578#ifdef CONFIG_MMU
579/*
580 * Access Exception handler
581 */
582ENTRY(ace_handler)
583	SWITCH_TO_KERNEL_STACK
584	SAVE_ALL
585
586	seth	r2, #shigh(MMU_REG_BASE)	/* Check status register */
587	ld	r4, @(low(MESTS_offset),r2)
588	st	r4, @(low(MESTS_offset),r2)
589	srl3	r1, r4, #4
590#ifdef CONFIG_CHIP_M32700
591	and3	r1, r1, #0x0000ffff
592	; WORKAROUND: ignore TME bit for the M32700(TS1).
593#endif /* CONFIG_CHIP_M32700 */
594	beqz	r1, inst
595oprand:
596	ld	r2, @(low(MDEVA_offset),r2)	; set address
597	srli	r1, #1
598	bra	1f
599inst:
600	and3	r1, r4, #2
601	srli	r1, #1
602	or3	r1, r1, #8
603	mvfc	r2, bpc				; set address
604	.fillinsn
6051:
606	mvfc	r3, psw
607	mv	r0, sp
608	and3	r3, r3, 0x800
609	srli	r3, #9
610	or	r1, r3
611	/*
612	 * do_page_fault():
613	 *    r0 : struct pt_regs *regs
614	 *    r1 : unsigned long error-code
615	 *    r2 : unsigned long address
616	 * error-code:
617	 *    +------+------+------+------+
618	 *    | bit3 | bit2 | bit1 | bit0 |
619	 *    +------+------+------+------+
620	 *    bit 3 == 0:means data,          1:means instruction
621	 *    bit 2 == 0:means kernel,        1:means user-mode
622	 *    bit 1 == 0:means read,          1:means write
623	 *    bit 0 == 0:means no page found  1:means protection fault
624	 *
625	 */
626	bl	do_page_fault
627	bra	ret_from_intr
628#endif  /* CONFIG_MMU */
629
630
631ENTRY(alignment_check)
632/* void alignment_check(int error_code) */
633	SWITCH_TO_KERNEL_STACK
634	SAVE_ALL
635	ldi	r1, #0x30			; error_code
636	mv	r0, sp				; pt_regs
637	bl	do_alignment_check
638error_code:
639	bra	ret_from_exception
640
641ENTRY(rie_handler)
642/* void rie_handler(int error_code) */
643	SWITCH_TO_KERNEL_STACK
644	SAVE_ALL
645	ldi	r1, #0x20			; error_code
646	mv	r0, sp				; pt_regs
647	bl	do_rie_handler
648	bra	error_code
649
650ENTRY(pie_handler)
651/* void pie_handler(int error_code) */
652	SWITCH_TO_KERNEL_STACK
653	SAVE_ALL
654	ldi	r1, #0				; error_code ; FIXME
655	mv	r0, sp				; pt_regs
656	bl	do_pie_handler
657	bra	error_code
658
659ENTRY(debug_trap)
660	.global	withdraw_debug_trap
661	/* void debug_trap(void) */
662	SWITCH_TO_KERNEL_STACK
663	SAVE_ALL
664	mv	r0, sp				; pt_regs
665	bl	withdraw_debug_trap
666	ldi	r1, #0				; error_code
667	mv	r0, sp				; pt_regs
668	bl	do_debug_trap
669	bra	error_code
670
671ENTRY(ill_trap)
672	/* void ill_trap(void) */
673	SWITCH_TO_KERNEL_STACK
674	SAVE_ALL
675	ldi	r1, #0				; error_code ; FIXME
676	mv	r0, sp				; pt_regs
677	bl	do_ill_trap
678	bra	error_code
679
680
681/* Cache flushing handler */
682ENTRY(cache_flushing_handler)
683	.global	_flush_cache_all
684	/* void _flush_cache_all(void); */
685	SWITCH_TO_KERNEL_STACK
686	push	r0
687	push	r1
688	push	r2
689	push	r3
690	push	r4
691	push	r5
692	push	r6
693	push	r7
694	push	lr
695	bl	_flush_cache_all
696	pop	lr
697	pop	r7
698	pop	r6
699	pop	r5
700	pop	r4
701	pop	r3
702	pop	r2
703	pop	r1
704	pop	r0
705	rte
706
707.data
708ENTRY(sys_call_table)
709	.long sys_restart_syscall	/* 0  -  old "setup()" system call*/
710	.long sys_exit
711	.long sys_fork
712	.long sys_read
713	.long sys_write
714	.long sys_open			/* 5 */
715	.long sys_close
716	.long sys_waitpid
717	.long sys_creat
718	.long sys_link
719	.long sys_unlink		/* 10 */
720	.long sys_execve
721	.long sys_chdir
722	.long sys_time
723	.long sys_mknod
724	.long sys_chmod			/* 15 */
725	.long sys_ni_syscall		/* lchown16 syscall holder */
726	.long sys_ni_syscall		/* old break syscall holder */
727	.long sys_ni_syscall		/* old stat syscall holder */
728	.long sys_lseek
729	.long sys_getpid		/* 20 */
730	.long sys_mount
731	.long sys_oldumount
732	.long sys_ni_syscall		/* setuid16 syscall holder */
733	.long sys_ni_syscall		/* getuid16 syscall holder */
734	.long sys_stime			/* 25 */
735	.long sys_ptrace
736	.long sys_alarm
737	.long sys_ni_syscall		/* old fstat syscall holder */
738	.long sys_pause
739	.long sys_utime			/* 30 */
740	.long sys_ni_syscall		/* old stty syscall holder */
741	.long sys_cachectl		/* for M32R */ /* old gtty syscall holder */
742	.long sys_access
743	.long sys_ni_syscall		/* nice	syscall holder */
744	.long sys_ni_syscall		/* 35  -  old ftime syscall holder */
745	.long sys_sync
746	.long sys_kill
747	.long sys_rename
748	.long sys_mkdir
749	.long sys_rmdir			/* 40 */
750	.long sys_dup
751	.long sys_pipe
752	.long sys_times
753	.long sys_ni_syscall		/* old prof syscall holder */
754	.long sys_brk			/* 45 */
755	.long sys_ni_syscall		/* setgid16 syscall holder */
756	.long sys_getgid		/* will be unused */
757	.long sys_ni_syscall		/* signal syscall holder */
758	.long sys_ni_syscall		/* geteuid16  syscall holder */
759	.long sys_ni_syscall		/* 50 - getegid16 syscall holder */
760	.long sys_acct
761	.long sys_umount		/* recycled never used phys() */
762	.long sys_ni_syscall		/* old lock syscall holder */
763	.long sys_ioctl
764	.long sys_fcntl			/* 55 - will be unused */
765	.long sys_ni_syscall		/* mpx syscall holder */
766	.long sys_setpgid
767	.long sys_ni_syscall		/* old ulimit syscall holder */
768	.long sys_ni_syscall		/* sys_olduname */
769	.long sys_umask			/* 60 */
770	.long sys_chroot
771	.long sys_ustat
772	.long sys_dup2
773	.long sys_getppid
774	.long sys_getpgrp		/* 65 */
775	.long sys_setsid
776	.long sys_ni_syscall		/* sigaction syscall holder */
777	.long sys_ni_syscall		/* sgetmask syscall holder */
778	.long sys_ni_syscall		/* ssetmask syscall holder */
779	.long sys_ni_syscall		/* 70 - setreuid16 syscall holder */
780	.long sys_ni_syscall		/* setregid16 syscall holder */
781	.long sys_ni_syscall		/* sigsuspend syscall holder */
782	.long sys_ni_syscall		/* sigpending syscall holder */
783	.long sys_sethostname
784	.long sys_setrlimit		/* 75 */
785	.long sys_getrlimit/*will be unused*/
786	.long sys_getrusage
787	.long sys_gettimeofday
788	.long sys_settimeofday
789	.long sys_ni_syscall		/* 80 - getgroups16 syscall holder */
790	.long sys_ni_syscall		/* setgroups16 syscall holder */
791	.long sys_ni_syscall		/* sys_oldselect */
792	.long sys_symlink
793	.long sys_ni_syscall		/* old lstat syscall holder */
794	.long sys_readlink		/* 85 */
795	.long sys_uselib
796	.long sys_swapon
797	.long sys_reboot
798	.long sys_ni_syscall		/* readdir syscall holder */
799	.long sys_ni_syscall		/* 90 - old_mmap syscall holder */
800	.long sys_munmap
801	.long sys_truncate
802	.long sys_ftruncate
803	.long sys_fchmod
804	.long sys_ni_syscall		/* 95 - fchwon16  syscall holder */
805	.long sys_getpriority
806	.long sys_setpriority
807	.long sys_ni_syscall		/* old profil syscall holder */
808	.long sys_statfs
809	.long sys_fstatfs		/* 100 */
810	.long sys_ni_syscall		/* ioperm syscall holder */
811	.long sys_socketcall
812	.long sys_syslog
813	.long sys_setitimer
814	.long sys_getitimer		/* 105 */
815	.long sys_newstat
816	.long sys_newlstat
817	.long sys_newfstat
818	.long sys_ni_syscall		/* old uname syscall holder */
819	.long sys_ni_syscall		/* 110  -  iopl syscall holder */
820	.long sys_vhangup
821	.long sys_ni_syscall		/* idle syscall holder */
822	.long sys_ni_syscall		/* vm86old syscall holder */
823	.long sys_wait4
824	.long sys_swapoff		/* 115 */
825	.long sys_sysinfo
826	.long sys_ipc
827	.long sys_fsync
828	.long sys_ni_syscall		/* sigreturn syscall holder */
829	.long sys_clone			/* 120 */
830	.long sys_setdomainname
831	.long sys_newuname
832	.long sys_ni_syscall		/* modify_ldt syscall holder */
833	.long sys_adjtimex
834	.long sys_mprotect		/* 125 */
835	.long sys_ni_syscall		/* sigprocmask syscall holder */
836	.long sys_ni_syscall		/* create_module syscall holder */
837	.long sys_init_module
838	.long sys_delete_module
839	.long sys_ni_syscall		/* 130 - get_kernel_syms */
840	.long sys_quotactl
841	.long sys_getpgid
842	.long sys_fchdir
843	.long sys_bdflush
844	.long sys_sysfs			/* 135 */
845	.long sys_personality
846	.long sys_ni_syscall		/* afs_syscall syscall holder */
847	.long sys_ni_syscall		/* setfsuid16 syscall holder */
848	.long sys_ni_syscall		/* setfsgid16 syscall holder */
849	.long sys_llseek		/* 140 */
850	.long sys_getdents
851	.long sys_select
852	.long sys_flock
853	.long sys_msync
854	.long sys_readv			/* 145 */
855	.long sys_writev
856	.long sys_getsid
857	.long sys_fdatasync
858	.long sys_sysctl
859	.long sys_mlock			/* 150 */
860	.long sys_munlock
861	.long sys_mlockall
862	.long sys_munlockall
863	.long sys_sched_setparam
864	.long sys_sched_getparam	/* 155 */
865	.long sys_sched_setscheduler
866	.long sys_sched_getscheduler
867	.long sys_sched_yield
868	.long sys_sched_get_priority_max
869	.long sys_sched_get_priority_min	/* 160 */
870	.long sys_sched_rr_get_interval
871	.long sys_nanosleep
872	.long sys_mremap
873	.long sys_ni_syscall		/* setresuid16 syscall holder */
874	.long sys_ni_syscall		/* 165 - getresuid16 syscall holder */
875	.long sys_tas			/* vm86 syscall holder */
876	.long sys_ni_syscall		/* query_module syscall holder */
877	.long sys_poll
878	.long sys_nfsservctl
879	.long sys_setresgid		/* 170 */
880	.long sys_getresgid
881	.long sys_prctl
882	.long sys_rt_sigreturn
883	.long sys_rt_sigaction
884	.long sys_rt_sigprocmask	/* 175 */
885	.long sys_rt_sigpending
886	.long sys_rt_sigtimedwait
887	.long sys_rt_sigqueueinfo
888	.long sys_rt_sigsuspend
889	.long sys_pread64		/* 180 */
890	.long sys_pwrite64
891	.long sys_ni_syscall		/* chown16 syscall holder */
892	.long sys_getcwd
893	.long sys_capget
894	.long sys_capset		/* 185 */
895	.long sys_sigaltstack
896	.long sys_sendfile
897	.long sys_ni_syscall		/* streams1 */
898	.long sys_ni_syscall		/* streams2 */
899	.long sys_vfork			/* 190 */
900	.long sys_getrlimit
901	.long sys_mmap2
902	.long sys_truncate64
903	.long sys_ftruncate64
904	.long sys_stat64		/* 195 */
905	.long sys_lstat64
906	.long sys_fstat64
907	.long sys_lchown
908	.long sys_getuid
909	.long sys_getgid		/* 200 */
910	.long sys_geteuid
911	.long sys_getegid
912	.long sys_setreuid
913	.long sys_setregid
914	.long sys_getgroups		/* 205 */
915	.long sys_setgroups
916	.long sys_fchown
917	.long sys_setresuid
918	.long sys_getresuid
919	.long sys_setresgid		/* 210 */
920	.long sys_getresgid
921	.long sys_chown
922	.long sys_setuid
923	.long sys_setgid
924	.long sys_setfsuid		/* 215 */
925	.long sys_setfsgid
926	.long sys_pivot_root
927	.long sys_mincore
928	.long sys_madvise
929	.long sys_getdents64		/* 220 */
930	.long sys_fcntl64
931	.long sys_ni_syscall		/* reserved for TUX */
932	.long sys_ni_syscall		/* Reserved for Security */
933	.long sys_gettid
934	.long sys_readahead		/* 225 */
935	.long sys_setxattr
936	.long sys_lsetxattr
937	.long sys_fsetxattr
938	.long sys_getxattr
939	.long sys_lgetxattr		/* 230 */
940	.long sys_fgetxattr
941	.long sys_listxattr
942	.long sys_llistxattr
943	.long sys_flistxattr
944	.long sys_removexattr		/* 235 */
945	.long sys_lremovexattr
946	.long sys_fremovexattr
947	.long sys_tkill
948	.long sys_sendfile64
949	.long sys_futex			/* 240 */
950	.long sys_sched_setaffinity
951	.long sys_sched_getaffinity
952	.long sys_ni_syscall		/* reserved for "set_thread_area" system call */
953	.long sys_ni_syscall		/* reserved for "get_thread_area" system call */
954	.long sys_io_setup		/* 245 */
955	.long sys_io_destroy
956	.long sys_io_getevents
957	.long sys_io_submit
958	.long sys_io_cancel
959	.long sys_fadvise64		/* 250 */
960	.long sys_ni_syscall
961	.long sys_exit_group
962	.long sys_lookup_dcookie
963	.long sys_epoll_create
964	.long sys_epoll_ctl		/* 255 */
965	.long sys_epoll_wait
966 	.long sys_remap_file_pages
967 	.long sys_set_tid_address
968 	.long sys_timer_create
969 	.long sys_timer_settime		/* 260 */
970 	.long sys_timer_gettime
971 	.long sys_timer_getoverrun
972 	.long sys_timer_delete
973 	.long sys_clock_settime
974 	.long sys_clock_gettime		/* 265 */
975 	.long sys_clock_getres
976 	.long sys_clock_nanosleep
977	.long sys_statfs64
978	.long sys_fstatfs64
979	.long sys_tgkill		/* 270 */
980	.long sys_utimes
981 	.long sys_fadvise64_64
982	.long sys_ni_syscall		/* Reserved for sys_vserver */
983        .long sys_ni_syscall		/* Reserved for sys_mbind */
984        .long sys_ni_syscall		/* Reserved for sys_get_mempolicy */
985        .long sys_ni_syscall		/* Reserved for sys_set_mempolicy */
986        .long sys_mq_open
987        .long sys_mq_unlink
988        .long sys_mq_timedsend
989        .long sys_mq_timedreceive       /* 280 */
990        .long sys_mq_notify
991        .long sys_mq_getsetattr
992        .long sys_ni_syscall            /* reserved for kexec */
993	.long sys_waitid
994
995syscall_table_size=(.-sys_call_table)
996