Linux Audio

Check our new training course

Linux BSP development engineering services

Need help to port Linux and bootloaders to your hardware?
Loading...
v3.1
  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
112#define nr_syscalls ((syscall_table_size)/4)
113
114#ifdef CONFIG_PREEMPT
115#define preempt_stop(x)		DISABLE_INTERRUPTS(x)
116#else
117#define preempt_stop(x)
118#define resume_kernel		restore_all
119#endif
120
121/* how to get the thread information struct from ASM */
122#define GET_THREAD_INFO(reg)	GET_THREAD_INFO reg
123	.macro GET_THREAD_INFO reg
124	ldi	\reg, #-THREAD_SIZE
125	and	\reg, sp
126	.endm
127
 
 
 
 
 
 
 
 
 
128ENTRY(ret_from_fork)
129	pop	r0
130	bl	schedule_tail
131	GET_THREAD_INFO(r8)
132	bra	syscall_exit
133
134/*
135 * Return to user mode is not as complex as all this looks,
136 * but we want the default path for a system call return to
137 * go as quickly as possible which is why some of this is
138 * less clear than it otherwise should be.
139 */
140
141	; userspace resumption stub bypassing syscall exit tracing
142	ALIGN
143ret_from_exception:
144	preempt_stop(r4)
145ret_from_intr:
146	ld	r4, PSW(sp)
147#ifdef CONFIG_ISA_M32R2
148	and3	r4, r4, #0x8800		; check BSM and BPM bits
149#else
150	and3	r4, r4, #0x8000		; check BSM bit
151#endif
152	beqz	r4, resume_kernel
153resume_userspace:
154	DISABLE_INTERRUPTS(r4)		; make sure we don't miss an interrupt
155					; setting need_resched or sigpending
156					; between sampling and the iret
157	GET_THREAD_INFO(r8)
158	ld	r9, @(TI_FLAGS, r8)
159	and3	r4, r9, #_TIF_WORK_MASK	; is there any work to be done on
160					; int/exception return?
161	bnez	r4, work_pending
162	bra	restore_all
163
164#ifdef CONFIG_PREEMPT
165ENTRY(resume_kernel)
166	GET_THREAD_INFO(r8)
167	ld	r9, @(TI_PRE_COUNT, r8)	; non-zero preempt_count ?
168	bnez	r9, restore_all
169need_resched:
170	ld	r9, @(TI_FLAGS, r8)	; need_resched set ?
171	and3	r4, r9, #_TIF_NEED_RESCHED
172	beqz	r4, restore_all
173	ld	r4, PSW(sp)		; interrupts off (exception path) ?
174	and3	r4, r4, #0x4000
175	beqz	r4, restore_all
176	LDIMM	(r4, PREEMPT_ACTIVE)
177	st	r4, @(TI_PRE_COUNT, r8)
178	ENABLE_INTERRUPTS(r4)
179	bl	schedule
180	ldi	r4, #0
181	st	r4, @(TI_PRE_COUNT, r8)
182	DISABLE_INTERRUPTS(r4)
183	bra	need_resched
184#endif
185
186	; system call handler stub
187ENTRY(system_call)
188	SWITCH_TO_KERNEL_STACK
189	SAVE_ALL
190	ENABLE_INTERRUPTS(r4)		; Enable interrupt
191	st	sp, PTREGS(sp)		; implicit pt_regs parameter
192	cmpui	r7, #NR_syscalls
193	bnc	syscall_badsys
194	st	r7, SYSCALL_NR(sp)	; syscall_nr
195					; system call tracing in operation
196	GET_THREAD_INFO(r8)
197	ld	r9, @(TI_FLAGS, r8)
198	and3	r4, r9, #_TIF_SYSCALL_TRACE
199	bnez	r4, syscall_trace_entry
200syscall_call:
201	slli	r7, #2			; table jump for the system call
202	LDIMM	(r4, sys_call_table)
203	add	r7, r4
204	ld	r7, @r7
205	jl	r7			; execute system call
206	st	r0, R0(sp)		; save the return value
207syscall_exit:
208	DISABLE_INTERRUPTS(r4)		; make sure we don't miss an interrupt
209					; setting need_resched or sigpending
210					; between sampling and the iret
211	ld	r9, @(TI_FLAGS, r8)
212	and3	r4, r9, #_TIF_ALLWORK_MASK	; current->work
213	bnez	r4, syscall_exit_work
214restore_all:
215	RESTORE_ALL
216
217	# perform work that needs to be done immediately before resumption
218	# r9 : flags
219	ALIGN
220work_pending:
221	and3	r4, r9, #_TIF_NEED_RESCHED
222	beqz	r4, work_notifysig
223work_resched:
224	bl	schedule
225	DISABLE_INTERRUPTS(r4)		; make sure we don't miss an interrupt
226					; setting need_resched or sigpending
227					; between sampling and the iret
228	ld	r9, @(TI_FLAGS, r8)
229	and3	r4, r9, #_TIF_WORK_MASK	; is there any work to be done other
230					; than syscall tracing?
231	beqz	r4, restore_all
232	and3	r4, r4, #_TIF_NEED_RESCHED
233	bnez	r4, work_resched
234
235work_notifysig:				; deal with pending signals and
236					; notify-resume requests
237	mv	r0, sp			; arg1 : struct pt_regs *regs
238	mv	r1, r9			; arg2 : __u32 thread_info_flags
239	bl	do_notify_resume
240	bra	resume_userspace
241
242	; perform syscall exit tracing
243	ALIGN
244syscall_trace_entry:
245	ldi	r4, #-ENOSYS
246	st	r4, R0(sp)
247	bl	do_syscall_trace
248	ld	r0, ORIG_R0(sp)
249	ld	r1, R1(sp)
250	ld	r2, R2(sp)
251	ld	r3, R3(sp)
252	ld	r4, R4(sp)
253	ld	r5, R5(sp)
254	ld	r6, R6(sp)
255	ld	r7, SYSCALL_NR(sp)
256	cmpui	r7, #NR_syscalls
257	bc	syscall_call
258	bra	syscall_exit
259
260	; perform syscall exit tracing
261	ALIGN
262syscall_exit_work:
263	ld	r9, @(TI_FLAGS, r8)
264	and3	r4, r9, #_TIF_SYSCALL_TRACE
265	beqz	r4, work_pending
266	ENABLE_INTERRUPTS(r4)		; could let do_syscall_trace() call
267					; schedule() instead
268	bl	do_syscall_trace
269	bra	resume_userspace
270
271	ALIGN
272syscall_fault:
273	SAVE_ALL
274	GET_THREAD_INFO(r8)
275	ldi	r4, #-EFAULT
276	st	r4, R0(sp)
277	bra	resume_userspace
278
279	ALIGN
280syscall_badsys:
281	ldi	r4, #-ENOSYS
282	st	r4, R0(sp)
283	bra	resume_userspace
284
285	.global	eit_vector
286
287	.equ ei_vec_table, eit_vector + 0x0200
288
289/*
290 * EI handler routine
291 */
292ENTRY(ei_handler)
293#if defined(CONFIG_CHIP_M32700)
294	; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
295	SWITCH_TO_KERNEL_STACK
296#endif
297	SAVE_ALL
298	mv	r1, sp			; arg1(regs)
299	; get ICU status
300	seth	r0, #shigh(M32R_ICU_ISTS_ADDR)
301	ld	r0, @(low(M32R_ICU_ISTS_ADDR),r0)
302	push	r0
303#if defined(CONFIG_SMP)
304	/*
305	 * If IRQ == 0      --> Nothing to do,  Not write IMASK
306	 * If IRQ == IPI    --> Do IPI handler, Not write IMASK
307	 * If IRQ != 0, IPI --> Do do_IRQ(),    Write IMASK
308	 */
309	slli	r0, #4
310	srli	r0, #24			; r0(irq_num<<2)
311	;; IRQ exist check
312#if defined(CONFIG_CHIP_M32700)
313	/* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
314	bnez	r0, 0f
315	ld24	r14, #0x00070000
316	seth	r0, #shigh(M32R_ICU_IMASK_ADDR)
317	st	r14, @(low(M32R_ICU_IMASK_ADDR),r0)
318	bra	1f
319	.fillinsn
3200:
321#endif /* CONFIG_CHIP_M32700 */
322	beqz	r0, 1f			; if (!irq_num) goto exit
323	;; IPI check
324	cmpi	r0, #(M32R_IRQ_IPI0<<2)	; ISN < IPI0 check
325	bc	2f
326	cmpi	r0, #((M32R_IRQ_IPI7+1)<<2)	; ISN > IPI7 check
327	bnc	2f
328	LDIMM	(r2, ei_vec_table)
329	add	r2, r0
330	ld	r2, @r2
331	beqz	r2, 1f			; if (no IPI handler) goto exit
332	mv	r0, r1			; arg0(regs)
333	jl	r2
334	.fillinsn
3351:
336	addi	sp, #4
337	bra	restore_all
338	.fillinsn
3392:
340	srli	r0, #2
341#else /* not CONFIG_SMP */
342	srli	r0, #22			; r0(irq)
343#endif /* not CONFIG_SMP */
344
345#if defined(CONFIG_PLAT_HAS_INT1ICU)
346	add3	r2, r0, #-(M32R_IRQ_INT1)	; INT1# interrupt
347	bnez	r2, 3f
348	seth	r0, #shigh(M32R_INT1ICU_ISTS)
349	lduh	r0, @(low(M32R_INT1ICU_ISTS),r0)	; bit10-6 : ISN
350	slli	r0, #21
351	srli	r0, #27				; ISN
352	addi	r0, #(M32R_INT1ICU_IRQ_BASE)
353	bra	check_end
354	.fillinsn
3553:
356#endif /* CONFIG_PLAT_HAS_INT1ICU */
357#if defined(CONFIG_PLAT_HAS_INT0ICU)
358	add3	r2, r0, #-(M32R_IRQ_INT0)	; INT0# interrupt
359	bnez	r2, 4f
360	seth	r0, #shigh(M32R_INT0ICU_ISTS)
361	lduh	r0, @(low(M32R_INT0ICU_ISTS),r0)	; bit10-6 : ISN
362	slli	r0, #21
363	srli	r0, #27				; ISN
364	add3	r0, r0, #(M32R_INT0ICU_IRQ_BASE)
365	bra	check_end
366	.fillinsn
3674:
368#endif /* CONFIG_PLAT_HAS_INT0ICU */
369#if defined(CONFIG_PLAT_HAS_INT2ICU)
370	add3	r2, r0, #-(M32R_IRQ_INT2)	; INT2# interrupt
371	bnez	r2, 5f
372	seth	r0, #shigh(M32R_INT2ICU_ISTS)
373	lduh	r0, @(low(M32R_INT2ICU_ISTS),r0)	; bit10-6 : ISN
374	slli	r0, #21
375	srli	r0, #27				; ISN
376	add3	r0, r0, #(M32R_INT2ICU_IRQ_BASE)
377	; bra	check_end
378	.fillinsn
3795:
380#endif /* CONFIG_PLAT_HAS_INT2ICU */
381
382check_end:
383	bl	do_IRQ
384	pop	r14
385	seth	r0, #shigh(M32R_ICU_IMASK_ADDR)
386	st	r14, @(low(M32R_ICU_IMASK_ADDR),r0)
387	bra  ret_from_intr
388
389/*
390 * Default EIT handler
391 */
392	ALIGN
393int_msg:
394	.asciz  "Unknown interrupt\n"
395	.byte	0
396
397ENTRY(default_eit_handler)
398	push	r0
399	mvfc	r0, psw
400	push	r1
401	push	r2
402	push	r3
403	push	r0
404	LDIMM	(r0, __KERNEL_DS)
405	mv	r0, r1
406	mv	r0, r2
407	LDIMM	(r0, int_msg)
408	bl	printk
409	pop	r0
410	pop	r3
411	pop	r2
412	pop	r1
413	mvtc	r0, psw
414	pop	r0
415infinit:
416	bra	infinit
417
418#ifdef CONFIG_MMU
419/*
420 * Access Exception handler
421 */
422ENTRY(ace_handler)
423	SWITCH_TO_KERNEL_STACK
424	SAVE_ALL
425
426	seth	r2, #shigh(MMU_REG_BASE)	/* Check status register */
427	ld	r4, @(low(MESTS_offset),r2)
428	st	r4, @(low(MESTS_offset),r2)
429	srl3	r1, r4, #4
430#ifdef CONFIG_CHIP_M32700
431	and3	r1, r1, #0x0000ffff
432	; WORKAROUND: ignore TME bit for the M32700(TS1).
433#endif /* CONFIG_CHIP_M32700 */
434	beqz	r1, inst
435oprand:
436	ld	r2, @(low(MDEVA_offset),r2)	; set address
437	srli	r1, #1
438	bra	1f
439inst:
440	and3	r1, r4, #2
441	srli	r1, #1
442	or3	r1, r1, #8
443	mvfc	r2, bpc				; set address
444	.fillinsn
4451:
446	mvfc	r3, psw
447	mv	r0, sp
448	and3	r3, r3, 0x800
449	srli	r3, #9
450	or	r1, r3
451	/*
452	 * do_page_fault():
453	 *    r0 : struct pt_regs *regs
454	 *    r1 : unsigned long error-code
455	 *    r2 : unsigned long address
456	 * error-code:
457	 *    +------+------+------+------+
458	 *    | bit3 | bit2 | bit1 | bit0 |
459	 *    +------+------+------+------+
460	 *    bit 3 == 0:means data,          1:means instruction
461	 *    bit 2 == 0:means kernel,        1:means user-mode
462	 *    bit 1 == 0:means read,          1:means write
463	 *    bit 0 == 0:means no page found  1:means protection fault
464	 *
465	 */
466	bl	do_page_fault
467	bra	ret_from_intr
468#endif  /* CONFIG_MMU */
469
470
471ENTRY(alignment_check)
472	/* void alignment_check(int error_code) */
473	SWITCH_TO_KERNEL_STACK
474	SAVE_ALL
475	ldi	r1, #0x30			; error_code
476	mv	r0, sp				; pt_regs
477	bl	do_alignment_check
478error_code:
479	bra	ret_from_exception
480
481ENTRY(rie_handler)
482	/* void rie_handler(int error_code) */
483	SWITCH_TO_KERNEL_STACK
484	SAVE_ALL
485	ldi	r1, #0x20			; error_code
486	mv	r0, sp				; pt_regs
487	bl	do_rie_handler
488	bra	error_code
489
490ENTRY(pie_handler)
491	/* void pie_handler(int error_code) */
492	SWITCH_TO_KERNEL_STACK
493	SAVE_ALL
494	ldi	r1, #0				; error_code ; FIXME
495	mv	r0, sp				; pt_regs
496	bl	do_pie_handler
497	bra	error_code
498
499ENTRY(debug_trap)
500	/* void debug_trap(void) */
501	.global	withdraw_debug_trap
502	SWITCH_TO_KERNEL_STACK
503	SAVE_ALL
504	mv	r0, sp				; pt_regs
505	bl	withdraw_debug_trap
506	ldi	r1, #0				; error_code
507	mv	r0, sp				; pt_regs
508	bl	do_debug_trap
509	bra	error_code
510
511ENTRY(ill_trap)
512	/* void ill_trap(void) */
513	SWITCH_TO_KERNEL_STACK
514	SAVE_ALL
515	ldi	r1, #0				; error_code ; FIXME
516	mv	r0, sp				; pt_regs
517	bl	do_ill_trap
518	bra	error_code
519
520ENTRY(cache_flushing_handler)
521	/* void _flush_cache_all(void); */
522	.global	_flush_cache_all
523	SWITCH_TO_KERNEL_STACK
524	push	r0
525	push	r1
526	push	r2
527	push	r3
528	push	r4
529	push	r5
530	push	r6
531	push	r7
532	push	lr
533	bl	_flush_cache_all
534	pop	lr
535	pop	r7
536	pop	r6
537	pop	r5
538	pop	r4
539	pop	r3
540	pop	r2
541	pop	r1
542	pop	r0
543	rte
544
545	.section .rodata,"a"
546#include "syscall_table.S"
547
548syscall_table_size=(.-sys_call_table)
v4.6
  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#include <asm/asm-offsets.h>
 69
 70#if !defined(CONFIG_MMU)
 71#define sys_madvise		sys_ni_syscall
 72#define sys_readahead		sys_ni_syscall
 73#define sys_mprotect		sys_ni_syscall
 74#define sys_msync		sys_ni_syscall
 75#define sys_mlock		sys_ni_syscall
 76#define sys_munlock		sys_ni_syscall
 77#define sys_mlockall		sys_ni_syscall
 78#define sys_munlockall		sys_ni_syscall
 79#define sys_mremap		sys_ni_syscall
 80#define sys_mincore		sys_ni_syscall
 81#define sys_remap_file_pages	sys_ni_syscall
 82#endif /* CONFIG_MMU */
 83
 84#define R4(reg)			@reg
 85#define R5(reg)			@(0x04,reg)
 86#define R6(reg)			@(0x08,reg)
 87#define PTREGS(reg)		@(0x0C,reg)
 88#define R0(reg)			@(0x10,reg)
 89#define R1(reg)			@(0x14,reg)
 90#define R2(reg)			@(0x18,reg)
 91#define R3(reg)			@(0x1C,reg)
 92#define R7(reg)			@(0x20,reg)
 93#define R8(reg)			@(0x24,reg)
 94#define R9(reg)			@(0x28,reg)
 95#define R10(reg)		@(0x2C,reg)
 96#define R11(reg)		@(0x30,reg)
 97#define R12(reg)		@(0x34,reg)
 98#define SYSCALL_NR(reg)		@(0x38,reg)
 99#define ACC0H(reg)		@(0x3C,reg)
100#define ACC0L(reg)		@(0x40,reg)
101#define ACC1H(reg)		@(0x44,reg)
102#define ACC1L(reg)		@(0x48,reg)
103#define PSW(reg)		@(0x4C,reg)
104#define BPC(reg)		@(0x50,reg)
105#define BBPSW(reg)		@(0x54,reg)
106#define BBPC(reg)		@(0x58,reg)
107#define SPU(reg)		@(0x5C,reg)
108#define FP(reg)			@(0x60,reg)  /* FP = R13 */
109#define LR(reg)			@(0x64,reg)
110#define SP(reg)			@(0x68,reg)
111#define ORIG_R0(reg)		@(0x6C,reg)
112
113#define nr_syscalls ((syscall_table_size)/4)
114
115#ifdef CONFIG_PREEMPT
116#define preempt_stop(x)		DISABLE_INTERRUPTS(x)
117#else
118#define preempt_stop(x)
119#define resume_kernel		restore_all
120#endif
121
122/* how to get the thread information struct from ASM */
123#define GET_THREAD_INFO(reg)	GET_THREAD_INFO reg
124	.macro GET_THREAD_INFO reg
125	ldi	\reg, #-THREAD_SIZE
126	and	\reg, sp
127	.endm
128
129ENTRY(ret_from_kernel_thread)
130	pop	r0
131	bl	schedule_tail
132	GET_THREAD_INFO(r8)
133	ld	r0, R0(r8)
134	ld	r1, R1(r8)
135	jl	r1
136	bra	syscall_exit
137
138ENTRY(ret_from_fork)
139	pop	r0
140	bl	schedule_tail
141	GET_THREAD_INFO(r8)
142	bra	syscall_exit
143
144/*
145 * Return to user mode is not as complex as all this looks,
146 * but we want the default path for a system call return to
147 * go as quickly as possible which is why some of this is
148 * less clear than it otherwise should be.
149 */
150
151	; userspace resumption stub bypassing syscall exit tracing
152	ALIGN
153ret_from_exception:
154	preempt_stop(r4)
155ret_from_intr:
156	ld	r4, PSW(sp)
157#ifdef CONFIG_ISA_M32R2
158	and3	r4, r4, #0x8800		; check BSM and BPM bits
159#else
160	and3	r4, r4, #0x8000		; check BSM bit
161#endif
162	beqz	r4, resume_kernel
163resume_userspace:
164	DISABLE_INTERRUPTS(r4)		; make sure we don't miss an interrupt
165					; setting need_resched or sigpending
166					; between sampling and the iret
167	GET_THREAD_INFO(r8)
168	ld	r9, @(TI_FLAGS, r8)
169	and3	r4, r9, #_TIF_WORK_MASK	; is there any work to be done on
170					; int/exception return?
171	bnez	r4, work_pending
172	bra	restore_all
173
174#ifdef CONFIG_PREEMPT
175ENTRY(resume_kernel)
176	GET_THREAD_INFO(r8)
177	ld	r9, @(TI_PRE_COUNT, r8)	; non-zero preempt_count ?
178	bnez	r9, restore_all
179need_resched:
180	ld	r9, @(TI_FLAGS, r8)	; need_resched set ?
181	and3	r4, r9, #_TIF_NEED_RESCHED
182	beqz	r4, restore_all
183	ld	r4, PSW(sp)		; interrupts off (exception path) ?
184	and3	r4, r4, #0x4000
185	beqz	r4, restore_all
186	bl	preempt_schedule_irq
 
 
 
 
 
 
187	bra	need_resched
188#endif
189
190	; system call handler stub
191ENTRY(system_call)
192	SWITCH_TO_KERNEL_STACK
193	SAVE_ALL
194	ENABLE_INTERRUPTS(r4)		; Enable interrupt
195	st	sp, PTREGS(sp)		; implicit pt_regs parameter
196	cmpui	r7, #NR_syscalls
197	bnc	syscall_badsys
198	st	r7, SYSCALL_NR(sp)	; syscall_nr
199					; system call tracing in operation
200	GET_THREAD_INFO(r8)
201	ld	r9, @(TI_FLAGS, r8)
202	and3	r4, r9, #_TIF_SYSCALL_TRACE
203	bnez	r4, syscall_trace_entry
204syscall_call:
205	slli	r7, #2			; table jump for the system call
206	LDIMM	(r4, sys_call_table)
207	add	r7, r4
208	ld	r7, @r7
209	jl	r7			; execute system call
210	st	r0, R0(sp)		; save the return value
211syscall_exit:
212	DISABLE_INTERRUPTS(r4)		; make sure we don't miss an interrupt
213					; setting need_resched or sigpending
214					; between sampling and the iret
215	ld	r9, @(TI_FLAGS, r8)
216	and3	r4, r9, #_TIF_ALLWORK_MASK	; current->work
217	bnez	r4, syscall_exit_work
218restore_all:
219	RESTORE_ALL
220
221	# perform work that needs to be done immediately before resumption
222	# r9 : flags
223	ALIGN
224work_pending:
225	and3	r4, r9, #_TIF_NEED_RESCHED
226	beqz	r4, work_notifysig
227work_resched:
228	bl	schedule
229	DISABLE_INTERRUPTS(r4)		; make sure we don't miss an interrupt
230					; setting need_resched or sigpending
231					; between sampling and the iret
232	ld	r9, @(TI_FLAGS, r8)
233	and3	r4, r9, #_TIF_WORK_MASK	; is there any work to be done other
234					; than syscall tracing?
235	beqz	r4, restore_all
236	and3	r4, r4, #_TIF_NEED_RESCHED
237	bnez	r4, work_resched
238
239work_notifysig:				; deal with pending signals and
240					; notify-resume requests
241	mv	r0, sp			; arg1 : struct pt_regs *regs
242	mv	r1, r9			; arg2 : __u32 thread_info_flags
243	bl	do_notify_resume
244	bra	resume_userspace
245
246	; perform syscall exit tracing
247	ALIGN
248syscall_trace_entry:
249	ldi	r4, #-ENOSYS
250	st	r4, R0(sp)
251	bl	do_syscall_trace
252	ld	r0, ORIG_R0(sp)
253	ld	r1, R1(sp)
254	ld	r2, R2(sp)
255	ld	r3, R3(sp)
256	ld	r4, R4(sp)
257	ld	r5, R5(sp)
258	ld	r6, R6(sp)
259	ld	r7, SYSCALL_NR(sp)
260	cmpui	r7, #NR_syscalls
261	bc	syscall_call
262	bra	syscall_exit
263
264	; perform syscall exit tracing
265	ALIGN
266syscall_exit_work:
267	ld	r9, @(TI_FLAGS, r8)
268	and3	r4, r9, #_TIF_SYSCALL_TRACE
269	beqz	r4, work_pending
270	ENABLE_INTERRUPTS(r4)		; could let do_syscall_trace() call
271					; schedule() instead
272	bl	do_syscall_trace
273	bra	resume_userspace
274
275	ALIGN
276syscall_fault:
277	SAVE_ALL
278	GET_THREAD_INFO(r8)
279	ldi	r4, #-EFAULT
280	st	r4, R0(sp)
281	bra	resume_userspace
282
283	ALIGN
284syscall_badsys:
285	ldi	r4, #-ENOSYS
286	st	r4, R0(sp)
287	bra	resume_userspace
288
289	.global	eit_vector
290
291	.equ ei_vec_table, eit_vector + 0x0200
292
293/*
294 * EI handler routine
295 */
296ENTRY(ei_handler)
297#if defined(CONFIG_CHIP_M32700)
298	; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
299	SWITCH_TO_KERNEL_STACK
300#endif
301	SAVE_ALL
302	mv	r1, sp			; arg1(regs)
303	; get ICU status
304	seth	r0, #shigh(M32R_ICU_ISTS_ADDR)
305	ld	r0, @(low(M32R_ICU_ISTS_ADDR),r0)
306	push	r0
307#if defined(CONFIG_SMP)
308	/*
309	 * If IRQ == 0      --> Nothing to do,  Not write IMASK
310	 * If IRQ == IPI    --> Do IPI handler, Not write IMASK
311	 * If IRQ != 0, IPI --> Do do_IRQ(),    Write IMASK
312	 */
313	slli	r0, #4
314	srli	r0, #24			; r0(irq_num<<2)
315	;; IRQ exist check
316#if defined(CONFIG_CHIP_M32700)
317	/* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
318	bnez	r0, 0f
319	ld24	r14, #0x00070000
320	seth	r0, #shigh(M32R_ICU_IMASK_ADDR)
321	st	r14, @(low(M32R_ICU_IMASK_ADDR),r0)
322	bra	1f
323	.fillinsn
3240:
325#endif /* CONFIG_CHIP_M32700 */
326	beqz	r0, 1f			; if (!irq_num) goto exit
327	;; IPI check
328	cmpi	r0, #(M32R_IRQ_IPI0<<2)	; ISN < IPI0 check
329	bc	2f
330	cmpi	r0, #((M32R_IRQ_IPI7+1)<<2)	; ISN > IPI7 check
331	bnc	2f
332	LDIMM	(r2, ei_vec_table)
333	add	r2, r0
334	ld	r2, @r2
335	beqz	r2, 1f			; if (no IPI handler) goto exit
336	mv	r0, r1			; arg0(regs)
337	jl	r2
338	.fillinsn
3391:
340	addi	sp, #4
341	bra	restore_all
342	.fillinsn
3432:
344	srli	r0, #2
345#else /* not CONFIG_SMP */
346	srli	r0, #22			; r0(irq)
347#endif /* not CONFIG_SMP */
348
349#if defined(CONFIG_PLAT_HAS_INT1ICU)
350	add3	r2, r0, #-(M32R_IRQ_INT1)	; INT1# interrupt
351	bnez	r2, 3f
352	seth	r0, #shigh(M32R_INT1ICU_ISTS)
353	lduh	r0, @(low(M32R_INT1ICU_ISTS),r0)	; bit10-6 : ISN
354	slli	r0, #21
355	srli	r0, #27				; ISN
356	addi	r0, #(M32R_INT1ICU_IRQ_BASE)
357	bra	check_end
358	.fillinsn
3593:
360#endif /* CONFIG_PLAT_HAS_INT1ICU */
361#if defined(CONFIG_PLAT_HAS_INT0ICU)
362	add3	r2, r0, #-(M32R_IRQ_INT0)	; INT0# interrupt
363	bnez	r2, 4f
364	seth	r0, #shigh(M32R_INT0ICU_ISTS)
365	lduh	r0, @(low(M32R_INT0ICU_ISTS),r0)	; bit10-6 : ISN
366	slli	r0, #21
367	srli	r0, #27				; ISN
368	add3	r0, r0, #(M32R_INT0ICU_IRQ_BASE)
369	bra	check_end
370	.fillinsn
3714:
372#endif /* CONFIG_PLAT_HAS_INT0ICU */
373#if defined(CONFIG_PLAT_HAS_INT2ICU)
374	add3	r2, r0, #-(M32R_IRQ_INT2)	; INT2# interrupt
375	bnez	r2, 5f
376	seth	r0, #shigh(M32R_INT2ICU_ISTS)
377	lduh	r0, @(low(M32R_INT2ICU_ISTS),r0)	; bit10-6 : ISN
378	slli	r0, #21
379	srli	r0, #27				; ISN
380	add3	r0, r0, #(M32R_INT2ICU_IRQ_BASE)
381	; bra	check_end
382	.fillinsn
3835:
384#endif /* CONFIG_PLAT_HAS_INT2ICU */
385
386check_end:
387	bl	do_IRQ
388	pop	r14
389	seth	r0, #shigh(M32R_ICU_IMASK_ADDR)
390	st	r14, @(low(M32R_ICU_IMASK_ADDR),r0)
391	bra  ret_from_intr
392
393/*
394 * Default EIT handler
395 */
396	ALIGN
397int_msg:
398	.asciz  "Unknown interrupt\n"
399	.byte	0
400
401ENTRY(default_eit_handler)
402	push	r0
403	mvfc	r0, psw
404	push	r1
405	push	r2
406	push	r3
407	push	r0
408	LDIMM	(r0, __KERNEL_DS)
409	mv	r0, r1
410	mv	r0, r2
411	LDIMM	(r0, int_msg)
412	bl	printk
413	pop	r0
414	pop	r3
415	pop	r2
416	pop	r1
417	mvtc	r0, psw
418	pop	r0
419infinit:
420	bra	infinit
421
422#ifdef CONFIG_MMU
423/*
424 * Access Exception handler
425 */
426ENTRY(ace_handler)
427	SWITCH_TO_KERNEL_STACK
428	SAVE_ALL
429
430	seth	r2, #shigh(MMU_REG_BASE)	/* Check status register */
431	ld	r4, @(low(MESTS_offset),r2)
432	st	r4, @(low(MESTS_offset),r2)
433	srl3	r1, r4, #4
434#ifdef CONFIG_CHIP_M32700
435	and3	r1, r1, #0x0000ffff
436	; WORKAROUND: ignore TME bit for the M32700(TS1).
437#endif /* CONFIG_CHIP_M32700 */
438	beqz	r1, inst
439oprand:
440	ld	r2, @(low(MDEVA_offset),r2)	; set address
441	srli	r1, #1
442	bra	1f
443inst:
444	and3	r1, r4, #2
445	srli	r1, #1
446	or3	r1, r1, #8
447	mvfc	r2, bpc				; set address
448	.fillinsn
4491:
450	mvfc	r3, psw
451	mv	r0, sp
452	and3	r3, r3, 0x800
453	srli	r3, #9
454	or	r1, r3
455	/*
456	 * do_page_fault():
457	 *    r0 : struct pt_regs *regs
458	 *    r1 : unsigned long error-code
459	 *    r2 : unsigned long address
460	 * error-code:
461	 *    +------+------+------+------+
462	 *    | bit3 | bit2 | bit1 | bit0 |
463	 *    +------+------+------+------+
464	 *    bit 3 == 0:means data,          1:means instruction
465	 *    bit 2 == 0:means kernel,        1:means user-mode
466	 *    bit 1 == 0:means read,          1:means write
467	 *    bit 0 == 0:means no page found  1:means protection fault
468	 *
469	 */
470	bl	do_page_fault
471	bra	ret_from_intr
472#endif  /* CONFIG_MMU */
473
474
475ENTRY(alignment_check)
476	/* void alignment_check(int error_code) */
477	SWITCH_TO_KERNEL_STACK
478	SAVE_ALL
479	ldi	r1, #0x30			; error_code
480	mv	r0, sp				; pt_regs
481	bl	do_alignment_check
482error_code:
483	bra	ret_from_exception
484
485ENTRY(rie_handler)
486	/* void rie_handler(int error_code) */
487	SWITCH_TO_KERNEL_STACK
488	SAVE_ALL
489	ldi	r1, #0x20			; error_code
490	mv	r0, sp				; pt_regs
491	bl	do_rie_handler
492	bra	error_code
493
494ENTRY(pie_handler)
495	/* void pie_handler(int error_code) */
496	SWITCH_TO_KERNEL_STACK
497	SAVE_ALL
498	ldi	r1, #0				; error_code ; FIXME
499	mv	r0, sp				; pt_regs
500	bl	do_pie_handler
501	bra	error_code
502
503ENTRY(debug_trap)
504	/* void debug_trap(void) */
505	.global	withdraw_debug_trap
506	SWITCH_TO_KERNEL_STACK
507	SAVE_ALL
508	mv	r0, sp				; pt_regs
509	bl	withdraw_debug_trap
510	ldi	r1, #0				; error_code
511	mv	r0, sp				; pt_regs
512	bl	do_debug_trap
513	bra	error_code
514
515ENTRY(ill_trap)
516	/* void ill_trap(void) */
517	SWITCH_TO_KERNEL_STACK
518	SAVE_ALL
519	ldi	r1, #0				; error_code ; FIXME
520	mv	r0, sp				; pt_regs
521	bl	do_ill_trap
522	bra	error_code
523
524ENTRY(cache_flushing_handler)
525	/* void _flush_cache_all(void); */
526	.global	_flush_cache_all
527	SWITCH_TO_KERNEL_STACK
528	push	r0
529	push	r1
530	push	r2
531	push	r3
532	push	r4
533	push	r5
534	push	r6
535	push	r7
536	push	lr
537	bl	_flush_cache_all
538	pop	lr
539	pop	r7
540	pop	r6
541	pop	r5
542	pop	r4
543	pop	r3
544	pop	r2
545	pop	r1
546	pop	r0
547	rte
548
549	.section .rodata,"a"
550#include "syscall_table.S"
551
552syscall_table_size=(.-sys_call_table)