2 * linux/arch/m32r/kernel/entry.S
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>
8 * Taken from i386 version.
9 * Copyright (C) 1991, 1992 Linus Torvalds
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.
17 * NOTE: This code handles signal-recognition, which happens every time
18 * after a timer-interrupt and after each system call.
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
30 * @(0x0c,sp) - *pt_regs
41 * @(0x38,sp) - syscall_nr
44 * @(0x44,sp) - acc1h ; ISA_DSP_LEVEL2 only
45 * @(0x48,sp) - acc1l ; ISA_DSP_LEVEL2 only
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
57 #include <linux/linkage.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>
67 #include <asm/mmu_context.h>
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 */
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)
119 #ifdef CONFIG_PREEMPT
120 #define preempt_stop(x) CLI(x)
122 #define preempt_stop(x)
123 #define resume_kernel restore_all
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.
139 ; userspace resumption stub bypassing syscall exit tracing
145 #ifdef CONFIG_ISA_M32R2
146 and3 r4, r4, #0x8800 ; check BSM and BPM bits
148 and3 r4, r4, #0x8000 ; check BSM bit
150 beqz r4, resume_kernel
151 ENTRY(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
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
162 #ifdef CONFIG_PREEMPT
165 ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
168 ld r9, @(TI_FLAGS, r8) ; need_resched set ?
169 and3 r4, r9, #_TIF_NEED_RESCHED
171 ld r4, PSW(sp) ; interrupts off (exception path) ?
174 LDIMM (r4, PREEMPT_ACTIVE)
175 st r4, @(TI_PRE_COUNT, r8)
179 st r4, @(TI_PRE_COUNT, r8)
184 ; system call handler stub
186 SWITCH_TO_KERNEL_STACK
188 STI(r4) ; Enable interrupt
189 st sp, PTREGS(sp) ; implicit pt_regs parameter
190 cmpui r7, #NR_syscalls
192 st r7, SYSCALL_NR(sp) ; syscall_nr
193 ; system call tracing in operation
195 ld r9, @(TI_FLAGS, r8)
196 and3 r4, r9, #_TIF_SYSCALL_TRACE
197 bnez r4, syscall_trace_entry
199 slli r7, #2 ; table jump for the system call
200 LDIMM (r4, sys_call_table)
203 jl r7 ; execute system call
204 st r0, R0(sp) ; save the return value
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
215 # perform work that needs to be done immediately before resumption
219 and3 r4, r9, #_TIF_NEED_RESCHED
220 beqz r4, work_notifysig
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?
230 and3 r4, r4, #_TIF_NEED_RESCHED
231 bnez r4, work_resched
233 work_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
241 ; perform syscall exit tracing
254 ld r7, SYSCALL_NR(sp)
255 cmpui r7, #NR_syscalls
259 ; perform syscall exit tracing
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
286 .equ ei_vec_table, eit_vector + 0x0200
292 #if defined(CONFIG_CHIP_M32700)
293 ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
294 SWITCH_TO_KERNEL_STACK
297 mv r1, sp ; arg1(regs)
299 seth r0, #shigh(M32R_ICU_ISTS_ADDR)
300 ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
302 #if defined(CONFIG_SMP)
304 * If IRQ == 0 --> Nothing to do, Not write IMASK
305 * If IRQ == IPI --> Do IPI handler, Not write IMASK
306 * If IRQ != 0, IPI --> Do do_IRQ(), Write IMASK
309 srli r0, #24 ; r0(irq_num<<2)
311 #if defined(CONFIG_CHIP_M32700)
312 /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
314 ld24 r14, #0x00070000
315 seth r0, #shigh(M32R_ICU_IMASK_ADDR)
316 st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
320 #endif /* CONFIG_CHIP_M32700 */
321 beqz r0, 1f ; if (!irq_num) goto exit
323 cmpi r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check
325 cmpi r0, #((M32R_IRQ_IPI7+1)<<2) ; ISN > IPI7 check
327 LDIMM (r2, ei_vec_table)
330 beqz r2, 1f ; if (no IPI handler) goto exit
331 mv r0, r1 ; arg0(regs)
340 #else /* not CONFIG_SMP */
341 srli r0, #22 ; r0(irq)
342 #endif /* not CONFIG_SMP */
344 #if defined(CONFIG_PLAT_HAS_INT1ICU)
345 add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
347 seth r0, #shigh(M32R_INT1ICU_ISTS)
348 lduh r0, @(low(M32R_INT1ICU_ISTS),r0) ; bit10-6 : ISN
351 addi r0, #(M32R_INT1ICU_IRQ_BASE)
355 #endif /* CONFIG_PLAT_HAS_INT1ICU */
356 #if defined(CONFIG_PLAT_HAS_INT0ICU)
357 add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt
359 seth r0, #shigh(M32R_INT0ICU_ISTS)
360 lduh r0, @(low(M32R_INT0ICU_ISTS),r0) ; bit10-6 : ISN
363 addi r0, #(M32R_INT0ICU_IRQ_BASE)
367 #endif /* CONFIG_PLAT_HAS_INT0ICU */
368 #if defined(CONFIG_PLAT_HAS_INT2ICU)
369 add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt
371 seth r0, #shigh(M32R_INT2ICU_ISTS)
372 lduh r0, @(low(M32R_INT2ICU_ISTS),r0) ; bit10-6 : ISN
375 addi r0, #(M32R_INT2ICU_IRQ_BASE)
379 #endif /* CONFIG_PLAT_HAS_INT2ICU */
383 seth r0, #shigh(M32R_ICU_IMASK_ADDR)
384 st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
389 * Default EIT handler
393 .asciz "Unknown interrupt\n"
396 ENTRY(default_eit_handler)
403 LDIMM (r0, __KERNEL_DS)
419 * Access Exception handler
422 SWITCH_TO_KERNEL_STACK
425 seth r2, #shigh(MMU_REG_BASE) /* Check status register */
426 ld r4, @(low(MESTS_offset),r2)
427 st r4, @(low(MESTS_offset),r2)
429 #ifdef CONFIG_CHIP_M32700
430 and3 r1, r1, #0x0000ffff
431 ; WORKAROUND: ignore TME bit for the M32700(TS1).
432 #endif /* CONFIG_CHIP_M32700 */
435 ld r2, @(low(MDEVA_offset),r2) ; set address
442 mvfc r2, bpc ; set address
452 * r0 : struct pt_regs *regs
453 * r1 : unsigned long error-code
454 * r2 : unsigned long address
456 * +------+------+------+------+
457 * | bit3 | bit2 | bit1 | bit0 |
458 * +------+------+------+------+
459 * bit 3 == 0:means data, 1:means instruction
460 * bit 2 == 0:means kernel, 1:means user-mode
461 * bit 1 == 0:means read, 1:means write
462 * bit 0 == 0:means no page found 1:means protection fault
467 #endif /* CONFIG_MMU */
470 ENTRY(alignment_check)
471 /* void alignment_check(int error_code) */
472 SWITCH_TO_KERNEL_STACK
474 ldi r1, #0x30 ; error_code
476 bl do_alignment_check
478 bra ret_from_exception
481 /* void rie_handler(int error_code) */
482 SWITCH_TO_KERNEL_STACK
484 ldi r1, #0x20 ; error_code
490 /* void pie_handler(int error_code) */
491 SWITCH_TO_KERNEL_STACK
493 ldi r1, #0 ; error_code ; FIXME
499 .global withdraw_debug_trap
500 /* void debug_trap(void) */
501 SWITCH_TO_KERNEL_STACK
504 bl withdraw_debug_trap
505 ldi r1, #0 ; error_code
511 /* void ill_trap(void) */
512 SWITCH_TO_KERNEL_STACK
514 ldi r1, #0 ; error_code ; FIXME
520 /* Cache flushing handler */
521 ENTRY(cache_flushing_handler)
522 .global _flush_cache_all
523 /* void _flush_cache_all(void); */
524 SWITCH_TO_KERNEL_STACK
547 ENTRY(sys_call_table)
548 .long sys_restart_syscall /* 0 - old "setup()" system call*/
553 .long sys_open /* 5 */
558 .long sys_unlink /* 10 */
563 .long sys_chmod /* 15 */
564 .long sys_ni_syscall /* lchown16 syscall holder */
565 .long sys_ni_syscall /* old break syscall holder */
566 .long sys_ni_syscall /* old stat syscall holder */
568 .long sys_getpid /* 20 */
571 .long sys_ni_syscall /* setuid16 syscall holder */
572 .long sys_ni_syscall /* getuid16 syscall holder */
573 .long sys_stime /* 25 */
576 .long sys_ni_syscall /* old fstat syscall holder */
578 .long sys_utime /* 30 */
579 .long sys_ni_syscall /* old stty syscall holder */
580 .long sys_cachectl /* for M32R */ /* old gtty syscall holder */
582 .long sys_ni_syscall /* nice syscall holder */
583 .long sys_ni_syscall /* 35 - old ftime syscall holder */
588 .long sys_rmdir /* 40 */
592 .long sys_ni_syscall /* old prof syscall holder */
593 .long sys_brk /* 45 */
594 .long sys_ni_syscall /* setgid16 syscall holder */
595 .long sys_getgid /* will be unused */
596 .long sys_ni_syscall /* signal syscall holder */
597 .long sys_ni_syscall /* geteuid16 syscall holder */
598 .long sys_ni_syscall /* 50 - getegid16 syscall holder */
600 .long sys_umount /* recycled never used phys() */
601 .long sys_ni_syscall /* old lock syscall holder */
603 .long sys_fcntl /* 55 - will be unused */
604 .long sys_ni_syscall /* mpx syscall holder */
606 .long sys_ni_syscall /* old ulimit syscall holder */
607 .long sys_ni_syscall /* sys_olduname */
608 .long sys_umask /* 60 */
613 .long sys_getpgrp /* 65 */
615 .long sys_ni_syscall /* sigaction syscall holder */
616 .long sys_ni_syscall /* sgetmask syscall holder */
617 .long sys_ni_syscall /* ssetmask syscall holder */
618 .long sys_ni_syscall /* 70 - setreuid16 syscall holder */
619 .long sys_ni_syscall /* setregid16 syscall holder */
620 .long sys_ni_syscall /* sigsuspend syscall holder */
621 .long sys_ni_syscall /* sigpending syscall holder */
622 .long sys_sethostname
623 .long sys_setrlimit /* 75 */
624 .long sys_getrlimit/*will be unused*/
626 .long sys_gettimeofday
627 .long sys_settimeofday
628 .long sys_ni_syscall /* 80 - getgroups16 syscall holder */
629 .long sys_ni_syscall /* setgroups16 syscall holder */
630 .long sys_ni_syscall /* sys_oldselect */
632 .long sys_ni_syscall /* old lstat syscall holder */
633 .long sys_readlink /* 85 */
637 .long sys_ni_syscall /* readdir syscall holder */
638 .long sys_ni_syscall /* 90 - old_mmap syscall holder */
643 .long sys_ni_syscall /* 95 - fchwon16 syscall holder */
644 .long sys_getpriority
645 .long sys_setpriority
646 .long sys_ni_syscall /* old profil syscall holder */
648 .long sys_fstatfs /* 100 */
649 .long sys_ni_syscall /* ioperm syscall holder */
653 .long sys_getitimer /* 105 */
657 .long sys_ni_syscall /* old uname syscall holder */
658 .long sys_ni_syscall /* 110 - iopl syscall holder */
660 .long sys_ni_syscall /* idle syscall holder */
661 .long sys_ni_syscall /* vm86old syscall holder */
663 .long sys_swapoff /* 115 */
667 .long sys_ni_syscall /* sigreturn syscall holder */
668 .long sys_clone /* 120 */
669 .long sys_setdomainname
671 .long sys_ni_syscall /* modify_ldt syscall holder */
673 .long sys_mprotect /* 125 */
674 .long sys_ni_syscall /* sigprocmask syscall holder */
675 .long sys_ni_syscall /* create_module syscall holder */
676 .long sys_init_module
677 .long sys_delete_module
678 .long sys_ni_syscall /* 130 - get_kernel_syms */
683 .long sys_sysfs /* 135 */
684 .long sys_personality
685 .long sys_ni_syscall /* afs_syscall syscall holder */
686 .long sys_ni_syscall /* setfsuid16 syscall holder */
687 .long sys_ni_syscall /* setfsgid16 syscall holder */
688 .long sys_llseek /* 140 */
693 .long sys_readv /* 145 */
698 .long sys_mlock /* 150 */
702 .long sys_sched_setparam
703 .long sys_sched_getparam /* 155 */
704 .long sys_sched_setscheduler
705 .long sys_sched_getscheduler
706 .long sys_sched_yield
707 .long sys_sched_get_priority_max
708 .long sys_sched_get_priority_min /* 160 */
709 .long sys_sched_rr_get_interval
712 .long sys_ni_syscall /* setresuid16 syscall holder */
713 .long sys_ni_syscall /* 165 - getresuid16 syscall holder */
714 .long sys_tas /* vm86 syscall holder */
715 .long sys_ni_syscall /* query_module syscall holder */
718 .long sys_setresgid /* 170 */
721 .long sys_rt_sigreturn
722 .long sys_rt_sigaction
723 .long sys_rt_sigprocmask /* 175 */
724 .long sys_rt_sigpending
725 .long sys_rt_sigtimedwait
726 .long sys_rt_sigqueueinfo
727 .long sys_rt_sigsuspend
728 .long sys_pread64 /* 180 */
730 .long sys_ni_syscall /* chown16 syscall holder */
733 .long sys_capset /* 185 */
734 .long sys_sigaltstack
736 .long sys_ni_syscall /* streams1 */
737 .long sys_ni_syscall /* streams2 */
738 .long sys_vfork /* 190 */
742 .long sys_ftruncate64
743 .long sys_stat64 /* 195 */
748 .long sys_getgid /* 200 */
753 .long sys_getgroups /* 205 */
758 .long sys_setresgid /* 210 */
763 .long sys_setfsuid /* 215 */
768 .long sys_getdents64 /* 220 */
770 .long sys_ni_syscall /* reserved for TUX */
771 .long sys_ni_syscall /* Reserved for Security */
773 .long sys_readahead /* 225 */
778 .long sys_lgetxattr /* 230 */
783 .long sys_removexattr /* 235 */
784 .long sys_lremovexattr
785 .long sys_fremovexattr
788 .long sys_futex /* 240 */
789 .long sys_sched_setaffinity
790 .long sys_sched_getaffinity
791 .long sys_ni_syscall /* reserved for "set_thread_area" system call */
792 .long sys_ni_syscall /* reserved for "get_thread_area" system call */
793 .long sys_io_setup /* 245 */
795 .long sys_io_getevents
798 .long sys_fadvise64 /* 250 */
801 .long sys_lookup_dcookie
802 .long sys_epoll_create
803 .long sys_epoll_ctl /* 255 */
805 .long sys_remap_file_pages
806 .long sys_set_tid_address
807 .long sys_timer_create
808 .long sys_timer_settime /* 260 */
809 .long sys_timer_gettime
810 .long sys_timer_getoverrun
811 .long sys_timer_delete
812 .long sys_clock_settime
813 .long sys_clock_gettime /* 265 */
814 .long sys_clock_getres
815 .long sys_clock_nanosleep
818 .long sys_tgkill /* 270 */
820 .long sys_fadvise64_64
821 .long sys_ni_syscall /* Reserved for sys_vserver */
822 .long sys_ni_syscall /* Reserved for sys_mbind */
823 .long sys_ni_syscall /* Reserved for sys_get_mempolicy */
824 .long sys_ni_syscall /* Reserved for sys_set_mempolicy */
827 .long sys_mq_timedsend
828 .long sys_mq_timedreceive /* 280 */
830 .long sys_mq_getsetattr
831 .long sys_ni_syscall /* reserved for kexec */
834 syscall_table_size=(.-sys_call_table)