#include <asm/asmmacro.h>
+#include <asm/ia32.h>
#include <asm/offsets.h>
#include <asm/signal.h>
#include <asm/thread_info.h>
adds r2=IA64_PT_REGS_R8_OFFSET+16,sp
;;
st8 [r2]=r3 // initialize return code to -ENOSYS
- br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args
- // Need to reload arguments (they may be changed by the tracing process)
- adds r2=IA64_PT_REGS_R9_OFFSET+16,sp // r2 = &pt_regs.r9
+ br.call.sptk.few rp=syscall_trace // give parent a chance to catch syscall args
+.ret2: // Need to reload arguments (they may be changed by the tracing process)
+ adds r2=IA64_PT_REGS_R1_OFFSET+16,sp // r2 = &pt_regs.r1
adds r3=IA64_PT_REGS_R13_OFFSET+16,sp // r3 = &pt_regs.r13
+ mov r15=IA32_NR_syscalls
+ ;;
+ ld4 r8=[r2],IA64_PT_REGS_R9_OFFSET-IA64_PT_REGS_R1_OFFSET
+ movl r16=ia32_syscall_table
;;
ld4 r33=[r2],8 // r9 == ecx
ld4 r37=[r3],16 // r13 == ebp
+ cmp.ltu.unc p6,p7=r8,r15
;;
ld4 r34=[r2],8 // r10 == edx
ld4 r36=[r3],8 // r15 == edi
+(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
+ ;;
+ ld8 r16=[r16]
;;
ld4 r32=[r2],8 // r11 == ebx
+ mov b6=r16
ld4 r35=[r3],8 // r14 == esi
- ;;
-.ret2: br.call.sptk.few rp=b6 // do the syscall
+ br.call.sptk.few rp=b6 // do the syscall
.ia32_strace_check_retval:
cmp.lt p6,p0=r8,r0 // syscall failed?
adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8
;;
st8.spill [r2]=r8 // store return value in slot for r8
- br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value
+ br.call.sptk.few rp=syscall_trace // give parent a chance to catch return value
.ret4: alloc r2=ar.pfs,0,0,0,0 // drop the syscall argument frame
br.cond.sptk.many ia64_leave_kernel
END(ia32_trace_syscall)
data8 sys_ni_syscall
data8 sys_statfs64
data8 sys_fstatfs64
- data8 sys_ni_syscall
-
- /*
- * CAUTION: If any system calls are added beyond this point
- * then the check in `arch/ia64/kernel/ivt.S' will have
- * to be modified also. You've been warned.
- */
+
+ // guard against failures to increase IA32_NR_syscalls
+ .org ia32_syscall_table + 8*IA32_NR_syscalls
br.ret.sptk.many rp
END(clone)
- /*
- * We invoke syscall_trace through this intermediate function to
- * ensure that the syscall input arguments are not clobbered. We
- * also use it to preserve b6, which contains the syscall entry point.
- */
-GLOBAL_ENTRY(invoke_syscall_trace)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
- alloc loc1=ar.pfs,8,3,0,0
- mov loc0=rp
- .body
- mov loc2=b6
- ;;
- br.call.sptk.many rp=syscall_trace
-.ret3: mov rp=loc0
- mov ar.pfs=loc1
- mov b6=loc2
- br.ret.sptk.many rp
-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_kernel
*/
nop.m 0
nop.i 0
- br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch syscall args
+ br.call.sptk.many rp=syscall_trace // give parent a chance to catch syscall args
}
-.ret6: br.call.sptk.many rp=b6 // do the syscall
-strace_check_retval:
+ // the syscall number may have changed, so re-load it and re-calculate the
+ // syscall entry-point:
+ adds r15=PT(R15)+16,sp // r15 = &pt_regs.r15 (syscall #)
+ ;;
+ ld8 r15=[r15]
+ mov r3=NR_syscalls - 1
+ ;;
+ adds r15=-1024,r15
+ movl r16=sys_call_table
+ ;;
+ shladd r20=r15,3,r16 // r20 = sys_call_table + 8*(syscall-1024)
+ cmp.leu p6,p7=r15,r3
+ ;;
+(p6) ld8 r20=[r20] // load address of syscall entry point
+(p7) movl r20=sys_ni_syscall
+ ;;
+ mov b6=r20
+ br.call.sptk.many rp=b6 // do the syscall
+.strace_check_retval:
cmp.lt p6,p0=r8,r0 // syscall failed?
adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10
mov r10=0
(p6) br.cond.sptk strace_error // syscall failed ->
;; // avoid RAW on r10
-strace_save_retval:
+.strace_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 r10
ia64_strace_leave_kernel:
- br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch return value
+ br.call.sptk.many rp=syscall_trace // give parent a chance to catch return value
.rety: br.cond.sptk ia64_leave_syscall
strace_error:
;;
(p6) mov r10=-1
(p6) mov r8=r9
- br.cond.sptk strace_save_retval
+ br.cond.sptk .strace_save_retval
END(ia64_trace_syscall)
GLOBAL_ENTRY(ia64_ret_from_clone)
;;
mov r8=0
tbit.nz p6,p0=r2,TIF_SYSCALL_TRACE
-(p6) br.cond.spnt strace_check_retval
+(p6) br.cond.spnt .strace_check_retval
;; // added stop bits to prevent r8 dependency
END(ia64_ret_from_clone)
// fall through
#include <asm/asmmacro.h>
#include <asm/break.h>
+#include <asm/ia32.h>
#include <asm/kregs.h>
#include <asm/offsets.h>
#include <asm/pgtable.h>
movl r2=ia64_ret_from_syscall
;;
shladd r20=r15,3,r16 // r20 = sys_call_table + 8*(syscall-1024)
- cmp.geu p0,p7=r3,r15 // (syscall > 0 && syscall < 1024 + NR_syscalls) ?
+ cmp.leu p6,p7=r15,r3 // (syscall > 0 && syscall < 1024 + NR_syscalls) ?
mov rp=r2 // set the real return addr
;;
-(p7) add r20=(__NR_ni_syscall-1024)*8,r16 // force __NR_ni_syscall
+(p6) ld8 r20=[r20] // load address of syscall entry point
+(p7) movl r20=sys_ni_syscall
+
add r2=TI_FLAGS+IA64_TASK_SIZE,r13
;;
- ld8 r20=[r20] // load address of syscall entry point
ld4 r2=[r2] // r2 = current_thread_info()->flags
;;
tbit.z p8,p0=r2,TIF_SYSCALL_TRACE
alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
;;
ld4 r8=[r14],8 // r8 == eax (syscall number)
- mov r15=270 // number of entries in ia32 system call table
+ mov r15=IA32_NR_syscalls
;;
cmp.ltu.unc p6,p7=r8,r15
ld4 out1=[r14],8 // r9 == ecx
return ret;
}
-void
+/* "asmlinkage" so the input arguments are preserved... */
+
+asmlinkage void
syscall_trace (void)
{
if (!test_thread_flag(TIF_SYSCALL_TRACE))
#include <asm/ptrace.h>
#include <asm/signal.h>
-#ifdef CONFIG_IA32_SUPPORT
+#define IA32_NR_syscalls 270 /* length of syscall table */
+
+#ifndef __ASSEMBLY__
+
+# ifdef CONFIG_IA32_SUPPORT
extern void ia32_cpu_init (void);
extern void ia32_boot_gdt_init (void);
extern int ia32_intercept (struct pt_regs *regs, unsigned long isr);
extern int ia32_clone_tls (struct task_struct *child, struct pt_regs *childregs);
-#endif /* !CONFIG_IA32_SUPPORT */
+# endif /* !CONFIG_IA32_SUPPORT */
/* Declare this unconditionally, so we don't get warnings for unreachable code. */
extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs);
+#endif /* !__ASSEMBLY__ */
+
#endif /* _ASM_IA64_IA32_H */