📄 entry.s
字号:
.long sys_setfsuid /* 215 */ .long sys_setfsgid .long sys_pivot_root .long sys_mincore .long sys_madvise .long sys_getdents64 /* 220 */ .rept 255-220 .long sys_ni_syscall .endr/* * Program check handler routine */pgm_lit: pgm_handle_per: .long handle_per_exception pgm_jump_table: .long pgm_check_table pgm_sysc_ret: .long sysc_return pgm_sysc_lit: .long sysc_lit pgm_do_signal: .long do_signal .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?). */ tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception jz pgm_sv # skip if not tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on jnz 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 je pgm_svcper# no interesting special case, ignore PER event lpsw 0x28# it was a single stepped SVC that is causing all the troublepgm_svcper: SAVE_ALL(0x20) mvi SP_SVC_STEP(%r15),1 # make SP_SVC_STEP nonzero mvc SP_PGM_OLD_ILC(4,%r15),__LC_PGM_ILC # save program check information j pgm_system_call # now do the svcpgm_svcret: lh %r7,SP_PGM_OLD_ILC(%r15) # get ilc from stack lhi %r0,0x28 st %r0,SP_TRAP(%r15) # set new trap indicator xc SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15) basr %r13,0 ahi %r13,pgm_lit-. # setup base pointer j pgm_no_svpgm_sv: SAVE_ALL(0x28) XC SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15) basr %r13,0 ahi %r13,pgm_lit-. # setup base pointer R13 to $PGMDAT lh %r7,__LC_PGM_ILC # load instruction lengthpgm_no_sv: lh %r8,__LC_PGM_INT_CODE # N.B. saved int code used later KEEP it stosm 24(%r15),0x03 # reenable interrupts lr %r3,%r8 lhi %r0,0x7f nr %r3,%r0 # clear per-event-bit je pgm_dn # none of Martins exceptions occured bypass l %r9,pgm_jump_table-pgm_lit(%r13) sll %r3,2 l %r9,0(%r3,%r9) # load address of handler routine la %r2,SP_PTREGS(%r15) # address of register-save area srl %r3,2 chi %r3,0x4 # protection-exception ? jne pgm_go # 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_go: basr %r14,%r9 # branch to interrupt-handlerpgm_dn: lhi %r0,0x80 nr %r8,%r0 # check for per exception je pgm_return la %r2,SP_PTREGS(15) # address of register-save area l %r9,pgm_handle_per-pgm_lit(%r13) # load adr. of per handler l %r14,pgm_sysc_ret-pgm_lit(%r13) # load adr. of system return l %r13,pgm_sysc_lit-pgm_lit(%r13) br %r9 # branch to handle_per_exception## the backend code is the same as for sys-call#pgm_return: l %r14,pgm_sysc_ret-pgm_lit(%r13) l %r13,pgm_sysc_lit-pgm_lit(%r13) br %r14/* * IO interrupt handler routine */io_lit: io_do_IRQ: .long do_IRQ io_schedule: .long schedule io_do_signal: .long do_signal io_do_softirq: .long do_softirq .globl io_int_handlerio_int_handler: SAVE_ALL(0x38) basr %r13,0 ahi %r13,io_lit-. # setup base pointer R13 to $IODAT 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 %r9,io_do_IRQ-io_lit(%r13) # load address of do_IRQ basr %r14,%r9 # branch to standard irq handlerio_return: GET_CURRENT # load pointer to task_struct to R9 tm SP_PSW+1(%r15),0x01 # returning to user ? jz io_leave # no-> skip resched & signal stosm 24(%r15),0x03 # reenable interrupts## check, if bottom-half has to be done# l %r0,__LC_IRQ_STAT # get softirq_active n %r0,__LC_IRQ_STAT+4 # and it with softirq_mask jnz io_handle_bottom_halfio_return_bh: ## check, if reschedule is needed# icm %r0,15,need_resched(%r9) # get need_resched from task_struct jnz io_reschedule icm %r0,15,sigpending(%r9) # get sigpending from task_struct jnz io_signal_returnio_leave: stnsm 24(%r15),disable # disable I/O and ext. interrupts RESTORE_ALL## call do_softirq and return from syscall, if interrupt-level# is zero#io_handle_bottom_half: l %r1,io_do_softirq-io_lit(%r13) la %r14,io_return_bh-io_lit(%r13) br %r1 # call do_softirq## call schedule with io_return as return-address#io_reschedule: l %r1,io_schedule-io_lit(%r13) la %r14,io_return-io_lit(%r13) 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,io_do_signal-io_lit(%r13) la %r14,io_leave-io_lit(%r13) br %r1 # return point is io_leave/* * External interrupt handler routine */ext_lit: ext_timer_int: .long do_timer_interrupt#ifdef CONFIG_SMP ext_call_int: .long do_ext_call_interrupt#endif#ifdef CONFIG_HWC ext_hwc_int: .long do_hwc_interrupt#endif#ifdef CONFIG_MDISK ext_mdisk_int: .long do_mdisk_interrupt#endif#ifdef CONFIG_IUCV ext_iucv_int: .long do_iucv_interrupt#endif ext_io_lit: .long io_lit ext_io_return: .long io_return .globl ext_int_handlerext_int_handler: SAVE_ALL(0x18) basr %r13,0 ahi %r13,ext_lit-. # setup base pointer R13 to $EXTDAT la %r2,SP_PTREGS(%r15) # address of register-save area lh %r3,__LC_EXT_INT_CODE # error code#ifdef CONFIG_SMP chi %r3,0x1202 # EXTERNAL_CALL jne ext_no_extcall l %r9,ext_call_int-ext_lit(%r13) # load ext_call_interrupt l %r14,ext_io_return-ext_lit(%r13) l %r13,ext_io_lit-ext_lit(%r13) br %r9 # branch to ext call handlerext_no_extcall:#endif chi %r3,0x1004 # CPU_TIMER jne ext_no_timer l %r9,ext_timer_int-ext_lit(%r13) # load timer_interrupt l %r14,ext_io_return-ext_lit(%r13) l %r13,ext_io_lit-ext_lit(%r13) br %r9 # branch to ext call handlerext_no_timer: #ifdef CONFIG_HWC chi %r3,0x2401 # HWC interrupt jne ext_no_hwc l %r9,ext_hwc_int-ext_lit(%r13) # load addr. of hwc routine l %r14,ext_io_return-ext_lit(%r13) l %r13,ext_io_lit-ext_lit(%r13) br %r9 # branch to ext call handlerext_no_hwc: #endif#ifdef CONFIG_MDISK chi %r3,0x2603 # diag 250 (VM) interrupt jne ext_no_mdisk l %r9,ext_mdisk_int-ext_lit(%r13) l %r14,ext_io_return-ext_lit(%r13) l %r13,ext_io_lit-ext_lit(%r13) br %r9 # branch to ext call handlerext_no_mdisk: #endif#ifdef CONFIG_IUCV chi %r3,0x4000 # diag 250 (VM) interrupt jne ext_no_iucv l %r9,ext_iucv_int-ext_lit(%r13) l %r14,ext_io_return-ext_lit(%r13) l %r13,ext_io_lit-ext_lit(%r13) br %r9 # branch to ext call handlerext_no_iucv: #endif l %r14,ext_io_return-ext_lit(%r13) l %r13,ext_io_lit-ext_lit(%r13) br %r14 # use backend code of io_int_handler/* * Machine check handler routines */mcck_lit: mcck_crw_pending: .long do_crw_pending .globl mcck_int_handlermcck_int_handler: SAVE_ALL(0x30) basr %r13,0 ahi %r13,mcck_lit-. # setup base pointer R13 to $MCCKDAT tm __LC_MCCK_CODE+1,0x40 jno mcck_no_crw l %r1,mcck_crw_pending-mcck_lit(%r13) basr %r14,%r1 # call do_crw_pendingmcck_no_crw:mcck_return: RESTORE_ALL#ifdef CONFIG_SMP/* * Restart interruption handler, kick starter for additional CPUs */ .globl restart_int_handlerrestart_int_handler: l %r15,__LC_KERNEL_STACK # load ksp lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs lam %a0,%a15,__LC_AREGS_SAVE_AREA stosm 0(%r15),daton # now we can turn dat on lm %r6,%r15,24(%r15) # load registers from clone bras %r14,restart_go .long start_secondaryrestart_go: l %r14,0(%r14) br %r14 # branch to 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -