📄 entry.s
字号:
/* * linux/arch/m32r/kernel/entry.S * * Copyright (c) 2001, 2002 Hirokazu Takata, Hitoshi Yamamoto, H. Kondo * Copyright (c) 2003 Hitoshi Yamamoto * Copyright (c) 2004 Hirokazu Takata <takata at linux-m32r.org> * * Taken from i386 version. * Copyright (C) 1991, 1992 Linus Torvalds *//* * entry.S contains the system-call and fault low-level handling routines. * This also contains the timer-interrupt handler, as well as all interrupts * and faults that can result in a task-switch. * * NOTE: This code handles signal-recognition, which happens every time * after a timer-interrupt and after each system call. * * Stack layout in 'ret_from_system_call': * ptrace needs to have all regs on the stack. * if the order here is changed, it needs to be * updated in fork.c:copy_process, signal.c:do_signal, * ptrace.c and ptrace.h * * M32Rx/M32R2 M32R * @(sp) - r4 ditto * @(0x04,sp) - r5 ditto * @(0x08,sp) - r6 ditto * @(0x0c,sp) - *pt_regs ditto * @(0x10,sp) - r0 ditto * @(0x14,sp) - r1 ditto * @(0x18,sp) - r2 ditto * @(0x1c,sp) - r3 ditto * @(0x20,sp) - r7 ditto * @(0x24,sp) - r8 ditto * @(0x28,sp) - r9 ditto * @(0x2c,sp) - r10 ditto * @(0x30,sp) - r11 ditto * @(0x34,sp) - r12 ditto * @(0x38,sp) - syscall_nr ditto * @(0x3c,sp) - acc0h @(0x3c,sp) - acch * @(0x40,sp) - acc0l @(0x40,sp) - accl * @(0x44,sp) - acc1h @(0x44,sp) - psw * @(0x48,sp) - acc1l @(0x48,sp) - bpc * @(0x4c,sp) - psw @(0x4c,sp) - bbpsw * @(0x50,sp) - bpc @(0x50,sp) - bbpc * @(0x54,sp) - bbpsw @(0x54,sp) - spu (cr3) * @(0x58,sp) - bbpc @(0x58,sp) - fp (r13) * @(0x5c,sp) - spu (cr3) @(0x5c,sp) - lr (r14) * @(0x60,sp) - fp (r13) @(0x60,sp) - spi (cr12) * @(0x64,sp) - lr (r14) @(0x64,sp) - orig_r0 * @(0x68,sp) - spi (cr2) * @(0x6c,sp) - orig_r0 * */#include <linux/config.h>#include <linux/linkage.h>#include <asm/irq.h>#include <asm/unistd.h>#include <asm/assembler.h>#include <asm/thread_info.h>#include <asm/errno.h>#include <asm/segment.h>#include <asm/smp.h>#include <asm/page.h>#include <asm/m32r.h>#include <asm/mmu_context.h>#if !defined(CONFIG_MMU)#define sys_madvise sys_ni_syscall#define sys_readahead sys_ni_syscall#define sys_mprotect sys_ni_syscall#define sys_msync sys_ni_syscall#define sys_mlock sys_ni_syscall#define sys_munlock sys_ni_syscall#define sys_mlockall sys_ni_syscall#define sys_munlockall sys_ni_syscall#define sys_mremap sys_ni_syscall#define sys_mincore sys_ni_syscall#define sys_remap_file_pages sys_ni_syscall#endif /* CONFIG_MMU */#define R4(reg) @reg#define R5(reg) @(0x04,reg)#define R6(reg) @(0x08,reg)#define PTREGS(reg) @(0x0C,reg)#define R0(reg) @(0x10,reg)#define R1(reg) @(0x14,reg)#define R2(reg) @(0x18,reg)#define R3(reg) @(0x1C,reg)#define R7(reg) @(0x20,reg)#define R8(reg) @(0x24,reg)#define R9(reg) @(0x28,reg)#define R10(reg) @(0x2C,reg)#define R11(reg) @(0x30,reg)#define R12(reg) @(0x34,reg)#define SYSCALL_NR(reg) @(0x38,reg)#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)#define ACC0H(reg) @(0x3C,reg)#define ACC0L(reg) @(0x40,reg)#define ACC1H(reg) @(0x44,reg)#define ACC1L(reg) @(0x48,reg)#define PSW(reg) @(0x4C,reg)#define BPC(reg) @(0x50,reg)#define BBPSW(reg) @(0x54,reg)#define BBPC(reg) @(0x58,reg)#define SPU(reg) @(0x5C,reg)#define FP(reg) @(0x60,reg) /* FP = R13 */#define LR(reg) @(0x64,reg)#define SP(reg) @(0x68,reg)#define ORIG_R0(reg) @(0x6C,reg)#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)#define ACCH(reg) @(0x3C,reg)#define ACCL(reg) @(0x40,reg)#define PSW(reg) @(0x44,reg)#define BPC(reg) @(0x48,reg)#define BBPSW(reg) @(0x4C,reg)#define BBPC(reg) @(0x50,reg)#define SPU(reg) @(0x54,reg)#define FP(reg) @(0x58,reg) /* FP = R13 */#define LR(reg) @(0x5C,reg)#define SP(reg) @(0x60,reg)#define ORIG_R0(reg) @(0x64,reg)#else#error unknown isa configuration#endifCF_MASK = 0x00000001TF_MASK = 0x00000100IF_MASK = 0x00000200DF_MASK = 0x00000400NT_MASK = 0x00004000VM_MASK = 0x00020000#ifdef CONFIG_PREEMPT#define preempt_stop(x) CLI(x)#else#define preempt_stop(x)#define resume_kernel restore_all#endifENTRY(ret_from_fork) ld r0, @sp+ bl schedule_tail GET_THREAD_INFO(r8) bra syscall_exit/* * Return to user mode is not as complex as all this looks, * but we want the default path for a system call return to * go as quickly as possible which is why some of this is * less clear than it otherwise should be. */ ; userspace resumption stub bypassing syscall exit tracing ALIGNret_from_exception: preempt_stop(r4)ret_from_intr: ld r4, PSW(sp)#ifdef CONFIG_ISA_M32R2 and3 r4, r4, #0x8800 ; check BSM and BPM bits#else and3 r4, r4, #0x8000 ; check BSM bit#endif beqz r4, resume_kernelENTRY(resume_userspace) CLI(r4) ; make sure we don't miss an interrupt ; setting need_resched or sigpending ; between sampling and the iret GET_THREAD_INFO(r8) ld r9, @(TI_FLAGS, r8) and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done on ; int/exception return? bnez r4, work_pending bra restore_all#ifdef CONFIG_PREEMPTENTRY(resume_kernel) GET_THREAD_INFO(r8) ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ? bnez r9, restore_allneed_resched: ld r9, @(TI_FLAGS, r8) ; need_resched set ? and3 r4, r9, #_TIF_NEED_RESCHED beqz r4, restore_all ld r4, PSW(sp) ; interrupts off (exception path) ? and3 r4, r4, #0x4000 beqz r4, restore_all LDIMM (r4, PREEMPT_ACTIVE) st r4, @(TI_PRE_COUNT, r8) STI(r4) bl schedule ldi r4, #0 st r4, @(TI_PRE_COUNT, r8) CLI(r4) bra need_resched#endif ; system call handler stubENTRY(system_call) SWITCH_TO_KERNEL_STACK SAVE_ALL STI(r4) ; Enable interrupt st sp, PTREGS(sp) ; implicit pt_regs parameter cmpui r7, #NR_syscalls bnc syscall_badsys st r7, SYSCALL_NR(sp) ; syscall_nr ; system call tracing in operation GET_THREAD_INFO(r8) ld r9, @(TI_FLAGS, r8) and3 r4, r9, #_TIF_SYSCALL_TRACE bnez r4, syscall_trace_entrysyscall_call: slli r7, #2 ; table jump for the system call LDIMM (r4, sys_call_table) add r7, r4 ld r7, @r7 jl r7 ; execute system call st r0, R0(sp) ; save the return valuesyscall_exit: CLI(r4) ; make sure we don't miss an interrupt ; setting need_resched or sigpending ; between sampling and the iret ld r9, @(TI_FLAGS, r8) and3 r4, r9, #_TIF_ALLWORK_MASK ; current->work bnez r4, syscall_exit_workrestore_all: RESTORE_ALL # perform work that needs to be done immediately before resumption # r9 : frags ALIGNwork_pending: and3 r4, r9, #_TIF_NEED_RESCHED beqz r4, work_notifysigwork_resched: bl schedule CLI(r4) ; make sure we don't miss an interrupt ; setting need_resched or sigpending ; between sampling and the iret ld r9, @(TI_FLAGS, r8) and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done other ; than syscall tracing? beqz r4, restore_all and3 r4, r4, #_TIF_NEED_RESCHED bnez r4, work_reschedwork_notifysig: ; deal with pending signals and ; notify-resume requests mv r0, sp ; arg1 : struct pt_regs *regs ldi r1, #0 ; arg2 : sigset_t *oldset mv r2, r9 ; arg3 : __u32 thread_info_flags bl do_notify_resume bra restore_all ; perform syscall exit tracing ALIGNsyscall_trace_entry: ldi r4, #-ENOSYS st r4, R0(sp) bl do_syscall_trace ld r0, ORIG_R0(sp) ld r1, R1(sp) ld r2, R2(sp) ld r3, R3(sp) ld r4, R4(sp) ld r5, R5(sp) ld r6, R6(sp) ld r7, SYSCALL_NR(sp) cmpui r7, #NR_syscalls bc syscall_call bra syscall_exit ; perform syscall exit tracing ALIGNsyscall_exit_work: ld r9, @(TI_FLAGS, r8) and3 r4, r9, #_TIF_SYSCALL_TRACE beqz r4, work_pending STI(r4) ; could let do_syscall_trace() call ; schedule() instead bl do_syscall_trace bra resume_userspace ALIGNsyscall_fault: SAVE_ALL GET_THREAD_INFO(r8) ldi r4, #-EFAULT st r4, R0(sp) bra resume_userspace ALIGNsyscall_badsys: ldi r4, #-ENOSYS st r4, R0(sp) bra resume_userspace .global eit_vector .equ ei_vec_table, eit_vector + 0x0200/* * EI handler routine */ENTRY(ei_handler)#if defined(CONFIG_CHIP_M32700) SWITCH_TO_KERNEL_STACK ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).#endif SAVE_ALL mv r1, sp ; arg1(regs)#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \ || defined(CONFIG_CHIP_OPSP); GET_ICU_STATUS; seth r0, #shigh(M32R_ICU_ISTS_ADDR) ld r0, @(low(M32R_ICU_ISTS_ADDR),r0) st r0, @-sp#if defined(CONFIG_SMP) /* * If IRQ == 0 --> Nothing to do, Not write IMASK * If IRQ == IPI --> Do IPI handler, Not write IMASK * If IRQ != 0, IPI --> Do do_IRQ(), Write IMASK */ slli r0, #4 srli r0, #24 ; r0(irq_num<<2) ;; IRQ exist check#if defined(CONFIG_CHIP_M32700) /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */ beqz r0, 3f ; if (!irq_num) goto exit#else beqz r0, 1f ; if (!irq_num) goto exit#endif /* WORKAROUND */ ;; IPI check cmpi r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check bc 2f cmpi r0, #((M32R_IRQ_IPI7+1)<<2) ; ISN > IPI7 check bnc 2f LDIMM (r2, ei_vec_table) add r2, r0 ld r2, @r2 beqz r2, 1f ; if (no IPI handler) goto exit mv r0, r1 ; arg0(regs) jl r2 .fillinsn1: addi sp, #4 bra ret_to_intr#if defined(CONFIG_CHIP_M32700) /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */ .fillinsn3: ld24 r14, #0x00070000 seth r0, #shigh(M32R_ICU_IMASK_ADDR) st r14, @(low(M32R_ICU_IMASK_ADDR), r0) addi sp, #4 bra ret_to_intr#endif /* WORKAROUND */ ;; do_IRQ .fillinsn2: srli r0, #2#if defined(CONFIG_PLAT_USRV) add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt bnez r2, 9f ; read ICU status register of PLD seth r0, #high(PLD_ICUISTS) or3 r0, r0, #low(PLD_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN addi r0, #(M32700UT_PLD_IRQ_BASE) .fillinsn9:#elif defined(CONFIG_PLAT_M32700UT) add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt bnez r2, check_int0 ; read ICU status register of PLD seth r0, #high(PLD_ICUISTS) or3 r0, r0, #low(PLD_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN addi r0, #(M32700UT_PLD_IRQ_BASE) bra check_end .fillinsncheck_int0: add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt bnez r2, check_int2 ; read ICU status of LAN-board seth r0, #high(M32700UT_LAN_ICUISTS) or3 r0, r0, #low(M32700UT_LAN_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN add3 r0, r0, #(M32700UT_LAN_PLD_IRQ_BASE) bra check_end .fillinsncheck_int2: add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt bnez r2, check_end ; read ICU status of LCD-board seth r0, #high(M32700UT_LCD_ICUISTS) or3 r0, r0, #low(M32700UT_LCD_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN add3 r0, r0, #(M32700UT_LCD_PLD_IRQ_BASE) bra check_end .fillinsncheck_end:#elif defined(CONFIG_PLAT_OPSPUT) add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt bnez r2, check_int0 ; read ICU status register of PLD seth r0, #high(PLD_ICUISTS) or3 r0, r0, #low(PLD_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN addi r0, #(OPSPUT_PLD_IRQ_BASE) bra check_end .fillinsncheck_int0: add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt bnez r2, check_int2 ; read ICU status of LAN-board seth r0, #high(OPSPUT_LAN_ICUISTS) or3 r0, r0, #low(OPSPUT_LAN_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN add3 r0, r0, #(OPSPUT_LAN_PLD_IRQ_BASE) bra check_end .fillinsncheck_int2: add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt bnez r2, check_end ; read ICU status of LCD-board seth r0, #high(OPSPUT_LCD_ICUISTS) or3 r0, r0, #low(OPSPUT_LCD_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN add3 r0, r0, #(OPSPUT_LCD_PLD_IRQ_BASE) bra check_end .fillinsncheck_end:#endif /* CONFIG_PLAT_OPSPUT */ bl do_IRQ ; r0(irq), r1(regs)#else /* not CONFIG_SMP */ srli r0, #22 ; r0(irq)#if defined(CONFIG_PLAT_USRV) add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt bnez r2, 1f ; read ICU status register of PLD seth r0, #high(PLD_ICUISTS) or3 r0, r0, #low(PLD_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN addi r0, #(M32700UT_PLD_IRQ_BASE) .fillinsn1:#elif defined(CONFIG_PLAT_M32700UT) add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt bnez r2, check_int0 ; read ICU status register of PLD seth r0, #high(PLD_ICUISTS) or3 r0, r0, #low(PLD_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN addi r0, #(M32700UT_PLD_IRQ_BASE) bra check_end .fillinsncheck_int0: add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt bnez r2, check_int2 ; read ICU status of LAN-board seth r0, #high(M32700UT_LAN_ICUISTS) or3 r0, r0, #low(M32700UT_LAN_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN add3 r0, r0, #(M32700UT_LAN_PLD_IRQ_BASE) bra check_end .fillinsncheck_int2: add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt bnez r2, check_end ; read ICU status of LCD-board seth r0, #high(M32700UT_LCD_ICUISTS) or3 r0, r0, #low(M32700UT_LCD_ICUISTS) lduh r0, @r0 slli r0, #21 srli r0, #27 ; ISN add3 r0, r0, #(M32700UT_LCD_PLD_IRQ_BASE) bra check_end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -