📄 entry.s
字号:
.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?). */ SAVE_ALL_BASE tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception bnz BASED(pgm_per) # got per exception -> special case SAVE_ALL __LC_PGM_OLD_PSW,1 l %r7,BASED(.Ljump_table) lh %r8,__LC_PGM_INT_CODE sll %r8,2 GET_CURRENT l %r7,0(%r8,%r7) # load address of handler routine la %r2,SP_PTREGS(%r15) # address of register-save area l %r3,__LC_PGM_ILC # load program interruption code la %r14,BASED(sysc_return) br %r7 # branch to interrupt-handler## handle per exception#pgm_per: tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on bnz BASED(pgm_per_std) # ok, normal per event from user space# 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## Normal per exception#pgm_per_std: SAVE_ALL __LC_PGM_OLD_PSW,1 GET_CURRENT la %r4,0x7f l %r3,__LC_PGM_ILC # load program interruption code nr %r4,%r3 # clear per-event-bit and ilc be BASED(pgm_per_only) # only per or per+check ? l %r1,BASED(.Ljump_table) sll %r4,2 l %r1,0(%r4,%r1) # load address of handler routine la %r2,SP_PTREGS(%r15) # address of register-save area basr %r14,%r1 # branch to interrupt-handlerpgm_per_only: 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## it was a single stepped SVC that is causing all the trouble#pgm_svcper: SAVE_ALL __LC_SVC_OLD_PSW,1 GET_CURRENT # load pointer to task_struct to R9 lh %r8,0x8a # get svc number from lowcore sll %r8,2 stosm 24(%r15),0x03 # reenable interrupts l %r8,sys_call_table-entry_base(%r8,%r13) # get system call addr. tm __TASK_ptrace+3(%r9),0x02 # PT_TRACESYS bnz BASED(pgm_tracesys) basr %r14,%r8 # call sys_xxxx st %r2,SP_R2(%r15) # store return value (change R2 on stack) # ATTENTION: check sys_execve_glue before # changing anything here !!pgm_svcret: icm %r0,15,__TASK_sigpending(%r9) bz BASED(pgm_svcper_nosig) la %r2,SP_PTREGS(%r15) # load pt_regs sr %r3,%r3 # clear *oldset l %r1,BASED(.Ldo_signal) basr %r4,%r1 # call do_signal pgm_svcper_nosig: mvi SP_TRAP+3(%r15),0x28 # set trap indication to pgm check 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## call trace before and after sys_call#pgm_tracesys: la %r12,BASED(pgm_svcret) b BASED(trace_svc)/* * IO interrupt handler routine */ .globl io_int_handlerio_int_handler: SAVE_ALL_BASE SAVE_ALL __LC_IO_OLD_PSW,0 GET_CURRENT # load pointer to task_struct to R9 l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ la %r2,SP_PTREGS(%r15) # address of register-save area sr %r3,%r3 icm %r3,3,__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 basr %r14,%r1 # branch to standard irq handlerio_return:## check, if bottom-half has to be done# l %r1,__TASK_processor(%r9) 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,__TASK_need_resched(%r9) bnz BASED(io_reschedule) icm %r0,15,__TASK_sigpending(%r9) 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_BASE 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_BASE 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.Lschedtail: .long schedule_tail
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -