X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fia64%2Fkernel%2Fentry.S;h=8cb60f9361c7febf381e2f893bb5a17fea64f5ed;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=5e22d9df67ddecfd031e5af99d4106321b509028;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 5e22d9df6..8cb60f936 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1,9 +1,9 @@ /* - * ia64/kernel/entry.S + * arch/ia64/kernel/entry.S * * Kernel entry points. * - * Copyright (C) 1998-2003 Hewlett-Packard Co + * Copyright (C) 1998-2003, 2005 Hewlett-Packard Co * David Mosberger-Tang * Copyright (C) 1999, 2002-2003 * Asit Mallick @@ -31,13 +31,12 @@ * pNonSys: !pSys */ -#include #include #include #include #include -#include +#include #include #include #include @@ -51,8 +50,11 @@ * setup a null register window frame. */ ENTRY(ia64_execve) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3) - alloc loc1=ar.pfs,3,2,4,0 + /* + * Allocate 8 input registers since ptrace() may clobber them + */ + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc loc1=ar.pfs,8,2,4,0 mov loc0=rp .body mov out0=in0 // filename @@ -113,8 +115,11 @@ END(ia64_execve) * u64 tls) */ GLOBAL_ENTRY(sys_clone2) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(6) - alloc r16=ar.pfs,6,2,6,0 + /* + * Allocate 8 input registers since ptrace() may clobber them + */ + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc r16=ar.pfs,8,2,6,0 DO_SAVE_SWITCH_STACK adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp mov loc0=rp @@ -142,8 +147,11 @@ END(sys_clone2) * Deprecated. Use sys_clone2() instead. */ GLOBAL_ENTRY(sys_clone) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5) - alloc r16=ar.pfs,5,2,6,0 + /* + * Allocate 8 input registers since ptrace() may clobber them + */ + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc r16=ar.pfs,8,2,6,0 DO_SAVE_SWITCH_STACK adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp mov loc0=rp @@ -172,7 +180,7 @@ END(sys_clone) * called. The code starting at .map relies on this. The rest of the code * doesn't care about the interrupt masking status. */ -GLOBAL_ENTRY(ia64_switch_to) +GLOBAL_ENTRY(__ia64_switch_to) .prologue alloc r16=ar.pfs,1,0,0,0 DO_SAVE_SWITCH_STACK @@ -195,9 +203,6 @@ GLOBAL_ENTRY(ia64_switch_to) (p6) br.cond.dpnt .map ;; .done: -(p6) ssm psr.ic // if we had to map, reenable the psr.ic bit FIRST!!! - ;; -(p6) srlz.d ld8 sp=[r21] // load kernel stack pointer of new task mov IA64_KR(CURRENT)=in0 // update "current" application register mov r8=r13 // return pointer to previously running task @@ -225,8 +230,11 @@ GLOBAL_ENTRY(ia64_switch_to) mov IA64_KR(CURRENT_STACK)=r26 // remember last page we mapped... ;; itr.d dtr[r25]=r23 // wire in new mapping... + ssm psr.ic // reenable the psr.ic bit + ;; + srlz.d br.cond.sptk .done -END(ia64_switch_to) +END(__ia64_switch_to) /* * Note that interrupts are enabled during save_switch_stack and load_switch_stack. This @@ -367,7 +375,7 @@ END(save_switch_stack) * - b7 holds address to return to * - must not touch r8-r11 */ -ENTRY(load_switch_stack) +GLOBAL_ENTRY(load_switch_stack) .prologue .altrp b7 @@ -461,23 +469,34 @@ ENTRY(load_switch_stack) br.cond.sptk.many b7 END(load_switch_stack) -GLOBAL_ENTRY(__ia64_syscall) - .regstk 6,0,0,0 - mov r15=in5 // put syscall number in place - break __BREAK_SYSCALL - movl r2=errno - cmp.eq p6,p7=-1,r10 +GLOBAL_ENTRY(prefetch_stack) + add r14 = -IA64_SWITCH_STACK_SIZE, sp + add r15 = IA64_TASK_THREAD_KSP_OFFSET, in0 + ;; + ld8 r16 = [r15] // load next's stack pointer + lfetch.fault.excl [r14], 128 + ;; + lfetch.fault.excl [r14], 128 + lfetch.fault [r16], 128 ;; -(p6) st4 [r2]=r8 -(p6) mov r8=-1 + lfetch.fault.excl [r14], 128 + lfetch.fault [r16], 128 + ;; + lfetch.fault.excl [r14], 128 + lfetch.fault [r16], 128 + ;; + lfetch.fault.excl [r14], 128 + lfetch.fault [r16], 128 + ;; + lfetch.fault [r16], 128 br.ret.sptk.many rp -END(__ia64_syscall) +END(prefetch_stack) -GLOBAL_ENTRY(execve) +GLOBAL_ENTRY(kernel_execve) mov r15=__NR_execve // put syscall number in place break __BREAK_SYSCALL br.ret.sptk.many rp -END(execve) +END(kernel_execve) GLOBAL_ENTRY(clone) mov r15=__NR_clone // put syscall number in place @@ -491,7 +510,7 @@ END(clone) * because some system calls (such as ia64_execve) directly * manipulate ar.pfs. */ -GLOBAL_ENTRY(ia64_trace_syscall) +GLOBAL_ENTRY(__ia64_trace_syscall) PT_REGS_UNWIND_INFO(0) /* * We need to preserve the scratch registers f6-f11 in case the system @@ -549,7 +568,9 @@ GLOBAL_ENTRY(ia64_trace_syscall) .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 r10 br.call.sptk.many rp=syscall_trace_leave // give parent a chance to catch return value -.ret3: br.cond.sptk ia64_leave_syscall +.ret3: +(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk + br.cond.sptk .work_pending_syscall_end strace_error: ld8 r3=[r2] // load pt_regs.r8 @@ -561,7 +582,7 @@ strace_error: (p6) mov r10=-1 (p6) mov r8=r9 br.cond.sptk .strace_save_retval -END(ia64_trace_syscall) +END(__ia64_trace_syscall) /* * When traced and returning from sigreturn, we invoke syscall_trace but then @@ -612,13 +633,13 @@ GLOBAL_ENTRY(ia64_ret_from_syscall) PT_REGS_UNWIND_INFO(0) cmp.ge p6,p7=r8,r0 // syscall executed successfully? adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 - adds r3=PT(R10)+16,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 + mov r10=r0 // clear error indication in r10 (p7) br.cond.spnt handle_syscall_error // handle potential syscall failure + ;; + // don't fall through, ia64_leave_syscall may be #define'd + br.cond.sptk.few ia64_leave_syscall + ;; END(ia64_ret_from_syscall) - // fall through /* * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't * need to switch to bank 0 and doesn't restore the scratch registers. @@ -631,12 +652,14 @@ END(ia64_ret_from_syscall) * r8-r11: restored (syscall return value(s)) * r12: restored (user-level stack pointer) * r13: restored (user-level thread pointer) - * r14: cleared + * r14: set to __kernel_syscall_via_epc * r15: restored (syscall #) - * r16-r19: cleared + * r16-r17: cleared + * r18: user-level b6 + * r19: cleared * r20: user-level ar.fpsr * r21: user-level b0 - * r22: user-level b6 + * r22: cleared * r23: user-level ar.bspstore * r24: user-level ar.rnat * r25: user-level ar.unat @@ -650,7 +673,7 @@ END(ia64_ret_from_syscall) * pr: restored (user-level pr) * b0: restored (user-level rp) * b6: restored - * b7: cleared + * b7: set to __kernel_syscall_via_epc * ar.unat: restored (user-level ar.unat) * ar.pfs: restored (user-level ar.pfs) * ar.rsc: restored (user-level ar.rsc) @@ -661,7 +684,7 @@ END(ia64_ret_from_syscall) * ar.csd: cleared * ar.ssd: cleared */ -GLOBAL_ENTRY(ia64_leave_syscall) +GLOBAL_ENTRY(__ia64_leave_syscall) PT_REGS_UNWIND_INFO(0) /* * work.need_resched etc. mustn't get changed by this CPU before it returns to @@ -690,82 +713,86 @@ GLOBAL_ENTRY(ia64_leave_syscall) (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk #endif .work_processed_syscall: - adds r16=PT(LOADRS)+16,r12 - adds r17=PT(AR_BSPSTORE)+16,r12 + adds r2=PT(LOADRS)+16,r12 + adds r3=PT(AR_BSPSTORE)+16,r12 adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 ;; (p6) ld4 r31=[r18] // load current_thread_info()->flags - ld8 r19=[r16],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" + ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" nop.i 0 ;; - ld8 r23=[r17],PT(R9)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage) - ld8 r22=[r16],PT(R8)-PT(B6) // load b6 + mov r16=ar.bsp // M2 get existing backing store pointer + ld8 r18=[r2],PT(R9)-PT(B6) // load b6 (p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? ;; - - mov.m ar.ccv=r0 // clear ar.ccv + ld8 r23=[r3],PT(R11)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage) (p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending? -(p6) br.cond.spnt .work_pending +(p6) br.cond.spnt .work_pending_syscall ;; // start restoring the state saved on the kernel stack (struct pt_regs): - ld8.fill r8=[r16],16 - ld8.fill r9=[r17],16 - mov f6=f0 // clear f6 + ld8 r9=[r2],PT(CR_IPSR)-PT(R9) + ld8 r11=[r3],PT(CR_IIP)-PT(R11) +(pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE! ;; - ld8.fill r10=[r16],16 - ld8.fill r11=[r17],16 - mov f7=f0 // clear f7 - ;; - ld8 r29=[r16],16 // load cr.ipsr - ld8 r28=[r17],16 // load cr.iip - mov f8=f0 // clear f8 - ;; - ld8 r30=[r16],16 // load cr.ifs - ld8 r25=[r17],16 // load ar.unat - cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs - ;; - rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection - invala // invalidate ALAT - mov f9=f0 // clear f9 + invala // M0|1 invalidate ALAT + rsm psr.i | psr.ic // M2 turn off interrupts and interruption collection + cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs - mov.m ar.ssd=r0 // clear ar.ssd - mov.m ar.csd=r0 // clear ar.csd - mov f10=f0 // clear f10 + ld8 r29=[r2],16 // M0|1 load cr.ipsr + ld8 r28=[r3],16 // M0|1 load cr.iip + mov r22=r0 // A clear r22 ;; - ld8 r26=[r16],16 // load ar.pfs - ld8 r27=[r17],PT(PR)-PT(AR_RSC) // load ar.rsc - mov f11=f0 // clear f11 - ;; - ld8 r24=[r16],PT(B0)-PT(AR_RNAT) // load ar.rnat (may be garbage) - ld8 r31=[r17],PT(R1)-PT(PR) // load predicates + ld8 r30=[r2],16 // M0|1 load cr.ifs + ld8 r25=[r3],16 // M0|1 load ar.unat (pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 ;; - ld8 r21=[r16],PT(R12)-PT(B0) // load b0 - ld8.fill r1=[r17],16 // load r1 -(pUStk) mov r3=1 + ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs +(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled + nop 0 ;; - ld8.fill r12=[r16],16 - ld8.fill r13=[r17],16 - mov r2=r0 // clear r2 + ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0 + ld8 r27=[r3],PT(PR)-PT(AR_RSC) // M0|1 load ar.rsc + mov f6=f0 // F clear f6 ;; - ld8 r20=[r16] // load ar.fpsr - ld8.fill r15=[r17] // load r15 - mov b7=r0 // clear b7 + ld8 r24=[r2],PT(AR_FPSR)-PT(AR_RNAT) // M0|1 load ar.rnat (may be garbage) + ld8 r31=[r3],PT(R1)-PT(PR) // M0|1 load predicates + mov f7=f0 // F clear f7 ;; -(pUStk) st1 [r14]=r3 - addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 + ld8 r20=[r2],PT(R12)-PT(AR_FPSR) // M0|1 load ar.fpsr + ld8.fill r1=[r3],16 // M0|1 load r1 +(pUStk) mov r17=1 // A ;; - mov r16=ar.bsp // get existing backing store pointer - srlz.i // ensure interruption collection is off - mov r14=r0 // clear r14 +(pUStk) st1 [r14]=r17 // M2|3 + ld8.fill r13=[r3],16 // M0|1 + mov f8=f0 // F clear f8 ;; - ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8 - mov b6=r22 // restore b6 - shr.u r18=r19,16 // get byte size of existing "dirty" partition -(pKStk) br.cond.dpnt.many skip_rbs_switch -(pNonSys) br.cond.dpnt.many dont_preserve_current_frame - br.cond.sptk.many rbs_switch -END(ia64_leave_syscall) + ld8.fill r12=[r2] // M0|1 restore r12 (sp) + ld8.fill r15=[r3] // M0|1 restore r15 + mov b6=r18 // I0 restore b6 + + addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 // A + mov f9=f0 // F clear f9 +(pKStk) br.cond.dpnt.many skip_rbs_switch // B + + srlz.d // M0 ensure interruption collection is off (for cover) + shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition + cover // B add current frame into dirty partition & set cr.ifs + ;; +(pUStk) ld4 r17=[r17] // M0|1 r17 = cpu_data->phys_stacked_size_p8 + mov r19=ar.bsp // M2 get new backing store pointer + mov f10=f0 // F clear f10 + + nop.m 0 + movl r14=__kernel_syscall_via_epc // X + ;; + mov.m ar.csd=r0 // M2 clear ar.csd + mov.m ar.ccv=r0 // M2 clear ar.ccv + mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc) + + mov.m ar.ssd=r0 // M2 clear ar.ssd + mov f11=f0 // F clear f11 + br.cond.sptk.many rbs_switch // B +END(__ia64_leave_syscall) #ifdef CONFIG_IA32_SUPPORT GLOBAL_ENTRY(ia64_ret_from_ia32_execve) @@ -777,10 +804,13 @@ GLOBAL_ENTRY(ia64_ret_from_ia32_execve) st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit .mem.offset 8,0 st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit -END(ia64_ret_from_ia32_execve_syscall) - // fall through + ;; + // don't fall through, ia64_leave_kernel may be #define'd + br.cond.sptk.few ia64_leave_kernel + ;; +END(ia64_ret_from_ia32_execve) #endif /* CONFIG_IA32_SUPPORT */ -GLOBAL_ENTRY(ia64_leave_kernel) +GLOBAL_ENTRY(__ia64_leave_kernel) PT_REGS_UNWIND_INFO(0) /* * work.need_resched etc. mustn't get changed by this CPU before it returns to @@ -880,15 +910,19 @@ GLOBAL_ENTRY(ia64_leave_kernel) ldf.fill f7=[r2],PT(F11)-PT(F7) ldf.fill f8=[r3],32 ;; - srlz.i // ensure interruption collection is off + 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...) ;; - ldf.fill f11=[r2] -(pUStk) mov r18=IA64_KR(CURRENT) // Itanium 2: 12 cycle read latency +(pUStk) mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency) 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 @@ -901,7 +935,7 @@ GLOBAL_ENTRY(ia64_leave_kernel) cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs ;; ld8 r24=[r16],16 // load ar.rnat (may be garbage) - ld8 r23=[r17],16// load ar.bspstore (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 @@ -936,11 +970,10 @@ GLOBAL_ENTRY(ia64_leave_kernel) * NOTE: alloc, loadrs, and cover can't be predicated. */ (pNonSys) br.cond.dpnt dont_preserve_current_frame - -rbs_switch: cover // add current frame into dirty partition and set cr.ifs ;; mov r19=ar.bsp // get new backing store pointer +rbs_switch: sub r16=r16,r18 // krbs = old bsp - size of dirty partition cmp.ne p9,p0=r0,r0 // clear p9 to skip restore of cr.ifs ;; @@ -971,6 +1004,7 @@ dont_preserve_current_frame: shladd in0=loc1,3,r17 mov in1=0 ;; + TEXT_ALIGN(32) rse_clear_invalid: #ifdef CONFIG_ITANIUM // cycle 0 @@ -1014,14 +1048,14 @@ rse_clear_invalid: mov loc5=0 mov loc6=0 mov loc7=0 -(pRecurse) br.call.sptk.few b0=rse_clear_invalid +(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.sptk.many b0 +(pReturn) br.ret.dptk.many b0 #endif /* !CONFIG_ITANIUM */ # undef pRecurse # undef pReturn @@ -1031,23 +1065,33 @@ rse_clear_invalid: loadrs ;; skip_rbs_switch: -(pLvSys) mov r19=r0 // clear r19 for leave_syscall, no-op otherwise - mov b0=r21 - mov ar.pfs=r26 -(pUStk) mov ar.bspstore=r23 -(p9) mov cr.ifs=r30 -(pLvSys)mov r16=r0 // clear r16 for leave_syscall, no-op otherwise - mov cr.ipsr=r29 - mov ar.fpsr=r20 -(pLvSys)mov r17=r0 // clear r17 for leave_syscall, no-op otherwise - mov cr.iip=r28 - ;; -(pUStk) mov ar.rnat=r24 // must happen with RSE in lazy mode -(pLvSys)mov r18=r0 // clear r18 for leave_syscall, no-op otherwise - mov ar.rsc=r27 - mov ar.unat=r25 - mov pr=r31,-1 - rfi + 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 + +(p9) mov cr.ifs=r30 // M2 + 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 +(pLvSys)mov r2=r0 + + mov ar.rsc=r27 // M2 + mov pr=r31,-1 // I0 + rfi // B /* * On entry: @@ -1056,6 +1100,12 @@ skip_rbs_switch: * 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.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0? (p6) br.cond.sptk.few .notify @@ -1074,15 +1124,24 @@ skip_rbs_switch: ;; (pKStk) st4 [r20]=r0 // preempt_count() <- 0 #endif -(pLvSys)br.cond.sptk.many .work_processed_syscall // re-check +(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.many .work_processed_syscall // don't re-check +(pLvSys)br.cond.sptk.few .work_pending_syscall_end br.cond.sptk.many .work_processed_kernel // don't re-check -END(ia64_leave_kernel) + +.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 + +END(__ia64_leave_kernel) ENTRY(handle_syscall_error) /* @@ -1093,17 +1152,11 @@ ENTRY(handle_syscall_error) */ 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 +(p7) mov r10=-1 +(p7) sub r8=0,r8 // negate return value to get errno br.cond.sptk ia64_leave_syscall END(handle_syscall_error) @@ -1128,7 +1181,7 @@ END(ia64_invoke_schedule_tail) * 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) +GLOBAL_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 @@ -1139,7 +1192,7 @@ ENTRY(notify_resume_user) ;; (pNonSys) mov out2=0 // out2==0 => not a syscall .fframe 16 - .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) + .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 @@ -1165,7 +1218,7 @@ GLOBAL_ENTRY(sys_rt_sigsuspend) adds out2=8,sp // out2=&sigscratch->ar_pfs ;; .fframe 16 - .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) + .spillsp ar.unat, 16 st8 [sp]=r9,-16 // allocate space for ar.unat and save it st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch .body @@ -1183,7 +1236,10 @@ END(sys_rt_sigsuspend) ENTRY(sys_rt_sigreturn) PT_REGS_UNWIND_INFO(0) - alloc r2=ar.pfs,0,0,1,0 + /* + * Allocate 8 input registers since ptrace() may clobber them + */ + alloc r2=ar.pfs,8,0,1,0 .prologue PT_REGS_SAVES(16) adds sp=-16,sp @@ -1209,11 +1265,11 @@ ENTRY(sys_rt_sigreturn) stf.spill [r17]=f11 adds out0=16,sp // out0 = &sigscratch br.call.sptk.many rp=ia64_rt_sigreturn -.ret19: .restore sp 0 +.ret19: .restore sp,0 adds sp=16,sp ;; ld8 r9=[sp] // load new ar.unat - mov.sptk b7=r8,ia64_leave_kernel + mov.sptk b7=r8,__ia64_leave_kernel ;; mov ar.unat=r9 br.many b7 @@ -1371,7 +1427,7 @@ sys_call_table: data8 sys_msgrcv data8 sys_msgctl data8 sys_shmget - data8 ia64_shmat + data8 sys_shmat data8 sys_shmdt // 1115 data8 sys_shmctl data8 sys_syslog @@ -1525,17 +1581,40 @@ sys_call_table: data8 sys_mq_timedreceive // 1265 data8 sys_mq_notify data8 sys_mq_getsetattr - data8 sys_ni_syscall // reserved for kexec_load + data8 sys_kexec_load data8 sys_vserver - data8 sys_ni_syscall // 1270 - data8 sys_ni_syscall - data8 sys_ni_syscall - data8 sys_ni_syscall - data8 sys_ni_syscall - data8 sys_ni_syscall // 1275 - data8 sys_ni_syscall - data8 sys_ni_syscall - data8 sys_ni_syscall - data8 sys_ni_syscall + data8 sys_waitid // 1270 + data8 sys_add_key + data8 sys_request_key + data8 sys_keyctl + data8 sys_ioprio_set + data8 sys_ioprio_get // 1275 + data8 sys_move_pages + data8 sys_inotify_init + data8 sys_inotify_add_watch + data8 sys_inotify_rm_watch + data8 sys_migrate_pages // 1280 + data8 sys_openat + data8 sys_mkdirat + data8 sys_mknodat + data8 sys_fchownat + data8 sys_futimesat // 1285 + data8 sys_newfstatat + data8 sys_unlinkat + data8 sys_renameat + data8 sys_linkat + data8 sys_symlinkat // 1290 + data8 sys_readlinkat + data8 sys_fchmodat + data8 sys_faccessat + data8 sys_ni_syscall // reserved for pselect + data8 sys_ni_syscall // 1295 reserved for ppoll + data8 sys_unshare + data8 sys_splice + data8 sys_set_robust_list + data8 sys_get_robust_list + data8 sys_sync_file_range // 1300 + data8 sys_tee + data8 sys_vmsplice .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls