📄 entry.s
字号:
(pUStk) rsm psr.i cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk#endif.work_processed_kernel:#ifdef XEN ;;(pUStk) ssm psr.i(pUStk) br.call.sptk.many b0=do_softirq(pUStk) rsm psr.i ;;(pUStk) br.call.sptk.many b0=reflect_event ;; adds r7 = PT(EML_UNAT)+16,r12 ;; ld8 r7 = [r7] ;; mov ar.unat=r7 /* load eml_unat */ mov r31=r0#else adds r17=TI_FLAGS+IA64_TASK_SIZE,r13 ;;(p6) ld4 r31=[r17] // load current_thread_info()->flags#endif adds r21=PT(PR)+16,r12 ;; lfetch [r21],PT(CR_IPSR)-PT(PR) adds r2=PT(B6)+16,r12 adds r3=PT(R16)+16,r12 ;; lfetch [r21] ld8 r28=[r2],8 // load b6 adds r29=PT(R24)+16,r12#ifdef XEN ld8.fill r16=[r3] adds r3=PT(AR_CSD)-PT(R16),r3#else ld8.fill r16=[r3],PT(AR_CSD)-PT(R16)#endif adds r30=PT(AR_CCV)+16,r12(p6) and r19=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? ;; ld8.fill r24=[r29] ld8 r15=[r30] // load ar.ccv(p6) cmp4.ne.unc p6,p0=r19, r0 // any special work pending? ;; ld8 r29=[r2],16 // load b7 ld8 r30=[r3],16 // load ar.csd#ifndef XEN(p6) br.cond.spnt .work_pending#endif ;; ld8 r31=[r2],16 // load ar.ssd ld8.fill r8=[r3],16 ;; ld8.fill r9=[r2],16 ld8.fill r10=[r3],PT(R17)-PT(R10) ;; ld8.fill r11=[r2],PT(R18)-PT(R11) ld8.fill r17=[r3],16 ;; ld8.fill r18=[r2],16 ld8.fill r19=[r3],16 ;; ld8.fill r20=[r2],16 ld8.fill r21=[r3],16 mov ar.csd=r30 mov ar.ssd=r31 ;; rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection invala // invalidate ALAT ;; ld8.fill r22=[r2],24 ld8.fill r23=[r3],24 mov b6=r28 ;; ld8.fill r25=[r2],16 ld8.fill r26=[r3],16 mov b7=r29 ;; ld8.fill r27=[r2],16 ld8.fill r28=[r3],16 ;; ld8.fill r29=[r2],16 ld8.fill r30=[r3],24 ;; ld8.fill r31=[r2],PT(F9)-PT(R31) adds r3=PT(F10)-PT(F6),r3 ;; ldf.fill f9=[r2],PT(F6)-PT(F9) ldf.fill f10=[r3],PT(F8)-PT(F10) ;; ldf.fill f6=[r2],PT(F7)-PT(F6) ;; ldf.fill f7=[r2],PT(F11)-PT(F7)#ifdef XEN ldf.fill f8=[r3],PT(R5)-PT(F8) ;; ldf.fill f11=[r2],PT(R4)-PT(F11) mov ar.ccv=r15 ;; ld8.fill r4=[r2],16 ld8.fill r5=[r3],16 ;; ld8.fill r6=[r2] ld8.fill r7=[r3] ;; srlz.d // ensure that inter. collection is off (VHPT is don't care, since text is pinned) ;; bsw.0 // switch back to bank 0 (no stop bit required beforehand...) ;;#else ldf.fill f8=[r3],32 ;; srlz.d // ensure that inter. collection is off (VHPT is don't care, since text is pinned) mov ar.ccv=r15 ;; ldf.fill f11=[r2] bsw.0 // switch back to bank 0 (no stop bit required beforehand...) ;;#endif#ifdef XEN(pUStk) movl r18=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET;;(pUStk) ld8 r18=[r18]#else(pUStk) mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency)#endif adds r16=PT(CR_IPSR)+16,r12 adds r17=PT(CR_IIP)+16,r12(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled nop.i 0 nop.i 0 ;; ld8 r29=[r16],16 // load cr.ipsr ld8 r28=[r17],16 // load cr.iip ;; ld8 r30=[r16],16 // load cr.ifs ld8 r25=[r17],16 // load ar.unat ;; ld8 r26=[r16],16 // load ar.pfs ld8 r27=[r17],16 // load ar.rsc#ifndef XEN cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs#endif ;; ld8 r24=[r16],16 // load ar.rnat (may be garbage) ld8 r23=[r17],16 // load ar.bspstore (may be garbage) ;; ld8 r31=[r16],16 // load predicates ld8 r21=[r17],16 // load b0 ;; ld8 r19=[r16],16 // load ar.rsc value for "loadrs" ld8.fill r1=[r17],16 // load r1 ;; ld8.fill r12=[r16],16 ld8.fill r13=[r17],16(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18 ;; ld8 r20=[r16],16 // ar.fpsr ld8.fill r15=[r17],16 ;; ld8.fill r14=[r16],16 ld8.fill r2=[r17](pUStk) mov r17=1 ;; ld8.fill r3=[r16](pUStk) st1 [r18]=r17 // restore current->thread.on_ustack shr.u r18=r19,16 // get byte size of existing "dirty" partition ;; mov r16=ar.bsp // get existing backing store pointer#ifdef XEN movl r17=THIS_CPU(ia64_phys_stacked_size_p8)#else addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0#endif ;; ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8(pKStk) br.cond.dpnt skip_rbs_switch /* * Restore user backing store. * * NOTE: alloc, loadrs, and cover can't be predicated. */(pNonSys) br.cond.dpnt dont_preserve_current_frame cover // add current frame into dirty partition and set cr.ifs ;; mov r19=ar.bsp // get new backing store pointerrbs_switch: sub r16=r16,r18 // krbs = old bsp - size of dirty partition#ifndef XEN cmp.ne p9,p0=r0,r0 // clear p9 to skip restore of cr.ifs#endif ;; sub r19=r19,r16 // calculate total byte size of dirty partition add r18=64,r18 // don't force in0-in7 into memory... ;; shl r19=r19,16 // shift size of dirty partition into loadrs position ;;dont_preserve_current_frame: /* * To prevent leaking bits between the kernel and user-space, * we must clear the stacked registers in the "invalid" partition here. * Not pretty, but at least it's fast (3.34 registers/cycle on Itanium, * 5 registers/cycle on McKinley). */# define pRecurse p6# define pReturn p7#ifdef CONFIG_ITANIUM# define Nregs 10#else# define Nregs 14#endif alloc loc0=ar.pfs,2,Nregs-2,2,0 shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8)) sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize ;; mov ar.rsc=r19 // load ar.rsc to be used for "loadrs" shladd in0=loc1,3,r17 mov in1=0 ;; TEXT_ALIGN(32)rse_clear_invalid:#ifdef CONFIG_ITANIUM // cycle 0 { .mii alloc loc0=ar.pfs,2,Nregs-2,2,0 cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse add out0=-Nregs*8,in0}{ .mfb add out1=1,in1 // increment recursion count nop.f 0 nop.b 0 // can't do br.call here because of alloc (WAW on CFM) ;;}{ .mfi // cycle 1 mov loc1=0 nop.f 0 mov loc2=0}{ .mib mov loc3=0 mov loc4=0(pRecurse) br.call.sptk.many b0=rse_clear_invalid}{ .mfi // cycle 2 mov loc5=0 nop.f 0 cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret}{ .mib mov loc6=0 mov loc7=0(pReturn) br.ret.sptk.many b0}#else /* !CONFIG_ITANIUM */ alloc loc0=ar.pfs,2,Nregs-2,2,0 cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse add out0=-Nregs*8,in0 add out1=1,in1 // increment recursion count mov loc1=0 mov loc2=0 ;; mov loc3=0 mov loc4=0 mov loc5=0 mov loc6=0 mov loc7=0(pRecurse) br.call.dptk.few b0=rse_clear_invalid ;; mov loc8=0 mov loc9=0 cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret mov loc10=0 mov loc11=0(pReturn) br.ret.dptk.many b0#endif /* !CONFIG_ITANIUM */# undef pRecurse# undef pReturn ;; alloc r17=ar.pfs,0,0,0,0 // drop current register frame ;; loadrs ;;skip_rbs_switch: mov ar.unat=r25 // M2(pKStk) extr.u r22=r22,21,1 // I0 extract current value of psr.pp from r22(pLvSys)mov r19=r0 // A clear r19 for leave_syscall, no-op otherwise ;;(pUStk) mov ar.bspstore=r23 // M2(pKStk) dep r29=r22,r29,21,1 // I0 update ipsr.pp with psr.pp(pLvSys)mov r16=r0 // A clear r16 for leave_syscall, no-op otherwise ;; mov cr.ipsr=r29 // M2 mov ar.pfs=r26 // I0(pLvSys)mov r17=r0 // A clear r17 for leave_syscall, no-op otherwise#ifdef XEN mov cr.ifs=r30 // M2#else (p9) mov cr.ifs=r30 // M2#endif mov b0=r21 // I0(pLvSys)mov r18=r0 // A clear r18 for leave_syscall, no-op otherwise mov ar.fpsr=r20 // M2 mov cr.iip=r28 // M2 nop 0 ;;(pUStk) mov ar.rnat=r24 // M2 must happen with RSE in lazy mode nop 0#ifdef XEN (pLvSys)mov r15=r0#else(pLvSys)mov r2=r0#endif mov ar.rsc=r27 // M2 mov pr=r31,-1 // I0 rfi // B#ifndef XEN /* * On entry: * r20 = ¤t->thread_info->pre_count (if CONFIG_PREEMPT) * r31 = current->thread_info->flags * On exit: * p6 = TRUE if work-pending-check needs to be redone */.work_pending_syscall: add r2=-8,r2 add r3=-8,r3 ;; st8 [r2]=r8 st8 [r3]=r10.work_pending: tbit.nz p6,p0=r31,TIF_SIGDELAYED // signal delayed from MCA/INIT/NMI/PMI context?(p6) br.cond.sptk.few .sigdelayed ;; tbit.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0?(p6) br.cond.sptk.few .notify#ifdef CONFIG_PREEMPT(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1 ;;(pKStk) st4 [r20]=r21 ssm psr.i // enable interrupts#endif br.call.spnt.many rp=schedule.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 rsm psr.i // disable interrupts ;;#ifdef CONFIG_PREEMPT(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 ;;(pKStk) st4 [r20]=r0 // preempt_count() <- 0#endif(pLvSys)br.cond.sptk.few .work_pending_syscall_end br.cond.sptk.many .work_processed_kernel // re-check.notify:(pUStk) br.call.spnt.many rp=notify_resume_user.ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0(pLvSys)br.cond.sptk.few .work_pending_syscall_end br.cond.sptk.many .work_processed_kernel // don't re-check// There is a delayed signal that was detected in MCA/INIT/NMI/PMI context where// it could not be delivered. Deliver it now. The signal might be for us and// may set TIF_SIGPENDING, so redrive ia64_leave_* after processing the delayed// signal..sigdelayed: br.call.sptk.many rp=do_sigdelayed cmp.eq p6,p0=r0,r0 // p6 <- 1, always re-check(pLvSys)br.cond.sptk.few .work_pending_syscall_end br.cond.sptk.many .work_processed_kernel // re-check.work_pending_syscall_end: adds r2=PT(R8)+16,r12 adds r3=PT(R10)+16,r12 ;; ld8 r8=[r2] ld8 r10=[r3] br.cond.sptk.many .work_processed_syscall // re-check#endifEND(ia64_leave_kernel)ENTRY(handle_syscall_error) /* * Some system calls (e.g., ptrace, mmap) can return arbitrary values which could * lead us to mistake a negative return value as a failed syscall. Those syscall * must deposit a non-zero value in pt_regs.r8 to indicate an error. If * pt_regs.r8 is zero, we assume that the call completed successfully. */ PT_REGS_UNWIND_INFO(0) ld8 r3=[r2] // load pt_regs.r8 ;; cmp.eq p6,p7=r3,r0 // is pt_regs.r8==0? ;;(p7) mov r10=-1(p7) sub r8=0,r8 // negate return value to get errno br.cond.sptk ia64_leave_syscallEND(handle_syscall_error) /* * Invoke schedule_tail(task) while preserving in0-in7, which may be needed * in case a system call gets restarted. */GLOBAL_ENTRY(ia64_invoke_schedule_tail) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) alloc loc1=ar.pfs,8,2,1,0 mov loc0=rp mov out0=r8 // Address of previous task ;; br.call.sptk.many rp=schedule_tail.ret11: mov ar.pfs=loc1 mov rp=loc0 br.ret.sptk.many rpEND(ia64_invoke_schedule_tail)#ifndef XEN /* * Setup stack and call do_notify_resume_user(). Note that pSys and pNonSys need to * be set up by the caller. We declare 8 input registers so the system call * args get preserved, in case we need to restart a system call. */ENTRY(notify_resume_user) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart! mov r9=ar.unat mov loc0=rp // save return address mov out0=0 // there is no "oldset" adds out1=8,sp // out1=&sigscratch->ar_pfs(pSys) mov out2=1 // out2==1 => we're in a syscall ;;(pNonSys) mov out2=0 // out2==0 => not a syscall .fframe 16 .spillsp ar.unat, 16 st8 [sp]=r9,-16 // allocate space for ar.unat and save it st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch .body br.call.sptk.many rp=do_notify_resume_user.ret15: .restore sp adds sp=16,sp // pop scratch stack space ;; ld8 r9=[sp] // load new unat from sigscratch->scratch_unat mov rp=loc0 ;; mov ar.unat=r9 mov ar.pfs=loc1 br.ret.sptk.many rpEND(notify_resume_user)GLOBAL_ENTRY(sys_rt_sigsuspend) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart! mov r9=ar.unat mov loc0=rp // save return address mov out0=in0 // mask mov out1=in1 // sigsetsize adds out2=8,sp // out2=&sigscratch->ar_pfs ;; .fframe 16
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -