📄 entry.s
字号:
;; // WAW on CFM at the br.call mov loc0=rp br.call.sptk.many rp=save_switch_stack_with_current_frame // must preserve b6!!.ret4: mov loc2=b6 br.call.sptk.few rp=syscall_trace.ret5: adds sp=IA64_SWITCH_STACK_SIZE,sp // drop switch_stack frame mov rp=loc0 mov ar.pfs=loc1 mov b6=loc2 ;; br.ret.sptk.few rp#endif /* !CONFIG_IA64_NEW_SYSCALL */END(invoke_syscall_trace) // // Invoke a system call, but do some tracing before and after the call. // We MUST preserve the current register frame throughout this routine // because some system calls (such as ia64_execve) directly // manipulate ar.pfs. // // Input: // r15 = syscall number // b6 = syscall entry point // .global ia64_strace_leave_kernelGLOBAL_ENTRY(ia64_trace_syscall) PT_REGS_UNWIND_INFO(0) br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args.ret6: br.call.sptk.few rp=b6 // do the syscallstrace_check_retval: cmp.lt p6,p0=r8,r0 // syscall failed? adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 adds r3=IA64_PT_REGS_R8_OFFSET+32,sp // r3 = &pt_regs.r10 mov r10=0(p6) br.cond.sptk.few strace_error // syscall failed -> ;; // avoid RAW on r10strace_save_retval:.mem.offset 0,0; st8.spill [r2]=r8 // store return value in slot for r8.mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10ia64_strace_leave_kernel: br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value.rety: br.cond.sptk.many ia64_leave_kernelstrace_error: ld8 r3=[r2] // load pt_regs.r8 sub r9=0,r8 // negate return value to get errno value ;; cmp.ne p6,p0=r3,r0 // is pt_regs.r8!=0? adds r3=16,r2 // r3=&pt_regs.r10 ;;(p6) mov r10=-1(p6) mov r8=r9 br.cond.sptk.few strace_save_retvalEND(ia64_trace_syscall)/* * A couple of convenience macros to help implement/understand the state * restoration that happens at the end of ia64_ret_from_syscall. */#define rARPR r31#define rCRIFS r30#define rCRIPSR r29#define rCRIIP r28#define rARRSC r27#define rARPFS r26#define rARUNAT r25#define rARRNAT r24#define rARBSPSTORE r23#define rKRBS r22#define rB6 r21GLOBAL_ENTRY(ia64_ret_from_clone) PT_REGS_UNWIND_INFO(0)#ifdef CONFIG_SMP // In SMP mode, we need to call schedule_tail to complete the scheduling process. // Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the // address of the previously executing task. br.call.sptk.few rp=invoke_schedule_tail.ret8:#endif adds r2=IA64_TASK_PTRACE_OFFSET,r13 ;; ld8 r2=[r2] ;; mov r8=0 tbit.nz p6,p0=r2,PT_TRACESYS_BIT(p6) br strace_check_retval ;; // added stop bits to prevent r8 dependencyEND(ia64_ret_from_clone) // fall throughGLOBAL_ENTRY(ia64_ret_from_syscall) PT_REGS_UNWIND_INFO(0) cmp.ge p6,p7=r8,r0 // syscall executed successfully? adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 adds r3=IA64_PT_REGS_R8_OFFSET+32,sp // r3 = &pt_regs.r10 ;; .mem.offset 0,0(p6) st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit .mem.offset 8,0(p6) st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit(p7) br.cond.spnt.few handle_syscall_error // handle potential syscall failureEND(ia64_ret_from_syscall) // fall throughGLOBAL_ENTRY(ia64_leave_kernel) // check & deliver software interrupts: PT_REGS_UNWIND_INFO(0)#ifdef CONFIG_SMP adds r2=IA64_TASK_PROCESSOR_OFFSET,r13 movl r3=irq_stat // softirq_active ;; ld4 r2=[r2] ;; shl r2=r2,SMP_CACHE_SHIFT // can't use shladd here... ;; add r3=r2,r3#else movl r3=irq_stat // softirq_active#endif ;; ld8 r2=[r3] // r3 (softirq_active+softirq_mask) is guaranteed to be 8-byte aligned! ;; shr r3=r2,32 ;; and r2=r2,r3 ;; cmp4.ne p6,p7=r2,r0(p6) br.call.spnt.many rp=invoke_do_softirq1:(pKern) br.cond.dpnt.many restore_all // yup -> skip check for rescheduling & signal delivery // call schedule() until we find a task that doesn't have need_resched set:back_from_resched: { .mii adds r2=IA64_TASK_NEED_RESCHED_OFFSET,r13 mov r3=ip adds r14=IA64_TASK_SIGPENDING_OFFSET,r13 } ;; ld8 r2=[r2] ld4 r14=[r14] mov rp=r3 // arrange for schedule() to return to back_from_resched ;; cmp.ne p6,p0=r2,r0 cmp.ne p2,p0=r14,r0 // NOTE: pKern is an alias for p2!! srlz.d(p6) br.call.spnt.many b6=invoke_schedule // ignore return value2: // check & deliver pending signals:(p2) br.call.spnt.few rp=handle_signal_delivery.ret9:#ifdef CONFIG_IA64_SOFTSDV_HACKS // Check for lost ticks rsm psr.i mov r2 = ar.itc movl r14 = 1000 // latency tolerance mov r3 = cr.itm ;; sub r2 = r2, r3 ;; sub r2 = r2, r14 ;; cmp.ge p6,p7 = r2, r0(p6) br.call.spnt.few rp=invoke_ia64_reset_itm.ret10: ;; ssm psr.i#endif restore_all: // start restoring the state saved on the kernel stack (struct pt_regs): adds r2=IA64_PT_REGS_R8_OFFSET+16,r12 adds r3=IA64_PT_REGS_R8_OFFSET+24,r12 ;; ld8.fill r8=[r2],16 ld8.fill r9=[r3],16 ;; ld8.fill r10=[r2],16 ld8.fill r11=[r3],16 ;; ld8.fill r16=[r2],16 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 ;; ld8.fill r22=[r2],16 ld8.fill r23=[r3],16 ;; ld8.fill r24=[r2],16 ld8.fill r25=[r3],16 ;; ld8.fill r26=[r2],16 ld8.fill r27=[r3],16 ;; ld8.fill r28=[r2],16 ld8.fill r29=[r3],16 ;; ld8.fill r30=[r2],16 ld8.fill r31=[r3],16 ;; ld8 r1=[r2],16 // ar.ccv ld8 r13=[r3],16 // ar.fpsr ;; ld8 r14=[r2],16 // b0 ld8 r15=[r3],16+8 // b7 ;; ldf.fill f6=[r2],32 ldf.fill f7=[r3],32 ;; ldf.fill f8=[r2],32 ldf.fill f9=[r3],32 ;; mov ar.ccv=r1 mov ar.fpsr=r13 mov b0=r14 // turn off interrupts, interrupt collection rsm psr.i | psr.ic ;; srlz.i // EAS 2.5 mov b7=r15 ;; invala // invalidate ALAT bsw.0;; // switch back to bank 0 (must be last in insn group) ;;#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC nop.i 0x0 ;; nop.i 0x0 ;; nop.i 0x0 ;;#endif adds r16=16,r12 adds r17=24,r12 ;; ld8 rCRIPSR=[r16],16 // load cr.ipsr ld8 rCRIIP=[r17],16 // load cr.iip ;; ld8 rCRIFS=[r16],16 // load cr.ifs ld8 rARUNAT=[r17],16 // load ar.unat ;; ld8 rARPFS=[r16],16 // load ar.pfs ld8 rARRSC=[r17],16 // load ar.rsc ;; ld8 rARRNAT=[r16],16 // load ar.rnat (may be garbage) ld8 rARBSPSTORE=[r17],16 // load ar.bspstore (may be garbage) ;; ld8 rARPR=[r16],16 // load predicates ld8 rB6=[r17],16 // load b6 ;; ld8 r18=[r16],16 // load ar.rsc value for "loadrs" ld8.fill r1=[r17],16 // load r1 ;; ld8.fill r2=[r16],16 ld8.fill r3=[r17],16 ;; ld8.fill r12=[r16],16 ld8.fill r13=[r17],16 extr.u r19=rCRIPSR,32,2 // extract ps.cpl ;; ld8.fill r14=[r16],16 ld8.fill r15=[r17],16 cmp.eq p6,p7=r0,r19 // are we returning to kernel mode? (psr.cpl==0) ;; mov b6=rB6 mov ar.pfs=rARPFS(p6) br.cond.dpnt.few skip_rbs_switch /* * Restore user backing store. * * NOTE: alloc, loadrs, and cover can't be predicated. * * XXX This needs some scheduling/tuning once we believe it * really does work as intended. */ mov r16=ar.bsp // get existing backing store pointer(pNonSys) br.cond.dpnt.few dont_preserve_current_frame cover // add current frame into dirty partition ;; mov rCRIFS=cr.ifs // fetch the cr.ifs value that "cover" produced mov r17=ar.bsp // get new backing store pointer ;; sub r16=r17,r16 // calculate number of bytes that were added to rbs ;; shl r16=r16,16 // shift additional frame size into position for loadrs ;; add r18=r16,r18 // adjust the loadrs value ;;dont_preserve_current_frame: alloc r16=ar.pfs,0,0,0,0 // drop the current call frame (noop for syscalls) ;; mov ar.rsc=r18 // load ar.rsc to be used for "loadrs"#ifdef CONFIG_IA32_SUPPORT tbit.nz p6,p0=rCRIPSR,IA64_PSR_IS_BIT ;;(p6) mov ar.rsc=r0 // returning to IA32 mode#endif ;; loadrs ;; mov ar.bspstore=rARBSPSTORE ;; mov ar.rnat=rARRNAT // must happen with RSE in lazy modeskip_rbs_switch: mov ar.rsc=rARRSC mov ar.unat=rARUNAT mov cr.ifs=rCRIFS // restore cr.ifs only if not a (synchronous) syscall mov pr=rARPR,-1 mov cr.iip=rCRIIP mov cr.ipsr=rCRIPSR ;; rfi;; // must be last instruction in an insn groupEND(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 sub r9=0,r8 // negate return value to get errno ;; mov r10=-1 // return -1 in pt_regs.r10 to indicate error cmp.eq p6,p7=r3,r0 // is pt_regs.r8==0? adds r3=16,r2 // r3=&pt_regs.r10 ;;(p6) mov r9=r8(p6) mov r10=0 ;;.mem.offset 0,0; st8.spill [r2]=r9 // store errno in pt_regs.r8 and set unat bit.mem.offset 8,0; st8.spill [r3]=r10 // store error indication in pt_regs.r10 and set unat bit br.cond.sptk.many ia64_leave_kernelEND(handle_syscall_error)#ifdef CONFIG_SMP /* * Invoke schedule_tail(task) while preserving in0-in7, which may be needed * in case a system call gets restarted. */ENTRY(invoke_schedule_tail) UNW(.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.few rp=schedule_tail.ret11: mov ar.pfs=loc1 mov rp=loc0 br.ret.sptk.many rpEND(invoke_schedule_tail)#endif /* CONFIG_SMP */#ifdef CONFIG_IA64_SOFTSDV_HACKSENTRY(invoke_ia64_reset_itm) UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)) alloc loc1=ar.pfs,8,2,0,0 mov loc0=rp ;; UNW(.body) br.call.sptk.many rp=ia64_reset_itm.ret12: ;; mov ar.pfs=loc1 mov rp=loc0 br.ret.sptk.many rpEND(invoke_ia64_reset_itm)#endif /* CONFIG_IA64_SOFTSDV_HACKS */ /* * Invoke do_softirq() while preserving in0-in7, which may be needed * in case a system call gets restarted. */ENTRY(invoke_do_softirq) UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)) alloc loc1=ar.pfs,8,2,0,0 mov loc0=rp ;; UNW(.body) br.call.sptk.few rp=do_softirq.ret13: mov ar.pfs=loc1 mov rp=loc0 br.ret.sptk.many rpEND(invoke_do_softirq) /* * Invoke schedule() while preserving in0-in7, which may be needed * in case a system call gets restarted. */ENTRY(invoke_schedule) UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)) alloc loc1=ar.pfs,8,2,0,0 mov loc0=rp ;; UNW(.body) br.call.sptk.few rp=schedule.ret14: mov ar.pfs=loc1 mov rp=loc0 br.ret.sptk.many rpEND(invoke_schedule) // // Setup stack and call ia64_do_signal. 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(handle_signal_delivery)#ifdef CONFIG_IA64_NEW_UNWIND .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=0,sp // out1=&sigscratch(pSys) mov out2=1 // out2==1 => we're in a syscall ;;(pNonSys) mov out2=0 // out2==0 => not a syscall .fframe 16 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) st8 [sp]=r9,-16 // allocate space for ar.unat and save it .body br.call.sptk.few rp=ia64_do_signal.ret15: .restore sp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -