📄 entry.s
字号:
.rept 255-224 .long sys_ni_syscall .endr/* * Program check handler routine */ .globl pgm_check_handlerpgm_check_handler:/* * First we need to check for a special case: * Single stepping an instruction that disables the PER event mask will * cause a PER event AFTER the mask has been set. Example: SVC or LPSW. * For a single stepped SVC the program check handler gets control after * the SVC new PSW has been loaded. But we want to execute the SVC first and * then handle the PER event. Therefore we update the SVC old PSW to point * to the pgm_check_handler and branch to the SVC handler after we checked * if we have to load the kernel stack register. * For every other possible cause for PER event without the PER mask set * we just ignore the PER event (FIXME: is there anything we have to do * for LPSW?). */ stm %r13,%r15,__LC_SAVE_AREA basr %r13,0 # temp base pointer l %r13,.Lentry_base-.(%r13)# load &entry_base to %r13 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception stam %a2,%a4,__LC_SAVE_AREA+12 bz BASED(pgm_sv) # skip if not tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on bnz BASED(pgm_sv) # skip if it is# ok its one of the special cases, now we need to find out which one clc __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW be BASED(pgm_svcper)# no interesting special case, ignore PER event lm %r13,%r15,__LC_SAVE_AREA lpsw 0x28# it was a single stepped SVC that is causing all the troublepgm_svcper: tm 0x21,0x01 # test problem state bit bz BASED(.+12) # skip stack & access regs setup l %r15,__LC_KERNEL_STACK # problem state -> load ksp lam %a2,%a4,BASED(.Lc_ac) # set ac.reg. 2 to primary space # and access reg. 4 to home space s %r15,BASED(.Lc_spsize) # make room for registers & psw n %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8 stm %r0,%r12,SP_R0(%r15) # store gprs 0-12 to kernel stack st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 mvc SP_R13(12,%r15),__LC_SAVE_AREA # move R13-R15 to stack stam %a0,%a15,SP_AREGS(%r15) # store access registers to kst. mvc SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs mvc SP_PSW(8,%r15),0x20 # move user PSW to stack la %r0,0x20 # store trap indication st %r0,SP_TRAP(%r15) xc 0(4,%r15),0(%r15) # clear back chain mvc SP_PGM_OLD_ILC(4,%r15),__LC_PGM_ILC # save program check information b BASED(pgm_system_call) # now do the svcpgm_svcret: mvi SP_TRAP+3(%r15),0x28 # set trap indication back to pgm_chk lh %r7,SP_PGM_OLD_ILC(%r15) # get ilc from stack mvi SP_PGM_OLD_ILC(%r15),1 # mark PGM_OLD_ILC as invalid b BASED(pgm_no_sv)pgm_sv: tm 0x29,0x01 # test problem state bit bz BASED(.+12) # skip stack & access regs setup l %r15,__LC_KERNEL_STACK # problem state -> load ksp lam %a2,%a4,BASED(.Lc_ac) # set ac.reg. 2 to primary space # and access reg. 4 to home space s %r15,BASED(.Lc_spsize) # make room for registers & psw n %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8 stm %r0,%r12,SP_R0(%r15) # store gprs 0-12 to kernel stack st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 mvc SP_R13(12,%r15),__LC_SAVE_AREA # move R13-R15 to stack stam %a0,%a15,SP_AREGS(%r15) # store access registers to kst. mvc SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs mvc SP_PSW(8,%r15),0x28 # move user PSW to stack la %r0,0x28 # store trap indication st %r0,SP_TRAP(%r15) xc 0(4,%r15),0(%r15) # clear back chain mvi SP_PGM_OLD_ILC(%r15),1 # mark PGM_OLD_ILC as invalid lh %r7,__LC_PGM_ILC # load instruction length GET_CURRENTpgm_no_sv: la %r3,0x7f lh %r8,__LC_PGM_INT_CODE # N.B. saved int code used later KEEP it nr %r3,%r8 # reload & clear per-event-bit be BASED(pgm_dn) # none of Martins exceptions occurred bypass l %r1,BASED(.Ljump_table) sll %r3,2 l %r1,0(%r3,%r1) # load address of handler routine la %r2,SP_PTREGS(%r15) # address of register-save area srl %r3,2 cl %r3,BASED(.Lc4) # protection-exception ? bne BASED(pgm_per) # if not, l %r5,SP_PSW+4(15) # load psw addr sr %r5,%r7 # substract ilc from psw st %r5,SP_PSW+4(15) # store corrected psw addrpgm_per:basr %r14,%r1 # branch to interrupt-handlerpgm_dn: n %r8,BASED(.Lc128) # check for per excepton be BASED(pgm_return) la %r2,SP_PTREGS(15) # address of register-save area l %r1,BASED(.Lhandle_per) # load adr. of per handler la %r14,BASED(sysc_return) # load adr. of system return br %r1 # branch to handle_per_exception## the backend code is the same as for sys-call#pgm_return: b BASED(sysc_return)/* * IO interrupt handler routine */ .globl io_int_handlerio_int_handler: SAVE_ALL __LC_IO_OLD_PSW,0 GET_CURRENT # load pointer to task_struct to R9 la %r2,SP_PTREGS(%r15) # address of register-save area sr %r3,%r3 icm %r3,%r3,__LC_SUBCHANNEL_NR # load subchannel nr & extend to int l %r4,__LC_IO_INT_PARM # load interuption parm l %r5,__LC_IO_INT_WORD # load interuption word l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ basr %r14,%r1 # branch to standard irq handlerio_return:## check, if bottom-half has to be done# l %r1,processor(%r9) # get cpu number from task struture sll %r1,L1_CACHE_SHIFT al %r1,BASED(.Lirq_stat) # get address of irq_stat icm %r0,15,0(%r1) # test irq_stat[#cpu].__softirq_pending bnz BASED(io_handle_bottom_half)io_return_bh: tm SP_PSW+1(%r15),0x01 # returning to user ? bno BASED(io_leave) # no-> skip resched & signal stosm 24(%r15),0x03 # reenable interrupts## check, if reschedule is needed# icm %r0,15,need_resched(%r9) # get need_resched from task_struct bnz BASED(io_reschedule) icm %r0,15,sigpending(%r9) # get sigpending from task_struct bnz BASED(io_signal_return)io_leave: stnsm 24(%r15),0xfc # disable I/O and ext. interrupts RESTORE_ALL 0## call do_softirq#io_handle_bottom_half: l %r1,BASED(.Ldo_softirq) la %r14,BASED(io_return_bh) br %r1 # call do_softirq## call schedule with io_return as return-address#io_reschedule: l %r1,BASED(.Lschedule) la %r14,BASED(io_return) br %r1 # call scheduler, return to io_return## call do_signal before return#io_signal_return: la %r2,SP_PTREGS(%r15) # load pt_regs sr %r3,%r3 # clear *oldset l %r1,BASED(.Ldo_signal) la %r14,BASED(io_leave) br %r1 # return point is io_leave/* * External interrupt handler routine */ .globl ext_int_handlerext_int_handler: SAVE_ALL __LC_EXT_OLD_PSW,0 GET_CURRENT # load pointer to task_struct to R9 la %r2,SP_PTREGS(%r15) # address of register-save area lh %r3,__LC_EXT_INT_CODE # error code lr %r1,%r3 # calculate index = code & 0xff n %r1,BASED(.Lc0xff) sll %r1,2 l %r4,BASED(.Lext_hash) l %r4,0(%r1,%r4) # get first list entry for hash value ltr %r4,%r4 # == NULL ? bz BASED(io_return) # yes, nothing to do, exitext_int_loop: ch %r3,8(%r4) # compare external interrupt code be BASED(ext_int_found) icm %r4,15,0(%r4) # next list entry bnz BASED(ext_int_loop) b BASED(io_return)ext_int_found: l %r4,4(%r4) # get handler address la %r14,BASED(io_return) br %r4 # branch to ext call handler/* * Machine check handler routines */ .globl mcck_int_handlermcck_int_handler: SAVE_ALL __LC_MCK_OLD_PSW,0 l %r1,BASED(.Ls390_mcck) basr %r14,%r1 # call machine check handlermcck_return: RESTORE_ALL 0#ifdef CONFIG_SMP/* * Restart interruption handler, kick starter for additional CPUs */ .globl restart_int_handlerrestart_int_handler: l %r15,__LC_SAVE_AREA+60 # load ksp lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs lam %a0,%a15,__LC_AREGS_SAVE_AREA stosm 0(%r15),0x04 # now we can turn dat on lm %r6,%r15,24(%r15) # load registers from clone basr %r14,0 l %r14,restart_addr-.(%r14) br %r14 # branch to start_secondaryrestart_addr: .long start_secondary#else/* * If we do not run with SMP enabled, let the new CPU crash ... */ .globl restart_int_handlerrestart_int_handler: basr %r1,0restart_base: lpsw restart_crash-restart_base(%r1) .align 8restart_crash: .long 0x000a0000,0x00000000restart_go:#endif/* * Integer constants */ .align 4.Lc0xfffffff8: .long -8 # to align stack pointer to 8.Lc0xffffe000: .long -8192 # to round stack pointer to &task_struct.Lc8191: .long 8191.Lc_spsize: .long SP_SIZE.Lc_overhead: .long STACK_FRAME_OVERHEAD.Lc_ac: .long 0,0,1.Lc_ENOSYS: .long -ENOSYS.Lc4: .long 4.Lc20: .long 20.Lc0x1202: .long 0x1202.Lc0x1004: .long 0x1004.Lc0x2401: .long 0x2401.Lc0x4000: .long 0x4000.Lc0xff: .long 0xff.Lc128: .long 128/* * Symbol constants */.Ls390_mcck: .long s390_do_machine_check.Ldo_IRQ: .long do_IRQ.Ldo_signal: .long do_signal.Ldo_softirq: .long do_softirq.Lentry_base: .long entry_base.Lext_hash: .long ext_int_hash.Lhandle_per: .long handle_per_exception.Lirq_stat: .long irq_stat.Ljump_table: .long pgm_check_table.Lschedule: .long schedule.Lclone: .long sys_clone.Lexecve: .long sys_execve.Lfork: .long sys_fork.Lrt_sigreturn:.long sys_rt_sigreturn.Lrt_sigsuspend: .long sys_rt_sigsuspend.Lsigreturn: .long sys_sigreturn.Lsigsuspend: .long sys_sigsuspend.Lsigaltstack: .long sys_sigaltstack.Ltrace: .long syscall_trace.Lvfork: .long sys_vfork#ifdef CONFIG_SMP.Lschedtail: .long schedule_tail#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -