📄 entry.s
字号:
sysc_singlestep: ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check la %r2,SP_PTREGS(%r15) # 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 do_single_step## call trace before and after sys_call#sysc_tracesys: l %r1,BASED(.Ltrace) la %r2,SP_PTREGS(%r15) # load pt_regs la %r3,0 srl %r7,2 st %r7,SP_R2(%r15) basr %r14,%r1 clc SP_R2(4,%r15),BASED(.Lnr_syscalls) bnl BASED(sysc_tracenogo) l %r8,BASED(.Lsysc_table) l %r7,SP_R2(%r15) # strace might have changed the sll %r7,2 # system call l %r8,0(%r7,%r8)sysc_tracego: lm %r3,%r6,SP_R3(%r15) l %r2,SP_ORIG_R2(%r15) basr %r14,%r8 # call sys_xxx st %r2,SP_R2(%r15) # store return valuesysc_tracenogo: tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) bz BASED(sysc_return) l %r1,BASED(.Ltrace) la %r2,SP_PTREGS(%r15) # load pt_regs la %r3,1 la %r14,BASED(sysc_return) br %r1## a new process exits the kernel with ret_from_fork# .globl ret_from_forkret_from_fork: l %r13,__LC_SVC_NEW_PSW+4 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct tm SP_PSW+1(%r15),0x01 # forking a kernel thread ? bo BASED(0f) st %r15,SP_R15(%r15) # store stack pointer for new kthread0: l %r1,BASED(.Lschedtail) basr %r14,%r1 TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts b BASED(sysc_return)## kernel_execve function needs to deal with pt_regs that is not# at the usual place# .globl kernel_execvekernel_execve: stm %r12,%r15,48(%r15) lr %r14,%r15 l %r13,__LC_SVC_NEW_PSW+4 s %r15,BASED(.Lc_spsize) st %r14,__SF_BACKCHAIN(%r15) la %r12,SP_PTREGS(%r15) xc 0(__PT_SIZE,%r12),0(%r12) l %r1,BASED(.Ldo_execve) lr %r5,%r12 basr %r14,%r1 ltr %r2,%r2 be BASED(0f) a %r15,BASED(.Lc_spsize) lm %r12,%r15,48(%r15) br %r14 # execve succeeded.0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts l %r15,__LC_KERNEL_STACK # load ksp s %r15,BASED(.Lc_spsize) # make room for registers & psw l %r9,__LC_THREAD_INFO mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) stosm __SF_EMPTY(%r15),0x03 # reenable interrupts l %r1,BASED(.Lexecve_tail) basr %r14,%r1 b BASED(sysc_return)/* * 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?). */ STORE_TIMER __LC_SYNC_ENTER_TIMER SAVE_ALL_BASE __LC_SAVE_AREA 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_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA#ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? bz BASED(pgm_no_vtime) UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMERpgm_no_vtime:#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct TRACE_IRQS_OFF l %r3,__LC_PGM_ILC # load program interruption code la %r8,0x7f nr %r8,%r3pgm_do_call: l %r7,BASED(.Ljump_table) sll %r8,2 l %r7,0(%r8,%r7) # load address of handler routine la %r2,SP_PTREGS(%r15) # address of register-save area 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 %r12,%r15,__LC_SAVE_AREA lpsw 0x28## Normal per exception#pgm_per_std: SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA#ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? bz BASED(pgm_no_vtime2) UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMERpgm_no_vtime2:#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct TRACE_IRQS_OFF l %r1,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP tm SP_PSW+1(%r15),0x01 # kernel per event ? bz BASED(kernel_per) l %r3,__LC_PGM_ILC # load program interruption code la %r8,0x7f nr %r8,%r3 # clear per-event-bit and ilc be BASED(sysc_return) # only per or per+check ? b BASED(pgm_do_call)## it was a single stepped SVC that is causing all the trouble#pgm_svcper: SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA#ifdef CONFIG_VIRT_CPU_ACCOUNTING UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER#endif lh %r7,0x8a # get svc number from lowcore l %r9,__LC_THREAD_INFO # load pointer to thread_info struct TRACE_IRQS_OFF l %r1,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts b BASED(sysc_do_svc)## per was called from kernel, must be kprobes#kernel_per: mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check la %r2,SP_PTREGS(%r15) # address of register-save area l %r1,BASED(.Lhandle_per) # load adr. of per handler la %r14,BASED(sysc_restore)# load adr. of system return br %r1 # branch to do_single_step/* * IO interrupt handler routine */ .globl io_int_handlerio_int_handler: STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+16 SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16#ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? bz BASED(io_no_vtime) UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMERio_no_vtime:#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct TRACE_IRQS_OFF l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ la %r2,SP_PTREGS(%r15) # address of register-save area basr %r14,%r1 # branch to standard irq handlerio_return: tm SP_PSW+1(%r15),0x01 # returning to user ?#ifdef CONFIG_PREEMPT bno BASED(io_preempt) # no -> check for preemptive scheduling#else bno BASED(io_restore) # no-> skip resched & signal#endif tm __TI_flags+3(%r9),_TIF_WORK_INT bnz BASED(io_work) # there is work to do (signals etc.)io_restore:#ifdef CONFIG_TRACE_IRQFLAGS la %r1,BASED(io_restore_trace_psw) lpsw 0(%r1)io_restore_trace: TRACE_IRQS_CHECK LOCKDEP_SYS_EXIT#endifio_leave: RESTORE_ALL __LC_RETURN_PSW,0io_done:#ifdef CONFIG_TRACE_IRQFLAGS .align 8 .globl io_restore_trace_pswio_restore_trace_psw: .long 0, io_restore_trace + 0x80000000#endif#ifdef CONFIG_PREEMPTio_preempt: icm %r0,15,__TI_precount(%r9) bnz BASED(io_restore) l %r1,SP_R15(%r15) s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain lr %r15,%r1io_resume_loop: tm __TI_flags+3(%r9),_TIF_NEED_RESCHED bno BASED(io_restore) l %r1,BASED(.Lpreempt_schedule_irq) la %r14,BASED(io_resume_loop) br %r1 # call schedule#endif## switch to kernel stack, then check the TIF bits#io_work: l %r1,__LC_KERNEL_STACK s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain lr %r15,%r1## One of the work bits is on. Find out which one.# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED# and _TIF_MCCK_PENDING#io_work_loop: tm __TI_flags+3(%r9),_TIF_MCCK_PENDING bo BASED(io_mcck_pending) tm __TI_flags+3(%r9),_TIF_NEED_RESCHED bo BASED(io_reschedule) tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) bnz BASED(io_sigpending) b BASED(io_restore)io_work_done:## _TIF_MCCK_PENDING is set, call handler#io_mcck_pending: l %r1,BASED(.Ls390_handle_mcck) basr %r14,%r1 # TIF bit will be cleared by handler b BASED(io_work_loop)## _TIF_NEED_RESCHED is set, call schedule#io_reschedule: TRACE_IRQS_ON l %r1,BASED(.Lschedule) stosm __SF_EMPTY(%r15),0x03 # reenable interrupts basr %r14,%r1 # call scheduler stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts TRACE_IRQS_OFF tm __TI_flags+3(%r9),_TIF_WORK_INT bz BASED(io_restore) # there is no work to do b BASED(io_work_loop)## _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal#io_sigpending: TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts la %r2,SP_PTREGS(%r15) # load pt_regs l %r1,BASED(.Ldo_signal) basr %r14,%r1 # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts TRACE_IRQS_OFF b BASED(io_work_loop)/* * External interrupt handler routine */ .globl ext_int_handlerext_int_handler: STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+16 SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16#ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? bz BASED(ext_no_vtime) UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMERext_no_vtime:#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area lh %r3,__LC_EXT_INT_CODE # get interruption code l %r1,BASED(.Ldo_extint) basr %r14,%r1 b BASED(io_return)__critical_end:/* * Machine check handler routines */ .globl mcck_int_handler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -