📄 entry64.s
字号:
# a new process exits the kernel with ret_from_fork# .globl ret_from_forkret_from_fork: lg %r13,__LC_SVC_NEW_PSW+8 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct tm SP_PSW+1(%r15),0x01 # forking a kernel thread ? jo 0f stg %r15,SP_R15(%r15) # store stack pointer for new kthread0: brasl %r14,schedule_tail stosm 24(%r15),0x03 # reenable interrupts j sysc_return## clone, fork, vfork, exec and sigreturn need glue,# because they all expect pt_regs as parameter,# but are called with different parameter.# return-address is set up above#sys_clone_glue: la %r2,SP_PTREGS(%r15) # load pt_regs jg sys_clone # branch to sys_clone#ifdef CONFIG_S390_SUPPORTsys32_clone_glue: la %r2,SP_PTREGS(%r15) # load pt_regs jg sys32_clone # branch to sys32_clone#endifsys_fork_glue: la %r2,SP_PTREGS(%r15) # load pt_regs jg sys_fork # branch to sys_forksys_vfork_glue: la %r2,SP_PTREGS(%r15) # load pt_regs jg sys_vfork # branch to sys_vforksys_execve_glue: la %r2,SP_PTREGS(%r15) # load pt_regs lgr %r12,%r14 # save return address brasl %r14,sys_execve # call sys_execve ltgr %r2,%r2 # check if execve failed bnz 0(%r12) # it did fail -> store result in gpr2 b 6(%r12) # SKIP STG 2,SP_R2(15) in # system_call/sysc_tracesys#ifdef CONFIG_S390_SUPPORTsys32_execve_glue: la %r2,SP_PTREGS(%r15) # load pt_regs lgr %r12,%r14 # save return address brasl %r14,sys32_execve # call sys32_execve ltgr %r2,%r2 # check if execve failed bnz 0(%r12) # it did fail -> store result in gpr2 b 6(%r12) # SKIP STG 2,SP_R2(15) in # system_call/sysc_tracesys#endifsys_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys_sigreturn # branch to sys_sigreturn#ifdef CONFIG_S390_SUPPORTsys32_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys32_sigreturn # branch to sys32_sigreturn#endifsys_rt_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys_rt_sigreturn # branch to sys_sigreturn#ifdef CONFIG_S390_SUPPORTsys32_rt_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys32_rt_sigreturn # branch to sys32_sigreturn#endif## sigsuspend and rt_sigsuspend need pt_regs as an additional# parameter and they have to skip the store of %r2 into the# user register %r2 because the return value was set in # sigsuspend and rt_sigsuspend already and must not be overwritten!#sys_sigsuspend_glue: lgr %r5,%r4 # move mask back lgr %r4,%r3 # move history1 parameter lgr %r3,%r2 # move history0 parameter la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter la %r14,6(%r14) # skip store of return value jg sys_sigsuspend # branch to sys_sigsuspend#ifdef CONFIG_S390_SUPPORTsys32_sigsuspend_glue: llgfr %r4,%r4 # unsigned long lgr %r5,%r4 # move mask back lgfr %r3,%r3 # int lgr %r4,%r3 # move history1 parameter lgfr %r2,%r2 # int lgr %r3,%r2 # move history0 parameter la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter la %r14,6(%r14) # skip store of return value jg sys32_sigsuspend # branch to sys32_sigsuspend#endifsys_rt_sigsuspend_glue: lgr %r4,%r3 # move sigsetsize parameter lgr %r3,%r2 # move unewset parameter la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter la %r14,6(%r14) # skip store of return value jg sys_rt_sigsuspend # branch to sys_rt_sigsuspend#ifdef CONFIG_S390_SUPPORTsys32_rt_sigsuspend_glue: llgfr %r3,%r3 # size_t lgr %r4,%r3 # move sigsetsize parameter llgtr %r2,%r2 # sigset_emu31_t * lgr %r3,%r2 # move unewset parameter la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter la %r14,6(%r14) # skip store of return value jg sys32_rt_sigsuspend # branch to sys32_rt_sigsuspend#endifsys_sigaltstack_glue: la %r4,SP_PTREGS(%r15) # load pt_regs as parameter jg sys_sigaltstack # branch to sys_sigreturn#ifdef CONFIG_S390_SUPPORTsys32_sigaltstack_glue: la %r4,SP_PTREGS(%r15) # load pt_regs as parameter jg sys32_sigaltstack_wrapper # branch to sys_sigreturn#endif/* * 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 jnz pgm_per # got per exception -> special case SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA#ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? jz 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 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lgf %r3,__LC_PGM_ILC # load program interruption code lghi %r8,0x7f ngr %r8,%r3pgm_do_call: sll %r8,3 larl %r1,pgm_check_table lg %r1,0(%r8,%r1) # load address of handler routine la %r2,SP_PTREGS(%r15) # address of register-save area larl %r14,sysc_return br %r1 # branch to interrupt-handler## handle per exception#pgm_per: tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on jnz 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(16),__LC_SVC_NEW_PSW je pgm_svcper# no interesting special case, ignore PER event lmg %r12,%r15,__LC_SAVE_AREA lpswe __LC_PGM_OLD_PSW## Normal per exception#pgm_per_std: SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA#ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? jz 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 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lg %r1,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP lgf %r3,__LC_PGM_ILC # load program interruption code lghi %r8,0x7f ngr %r8,%r3 # clear per-event-bit and ilc je sysc_return j pgm_do_call## it was a single stepped SVC that is causing all the trouble#pgm_svcper: SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA#ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? jz pgm_no_vtime3 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_vtime3:#endif llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lg %r1,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP stosm __SF_EMPTY(%r15),0x03 # reenable interrupts j sysc_do_svc/* * 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+32 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32#ifdef CONFIG_VIRT_CPU_ACCOUNTING tm SP_PSW+1(%r15),0x01 # interrupting from user ? jz 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 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handlerio_return: tm SP_PSW+1(%r15),0x01 # returning to user ?#ifdef CONFIG_PREEMPT jno io_preempt # no -> check for preemptive scheduling#else jno io_leave # no-> skip resched & signal#endif tm __TI_flags+7(%r9),_TIF_WORK_INT jnz io_work # there is work to do (signals etc.)io_leave: RESTORE_ALL __LC_RETURN_PSW,0io_done:#ifdef CONFIG_PREEMPTio_preempt: icm %r0,15,__TI_precount(%r9) jnz io_leave # switch to kernel stack lg %r1,SP_R15(%r15) aghi %r1,-SP_SIZE mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain lgr %r15,%r1io_resume_loop: tm __TI_flags+7(%r9),_TIF_NEED_RESCHED jno io_leave larl %r1,.Lc_pactive mvc __TI_precount(4,%r9),0(%r1) stosm __SF_EMPTY(%r15),0x03 # reenable interrupts brasl %r14,schedule # call schedule stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts xc __TI_precount(4,%r9),__TI_precount(%r9) j io_resume_loop#endif## switch to kernel stack, then check TIF bits#io_work: lg %r1,__LC_KERNEL_STACK aghi %r1,-SP_SIZE mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain lgr %r15,%r1## One of the work bits is on. Find out which one.# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING#io_work_loop: tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jo io_mcck_pending tm __TI_flags+7(%r9),_TIF_NEED_RESCHED jo io_reschedule tm __TI_flags+7(%r9),_TIF_SIGPENDING jo io_sigpending j io_leave## _TIF_MCCK_PENDING is set, call handler#io_mcck_pending: larl %r14,io_work_loop jg s390_handle_mcck # TIF bit will be cleared by handler## _TIF_NEED_RESCHED is set, call schedule# io_reschedule: stosm __SF_EMPTY(%r15),0x03 # reenable interrupts brasl %r14,schedule # call scheduler stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts tm __TI_flags+7(%r9),_TIF_WORK_INT jz io_leave # there is no work to do j io_work_loop## _TIF_SIGPENDING is set, call do_signal#
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -