aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/elf_machdep.c6
-rw-r--r--sys/amd64/amd64/trap.c157
-rw-r--r--sys/amd64/ia32/ia32_syscall.c160
-rw-r--r--sys/amd64/include/proc.h8
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c47
-rw-r--r--sys/arm/arm/elf_machdep.c6
-rw-r--r--sys/arm/arm/trap.c1
-rw-r--r--sys/cddl/dev/systrace/systrace.c1
-rw-r--r--sys/compat/ia32/ia32_sysvec.c7
-rw-r--r--sys/compat/ia32/ia32_util.h4
-rw-r--r--sys/compat/svr4/svr4_sysvec.c5
-rw-r--r--sys/conf/files2
-rw-r--r--sys/i386/i386/elf_machdep.c6
-rw-r--r--sys/i386/i386/trap.c164
-rw-r--r--sys/i386/ibcs2/ibcs2_sysvec.c5
-rw-r--r--sys/i386/include/proc.h8
-rw-r--r--sys/i386/linux/linux_sysvec.c54
-rw-r--r--sys/ia64/ia32/ia32_trap.c182
-rw-r--r--sys/ia64/ia64/elf_machdep.c5
-rw-r--r--sys/ia64/ia64/trap.c135
-rw-r--r--sys/ia64/include/proc.h10
-rw-r--r--sys/kern/imgact_aout.c4
-rw-r--r--sys/kern/init_main.c21
-rw-r--r--sys/kern/kern_exec.c4
-rw-r--r--sys/kern/kern_sig.c2
-rw-r--r--sys/kern/subr_trap.c162
-rw-r--r--sys/kern/sys_process.c8
-rw-r--r--sys/mips/mips/elf64_machdep.c6
-rw-r--r--sys/mips/mips/elf_machdep.c11
-rw-r--r--sys/mips/mips/trap.c1
-rw-r--r--sys/powerpc/aim/trap.c125
-rw-r--r--sys/powerpc/booke/trap.c118
-rw-r--r--sys/powerpc/include/proc.h10
-rw-r--r--sys/powerpc/powerpc/elf_machdep.c5
-rw-r--r--sys/sparc64/include/proc.h12
-rw-r--r--sys/sparc64/sparc64/elf_machdep.c6
-rw-r--r--sys/sparc64/sparc64/trap.c123
-rw-r--r--sys/sun4v/include/proc.h12
-rw-r--r--sys/sun4v/sun4v/trap.c157
-rw-r--r--sys/sys/proc.h8
-rw-r--r--sys/sys/ptrace.h3
-rw-r--r--sys/sys/sysent.h6
42 files changed, 736 insertions, 1041 deletions
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
index dc7c8b9ed8a6..6472d55e35fa 100644
--- a/sys/amd64/amd64/elf_machdep.c
+++ b/sys/amd64/amd64/elf_machdep.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/linker.h>
+#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/syscall.h>
@@ -74,7 +75,10 @@ struct sysentvec elf64_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_FREEBSD | SV_LP64
+ .sv_flags = SV_ABI_FREEBSD | SV_LP64,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = syscallnames,
};
static Elf64_Brandinfo freebsd_brand_info = {
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index d5ddc590027e..2deb93198540 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -76,7 +76,6 @@ __FBSDID("$FreeBSD$");
#ifdef HWPMC_HOOKS
#include <sys/pmckern.h>
#endif
-#include <security/audit/audit.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -170,8 +169,6 @@ static int prot_fault_translation = 0;
SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
&prot_fault_translation, 0, "Select signal to deliver on protection fault");
-extern char *syscallnames[];
-
/*
* Exception, fault, and trap interface to the FreeBSD kernel.
* This common code is called from assembly language IDT gate entry
@@ -805,19 +802,12 @@ dblfault_handler(struct trapframe *frame)
panic("double fault");
}
-struct syscall_args {
- u_int code;
- struct sysent *callp;
- register_t args[8];
- register_t *argp;
- int narg;
-};
-
-static int
-fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+int
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
struct proc *p;
struct trapframe *frame;
+ register_t *argp;
caddr_t params;
int reg, regcnt, error;
@@ -829,15 +819,10 @@ fetch_syscall_args(struct thread *td, struct syscall_args *sa)
params = (caddr_t)frame->tf_rsp + sizeof(register_t);
sa->code = frame->tf_rax;
- if (p->p_sysent->sv_prepsyscall) {
- (*p->p_sysent->sv_prepsyscall)(frame, (int *)sa->args,
- &sa->code, &params);
- } else {
- if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
- sa->code = frame->tf_rdi;
- reg++;
- regcnt--;
- }
+ if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
+ sa->code = frame->tf_rdi;
+ reg++;
+ regcnt--;
}
if (p->p_sysent->sv_mask)
sa->code &= p->p_sysent->sv_mask;
@@ -851,24 +836,20 @@ fetch_syscall_args(struct thread *td, struct syscall_args *sa)
KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
("Too many syscall arguments!"));
error = 0;
- sa->argp = &frame->tf_rdi;
- sa->argp += reg;
- bcopy(sa->argp, sa->args, sizeof(sa->args[0]) * regcnt);
+ argp = &frame->tf_rdi;
+ argp += reg;
+ bcopy(argp, sa->args, sizeof(sa->args[0]) * regcnt);
if (sa->narg > regcnt) {
KASSERT(params != NULL, ("copyin args with no params!"));
error = copyin(params, &sa->args[regcnt],
(sa->narg - regcnt) * sizeof(sa->args[0]));
}
- sa->argp = &sa->args[0];
- /*
- * This may result in two records if debugger modified
- * registers or memory during sleep at stop/ptrace point.
- */
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(sa->code, sa->narg, sa->argp);
-#endif
+ if (error == 0) {
+ td->td_retval[0] = 0;
+ td->td_retval[1] = frame->tf_rdx;
+ }
+
return (error);
}
@@ -881,87 +862,22 @@ void
syscall(struct trapframe *frame)
{
struct thread *td;
- struct proc *p;
struct syscall_args sa;
register_t orig_tf_rflags;
int error;
ksiginfo_t ksi;
- PCPU_INC(cnt.v_syscall);
- td = curthread;
- p = td->td_proc;
- td->td_syscalls++;
-
#ifdef DIAGNOSTIC
if (ISPL(frame->tf_cs) != SEL_UPL) {
panic("syscall");
/* NOT REACHED */
}
#endif
-
- td->td_pticks = 0;
- td->td_frame = frame;
- if (td->td_ucred != p->p_ucred)
- cred_update_thread(td);
orig_tf_rflags = frame->tf_rflags;
- if (p->p_flag & P_TRACED) {
- PROC_LOCK(p);
- td->td_dbgflags &= ~TDB_USERWR;
- PROC_UNLOCK(p);
- }
- error = fetch_syscall_args(td, &sa);
-
- CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, sa.code);
-
- if (error == 0) {
- td->td_retval[0] = 0;
- td->td_retval[1] = frame->tf_rdx;
-
- STOPEVENT(p, S_SCE, sa.narg);
- PTRACESTOP_SC(p, td, S_PT_SCE);
- if (td->td_dbgflags & TDB_USERWR) {
- /*
- * Reread syscall number and arguments if
- * debugger modified registers or memory.
- */
- error = fetch_syscall_args(td, &sa);
- if (error != 0)
- goto retval;
- td->td_retval[1] = frame->tf_rdx;
- }
-
-#ifdef KDTRACE_HOOKS
- /*
- * If the systrace module has registered it's probe
- * callback and if there is a probe active for the
- * syscall 'entry', process the probe.
- */
- if (systrace_probe_func != NULL && sa.callp->sy_entry != 0)
- (*systrace_probe_func)(sa.callp->sy_entry, sa.code,
- sa.callp, sa.args);
-#endif
-
- AUDIT_SYSCALL_ENTER(sa.code, td);
- error = (*sa.callp->sy_call)(td, sa.argp);
- AUDIT_SYSCALL_EXIT(error, td);
+ td = curthread;
+ td->td_frame = frame;
- /* Save the latest error return value. */
- td->td_errno = error;
-
-#ifdef KDTRACE_HOOKS
- /*
- * If the systrace module has registered it's probe
- * callback and if there is a probe active for the
- * syscall 'return', process the probe.
- */
- if (systrace_probe_func != NULL && sa.callp->sy_return != 0)
- (*systrace_probe_func)(sa.callp->sy_return, sa.code,
- sa.callp, sa.args);
-#endif
- }
- retval:
- cpu_set_syscall_retval(td, error);
+ error = syscallenter(td, &sa);
/*
* Traced syscall.
@@ -975,40 +891,5 @@ syscall(struct trapframe *frame)
trapsignal(td, &ksi);
}
- /*
- * Check for misbehavior.
- */
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- syscallnames[sa.code] : "???");
- KASSERT(td->td_critnest == 0,
- ("System call %s returning in a critical section",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- syscallnames[sa.code] : "???"));
- KASSERT(td->td_locks == 0,
- ("System call %s returning with %d locks held",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- syscallnames[sa.code] : "???", td->td_locks));
-
- /*
- * Handle reschedule and other end-of-syscall issues
- */
- userret(td, frame);
-
- CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, sa.code);
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(sa.code, error, td->td_retval[0]);
-#endif
-
- /*
- * This works because errno is findable through the
- * register set. If we ever support an emulation where this
- * is not the case, this code will need to be revisited.
- */
- STOPEVENT(p, S_SCX, sa.code);
-
- PTRACESTOP_SC(p, td, S_PT_SCX);
+ syscallret(td, error, &sa);
}
diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c
index aa1ae6cbd719..6a649aeeb19f 100644
--- a/sys/amd64/ia32/ia32_syscall.c
+++ b/sys/amd64/ia32/ia32_syscall.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
@@ -81,62 +82,54 @@ __FBSDID("$FreeBSD$");
#include <machine/intr_machdep.h>
#include <machine/md_var.h>
+#include <compat/freebsd32/freebsd32_util.h>
+
#define IDTVEC(name) __CONCAT(X,name)
extern inthand_t IDTVEC(int0x80_syscall), IDTVEC(rsvd);
-extern const char *freebsd32_syscallnames[];
void ia32_syscall(struct trapframe *frame); /* Called from asm code */
-struct ia32_syscall_args {
- u_int code;
- caddr_t params;
- struct sysent *callp;
- u_int64_t args64[8];
- int narg;
-};
+void
+ia32_set_syscall_retval(struct thread *td, int error)
+{
-static int
-fetch_ia32_syscall_args(struct thread *td, struct ia32_syscall_args *sa)
+ cpu_set_syscall_retval(td, error);
+}
+
+int
+ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
struct proc *p;
struct trapframe *frame;
+ caddr_t params;
u_int32_t args[8];
int error, i;
p = td->td_proc;
frame = td->td_frame;
- sa->params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
+ params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t);
sa->code = frame->tf_rax;
- if (p->p_sysent->sv_prepsyscall) {
+ /*
+ * Need to check if this is a 32 bit or 64 bit syscall.
+ */
+ if (sa->code == SYS_syscall) {
/*
- * The prep code is MP aware.
+ * Code is first argument, followed by actual args.
*/
- (*p->p_sysent->sv_prepsyscall)(frame, args, &sa->code,
- &sa->params);
- } else {
+ sa->code = fuword32(params);
+ params += sizeof(int);
+ } else if (sa->code == SYS___syscall) {
/*
- * Need to check if this is a 32 bit or 64 bit syscall.
- * fuword is MP aware.
+ * Like syscall, but code is a quad, so as to maintain
+ * quad alignment for the rest of the arguments.
+ * We use a 32-bit fetch in case params is not
+ * aligned.
*/
- if (sa->code == SYS_syscall) {
- /*
- * Code is first argument, followed by actual args.
- */
- sa->code = fuword32(sa->params);
- sa->params += sizeof(int);
- } else if (sa->code == SYS___syscall) {
- /*
- * Like syscall, but code is a quad, so as to maintain
- * quad alignment for the rest of the arguments.
- * We use a 32-bit fetch in case params is not
- * aligned.
- */
- sa->code = fuword32(sa->params);
- sa->params += sizeof(quad_t);
- }
+ sa->code = fuword32(params);
+ params += sizeof(quad_t);
}
if (p->p_sysent->sv_mask)
sa->code &= p->p_sysent->sv_mask;
@@ -146,19 +139,19 @@ fetch_ia32_syscall_args(struct thread *td, struct ia32_syscall_args *sa)
sa->callp = &p->p_sysent->sv_table[sa->code];
sa->narg = sa->callp->sy_narg;
- if (sa->params != NULL && sa->narg != 0)
- error = copyin(sa->params, (caddr_t)args,
+ if (params != NULL && sa->narg != 0)
+ error = copyin(params, (caddr_t)args,
(u_int)(sa->narg * sizeof(int)));
else
error = 0;
for (i = 0; i < sa->narg; i++)
- sa->args64[i] = args[i];
+ sa->args[i] = args[i];
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(sa->code, sa->narg, sa->args64);
-#endif
+ if (error == 0) {
+ td->td_retval[0] = 0;
+ td->td_retval[1] = frame->tf_rdx;
+ }
return (error);
}
@@ -167,58 +160,16 @@ void
ia32_syscall(struct trapframe *frame)
{
struct thread *td;
- struct proc *p;
- struct ia32_syscall_args sa;
+ struct syscall_args sa;
register_t orig_tf_rflags;
int error;
ksiginfo_t ksi;
- PCPU_INC(cnt.v_syscall);
+ orig_tf_rflags = frame->tf_rflags;
td = curthread;
- p = td->td_proc;
- td->td_syscalls++;
-
- td->td_pticks = 0;
td->td_frame = frame;
- if (td->td_ucred != p->p_ucred)
- cred_update_thread(td);
- orig_tf_rflags = frame->tf_rflags;
- if (p->p_flag & P_TRACED) {
- PROC_LOCK(p);
- td->td_dbgflags &= ~TDB_USERWR;
- PROC_UNLOCK(p);
- }
- error = fetch_ia32_syscall_args(td, &sa);
-
- CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, sa.code);
-
- if (error == 0) {
- td->td_retval[0] = 0;
- td->td_retval[1] = frame->tf_rdx;
- STOPEVENT(p, S_SCE, sa.narg);
- PTRACESTOP_SC(p, td, S_PT_SCE);
- if (td->td_dbgflags & TDB_USERWR) {
- /*
- * Reread syscall number and arguments if
- * debugger modified registers or memory.
- */
- error = fetch_ia32_syscall_args(td, &sa);
- if (error != 0)
- goto retval;
- td->td_retval[1] = frame->tf_rdx;
- }
-
- AUDIT_SYSCALL_ENTER(sa.code, td);
- error = (*sa.callp->sy_call)(td, sa.args64);
- AUDIT_SYSCALL_EXIT(error, td);
-
- /* Save the latest error return value. */
- td->td_errno = error;
- }
- retval:
- cpu_set_syscall_retval(td, error);
+ error = syscallenter(td, &sa);
/*
* Traced syscall.
@@ -232,44 +183,9 @@ ia32_syscall(struct trapframe *frame)
trapsignal(td, &ksi);
}
- /*
- * Check for misbehavior.
- */
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- freebsd32_syscallnames[sa.code] : "???");
- KASSERT(td->td_critnest == 0,
- ("System call %s returning in a critical section",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- freebsd32_syscallnames[sa.code] : "???"));
- KASSERT(td->td_locks == 0,
- ("System call %s returning with %d locks held",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- freebsd32_syscallnames[sa.code] : "???", td->td_locks));
-
- /*
- * Handle reschedule and other end-of-syscall issues
- */
- userret(td, frame);
-
- CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_proc->p_comm, sa.code);
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(sa.code, error, td->td_retval[0]);
-#endif
-
- /*
- * This works because errno is findable through the
- * register set. If we ever support an emulation where this
- * is not the case, this code will need to be revisited.
- */
- STOPEVENT(p, S_SCX, sa.code);
-
- PTRACESTOP_SC(p, td, S_PT_SCX);
+ syscallret(td, error, &sa);
}
-
static void
ia32_syscall_enable(void *dummy)
{
diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h
index acea4c0a77f0..2de7a9e698bf 100644
--- a/sys/amd64/include/proc.h
+++ b/sys/amd64/include/proc.h
@@ -79,6 +79,14 @@ int amd64_set_ldt_data(struct thread *td, int start, int num,
extern struct mtx dt_lock;
extern int max_ldt_segment;
+struct syscall_args {
+ u_int code;
+ struct sysent *callp;
+ register_t args[8];
+ int narg;
+};
+#define HAVE_SYSCALL_ARGS_DEF 1
+
#endif /* _KERNEL */
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 06f1e979e33a..010e1d60d5ed 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -121,8 +121,6 @@ SET_DECLARE(linux_device_handler_set, struct linux_device_handler);
static int elf_linux_fixup(register_t **stack_base,
struct image_params *iparams);
static register_t *linux_copyout_strings(struct image_params *imgp);
-static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code,
- caddr_t *params);
static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
static void exec_linux_setregs(struct thread *td,
struct image_params *imgp, u_long stack);
@@ -764,19 +762,33 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
return (EJUSTRETURN);
}
-/*
- * MPSAFE
- */
-static void
-linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params)
+static int
+linux32_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
- args[0] = tf->tf_rbx;
- args[1] = tf->tf_rcx;
- args[2] = tf->tf_rdx;
- args[3] = tf->tf_rsi;
- args[4] = tf->tf_rdi;
- args[5] = tf->tf_rbp; /* Unconfirmed */
- *params = NULL; /* no copyin */
+ struct proc *p;
+ struct trapframe *frame;
+
+ p = td->td_proc;
+ frame = td->td_frame;
+
+ sa->args[0] = frame->tf_rbx;
+ sa->args[1] = frame->tf_rcx;
+ sa->args[2] = frame->tf_rdx;
+ sa->args[3] = frame->tf_rsi;
+ sa->args[4] = frame->tf_rdi;
+ sa->args[5] = frame->tf_rbp; /* Unconfirmed */
+ sa->code = frame->tf_rax;
+
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
+ else
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+ sa->narg = sa->callp->sy_narg;
+
+ td->td_retval[0] = 0;
+ td->td_retval[1] = frame->tf_rdx;
+
+ return (0);
}
/*
@@ -1039,7 +1051,7 @@ struct sysentvec elf_linux_sysvec = {
.sv_sendsig = linux_sendsig,
.sv_sigcode = linux_sigcode,
.sv_szsigcode = &linux_szsigcode,
- .sv_prepsyscall = linux_prepsyscall,
+ .sv_prepsyscall = NULL,
.sv_name = "Linux ELF32",
.sv_coredump = elf32_coredump,
.sv_imgact_try = exec_linux_imgact_try,
@@ -1054,7 +1066,10 @@ struct sysentvec elf_linux_sysvec = {
.sv_setregs = exec_linux_setregs,
.sv_fixlimit = linux32_fixlimit,
.sv_maxssiz = &linux32_maxssiz,
- .sv_flags = SV_ABI_LINUX | SV_ILP32 | SV_IA32
+ .sv_flags = SV_ABI_LINUX | SV_ILP32 | SV_IA32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = linux32_fetch_syscall_args,
+ .sv_syscallnames = NULL,
};
static char GNU_ABI_VENDOR[] = "GNU";
diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c
index d77e7d49a980..e77a54273f35 100644
--- a/sys/arm/arm/elf_machdep.c
+++ b/sys/arm/arm/elf_machdep.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
+#include <sys/proc.h>
#include <sys/syscall.h>
#include <sys/signalvar.h>
#include <sys/vnode.h>
@@ -73,7 +74,10 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_FREEBSD | SV_ILP32
+ .sv_flags = SV_ABI_FREEBSD | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = NULL, /* XXXKIB */
+ .sv_syscallnames = syscallnames,
};
static Elf32_Brandinfo freebsd_brand_info = {
diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c
index 284e79790162..c7c84d0394d3 100644
--- a/sys/arm/arm/trap.c
+++ b/sys/arm/arm/trap.c
@@ -130,7 +130,6 @@ void undefinedinstruction(trapframe_t *);
#include <machine/machdep.h>
extern char fusubailout[];
-extern char *syscallnames[];
#ifdef DEBUG
int last_fault_code; /* For the benefit of pmap_fault_fixup() */
diff --git a/sys/cddl/dev/systrace/systrace.c b/sys/cddl/dev/systrace/systrace.c
index e54f776576d5..72c25e4e291e 100644
--- a/sys/cddl/dev/systrace/systrace.c
+++ b/sys/cddl/dev/systrace/systrace.c
@@ -77,7 +77,6 @@ extern struct sysent linux_sysent[];
*/
#include <sys/syscall.h>
#include <kern/systrace_args.c>
-extern const char *syscallnames[];
#define DEVNAME "dtrace/systrace"
#define PROVNAME "syscall"
#define MAXSYSCALL SYS_MAXSYSCALL
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
index 79448a52507f..d7ac5d0379bc 100644
--- a/sys/compat/ia32/ia32_sysvec.c
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -93,6 +93,8 @@ CTASSERT(sizeof(struct ia32_ucontext4) == 324);
CTASSERT(sizeof(struct ia32_sigframe4) == 408);
#endif
+extern const char *freebsd32_syscallnames[];
+
static void ia32_fixlimit(struct rlimit *rl, int which);
SYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode");
@@ -135,7 +137,10 @@ struct sysentvec ia32_freebsd_sysvec = {
.sv_setregs = ia32_setregs,
.sv_fixlimit = ia32_fixlimit,
.sv_maxssiz = &ia32_maxssiz,
- .sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32
+ .sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32,
+ .sv_set_syscall_retval = ia32_set_syscall_retval,
+ .sv_fetch_syscall_args = ia32_fetch_syscall_args,
+ .sv_syscallnames = freebsd32_syscallnames,
};
diff --git a/sys/compat/ia32/ia32_util.h b/sys/compat/ia32/ia32_util.h
index a2b88cb4272e..d91bfde618e3 100644
--- a/sys/compat/ia32/ia32_util.h
+++ b/sys/compat/ia32/ia32_util.h
@@ -47,3 +47,7 @@
#define IA32_MAXDSIZ (512*1024*1024) /* 512MB */
#define IA32_MAXSSIZ (64*1024*1024) /* 64MB */
#define IA32_MAXVMEM 0 /* Unlimited */
+
+struct syscall_args;
+int ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa);
+void ia32_set_syscall_retval(struct thread *, int);
diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c
index 54406f54660f..e15232b5e3c4 100644
--- a/sys/compat/svr4/svr4_sysvec.c
+++ b/sys/compat/svr4/svr4_sysvec.c
@@ -191,7 +191,10 @@ struct sysentvec svr4_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_UNDEF | SV_IA32 | SV_ILP32
+ .sv_flags = SV_ABI_UNDEF | SV_IA32 | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = NULL,
};
const char svr4_emul_path[] = "/compat/svr4";
diff --git a/sys/conf/files b/sys/conf/files
index aeb68bca5279..23fab8cb7391 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2166,7 +2166,7 @@ kern/sys_generic.c standard
kern/sys_pipe.c standard
kern/sys_process.c standard
kern/sys_socket.c standard
-kern/syscalls.c optional witness | invariants | kdtrace_hooks
+kern/syscalls.c standard
kern/sysv_ipc.c standard
kern/sysv_msg.c optional sysvmsg
kern/sysv_sem.c optional sysvsem
diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
index 408d6ad4a769..df3f48fc287b 100644
--- a/sys/i386/i386/elf_machdep.c
+++ b/sys/i386/i386/elf_machdep.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/linker.h>
+#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/syscall.h>
@@ -73,7 +74,10 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32
+ .sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = syscallnames,
};
static Elf32_Brandinfo freebsd_brand_info = {
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index a11daa6ef7e8..644bb47ba561 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -184,8 +184,6 @@ static int prot_fault_translation = 0;
SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
&prot_fault_translation, 0, "Select signal to deliver on protection fault");
-extern char *syscallnames[];
-
/*
* Exception, fault, and trap interface to the FreeBSD kernel.
* This common code is called from assembly language IDT gate entry
@@ -973,16 +971,8 @@ dblfault_handler()
panic("double fault");
}
-struct syscall_args {
- u_int code;
- struct sysent *callp;
- int args[8];
- register_t *argp;
- int narg;
-};
-
-static int
-fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+int
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
struct proc *p;
struct trapframe *frame;
@@ -995,27 +985,22 @@ fetch_syscall_args(struct thread *td, struct syscall_args *sa)
params = (caddr_t)frame->tf_esp + sizeof(int);
sa->code = frame->tf_eax;
- if (p->p_sysent->sv_prepsyscall) {
- (*p->p_sysent->sv_prepsyscall)(frame, sa->args, &sa->code,
- &params);
- } else {
+ /*
+ * Need to check if this is a 32 bit or 64 bit syscall.
+ */
+ if (sa->code == SYS_syscall) {
/*
- * Need to check if this is a 32 bit or 64 bit syscall.
+ * Code is first argument, followed by actual args.
*/
- if (sa->code == SYS_syscall) {
- /*
- * Code is first argument, followed by actual args.
- */
- sa->code = fuword(params);
- params += sizeof(int);
- } else if (sa->code == SYS___syscall) {
- /*
- * Like syscall, but code is a quad, so as to maintain
- * quad alignment for the rest of the arguments.
- */
- sa->code = fuword(params);
- params += sizeof(quad_t);
- }
+ sa->code = fuword(params);
+ params += sizeof(int);
+ } else if (sa->code == SYS___syscall) {
+ /*
+ * Like syscall, but code is a quad, so as to maintain
+ * quad alignment for the rest of the arguments.
+ */
+ sa->code = fuword(params);
+ params += sizeof(quad_t);
}
if (p->p_sysent->sv_mask)
@@ -1031,11 +1016,12 @@ fetch_syscall_args(struct thread *td, struct syscall_args *sa)
(u_int)(sa->narg * sizeof(int)));
else
error = 0;
+
+ if (error == 0) {
+ td->td_retval[0] = 0;
+ td->td_retval[1] = frame->tf_edx;
+ }
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(sa->code, sa->narg, sa->args);
-#endif
return (error);
}
@@ -1048,87 +1034,23 @@ void
syscall(struct trapframe *frame)
{
struct thread *td;
- struct proc *p;
struct syscall_args sa;
register_t orig_tf_eflags;
int error;
ksiginfo_t ksi;
- PCPU_INC(cnt.v_syscall);
- td = curthread;
- p = td->td_proc;
- td->td_syscalls++;
-
#ifdef DIAGNOSTIC
if (ISPL(frame->tf_cs) != SEL_UPL) {
panic("syscall");
/* NOT REACHED */
}
#endif
-
- td->td_pticks = 0;
- td->td_frame = frame;
- if (td->td_ucred != p->p_ucred)
- cred_update_thread(td);
orig_tf_eflags = frame->tf_eflags;
- if (p->p_flag & P_TRACED) {
- PROC_LOCK(p);
- td->td_dbgflags &= ~TDB_USERWR;
- PROC_UNLOCK(p);
- }
- error = fetch_syscall_args(td, &sa);
- CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, sa.code);
-
- if (error == 0) {
- td->td_retval[0] = 0;
- td->td_retval[1] = frame->tf_edx;
-
- STOPEVENT(p, S_SCE, sa.narg);
- PTRACESTOP_SC(p, td, S_PT_SCE);
- if (td->td_dbgflags & TDB_USERWR) {
- /*
- * Reread syscall number and arguments if
- * debugger modified registers or memory.
- */
- error = fetch_syscall_args(td, &sa);
- if (error != 0)
- goto retval;
- td->td_retval[1] = frame->tf_edx;
- }
-
-#ifdef KDTRACE_HOOKS
- /*
- * If the systrace module has registered it's probe
- * callback and if there is a probe active for the
- * syscall 'entry', process the probe.
- */
- if (systrace_probe_func != NULL && sa.callp->sy_entry != 0)
- (*systrace_probe_func)(sa.callp->sy_entry, sa.code,
- sa.callp, sa.args);
-#endif
-
- AUDIT_SYSCALL_ENTER(sa.code, td);
- error = (*sa.callp->sy_call)(td, sa.args);
- AUDIT_SYSCALL_EXIT(error, td);
+ td = curthread;
+ td->td_frame = frame;
- /* Save the latest error return value. */
- td->td_errno = error;
-
-#ifdef KDTRACE_HOOKS
- /*
- * If the systrace module has registered it's probe
- * callback and if there is a probe active for the
- * syscall 'return', process the probe.
- */
- if (systrace_probe_func != NULL && sa.callp->sy_return != 0)
- (*systrace_probe_func)(sa.callp->sy_return, sa.code,
- sa.callp, sa.args);
-#endif
- }
- retval:
- cpu_set_syscall_retval(td, error);
+ error = syscallenter(td, &sa);
/*
* Traced syscall.
@@ -1142,41 +1064,5 @@ syscall(struct trapframe *frame)
trapsignal(td, &ksi);
}
- /*
- * Check for misbehavior.
- */
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- syscallnames[sa.code] : "???");
- KASSERT(td->td_critnest == 0,
- ("System call %s returning in a critical section",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- syscallnames[sa.code] : "???"));
- KASSERT(td->td_locks == 0,
- ("System call %s returning with %d locks held",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- syscallnames[sa.code] : "???", td->td_locks));
-
- /*
- * Handle reschedule and other end-of-syscall issues
- */
- userret(td, frame);
-
- CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, sa.code);
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(sa.code, error, td->td_retval[0]);
-#endif
-
- /*
- * This works because errno is findable through the
- * register set. If we ever support an emulation where this
- * is not the case, this code will need to be revisited.
- */
- STOPEVENT(p, S_SCX, sa.code);
-
- PTRACESTOP_SC(p, td, S_PT_SCX);
+ syscallret(td, error, &sa);
}
-
diff --git a/sys/i386/ibcs2/ibcs2_sysvec.c b/sys/i386/ibcs2/ibcs2_sysvec.c
index 9112ed77f0d1..71d48a3dbc02 100644
--- a/sys/i386/ibcs2/ibcs2_sysvec.c
+++ b/sys/i386/ibcs2/ibcs2_sysvec.c
@@ -86,7 +86,10 @@ struct sysentvec ibcs2_svr3_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_UNDEF | SV_IA32 | SV_ILP32
+ .sv_flags = SV_ABI_UNDEF | SV_IA32 | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = NULL,
};
static int
diff --git a/sys/i386/include/proc.h b/sys/i386/include/proc.h
index 86be8c81721c..0d922520eab9 100644
--- a/sys/i386/include/proc.h
+++ b/sys/i386/include/proc.h
@@ -77,6 +77,14 @@ void user_ldt_deref(struct proc_ldt *pldt);
extern struct mtx dt_lock;
+struct syscall_args {
+ u_int code;
+ struct sysent *callp;
+ register_t args[8];
+ int narg;
+};
+#define HAVE_SYSCALL_ARGS_DEF 1
+
#endif /* _KERNEL */
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 3f0c6f4100e6..364cc0cdcd8d 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -102,8 +102,6 @@ static int linux_fixup(register_t **stack_base,
struct image_params *iparams);
static int elf_linux_fixup(register_t **stack_base,
struct image_params *iparams);
-static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code,
- caddr_t *params);
static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
static void exec_linux_setregs(struct thread *td,
struct image_params *imgp, u_long stack);
@@ -864,19 +862,33 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
return (EJUSTRETURN);
}
-/*
- * MPSAFE
- */
-static void
-linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params)
+static int
+linux_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
- args[0] = tf->tf_ebx;
- args[1] = tf->tf_ecx;
- args[2] = tf->tf_edx;
- args[3] = tf->tf_esi;
- args[4] = tf->tf_edi;
- args[5] = tf->tf_ebp; /* Unconfirmed */
- *params = NULL; /* no copyin */
+ struct proc *p;
+ struct trapframe *frame;
+
+ p = td->td_proc;
+ frame = td->td_frame;
+
+ sa->code = frame->tf_eax;
+ sa->args[0] = frame->tf_ebx;
+ sa->args[1] = frame->tf_ecx;
+ sa->args[2] = frame->tf_edx;
+ sa->args[3] = frame->tf_esi;
+ sa->args[4] = frame->tf_edi;
+ sa->args[5] = frame->tf_ebp; /* Unconfirmed */
+
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
+ else
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+ sa->narg = sa->callp->sy_narg;
+
+ td->td_retval[0] = 0;
+ td->td_retval[1] = frame->tf_edx;
+
+ return (0);
}
/*
@@ -972,7 +984,7 @@ struct sysentvec linux_sysvec = {
.sv_sendsig = linux_sendsig,
.sv_sigcode = linux_sigcode,
.sv_szsigcode = &linux_szsigcode,
- .sv_prepsyscall = linux_prepsyscall,
+ .sv_prepsyscall = NULL,
.sv_name = "Linux a.out",
.sv_coredump = NULL,
.sv_imgact_try = exec_linux_imgact_try,
@@ -987,7 +999,10 @@ struct sysentvec linux_sysvec = {
.sv_setregs = exec_linux_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_LINUX | SV_AOUT | SV_IA32 | SV_ILP32
+ .sv_flags = SV_ABI_LINUX | SV_AOUT | SV_IA32 | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = linux_fetch_syscall_args,
+ .sv_syscallnames = NULL,
};
struct sysentvec elf_linux_sysvec = {
@@ -1003,7 +1018,7 @@ struct sysentvec elf_linux_sysvec = {
.sv_sendsig = linux_sendsig,
.sv_sigcode = linux_sigcode,
.sv_szsigcode = &linux_szsigcode,
- .sv_prepsyscall = linux_prepsyscall,
+ .sv_prepsyscall = NULL,
.sv_name = "Linux ELF",
.sv_coredump = elf32_coredump,
.sv_imgact_try = exec_linux_imgact_try,
@@ -1018,7 +1033,10 @@ struct sysentvec elf_linux_sysvec = {
.sv_setregs = exec_linux_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32
+ .sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = linux_fetch_syscall_args,
+ .sv_syscallnames = NULL,
};
static char GNU_ABI_VENDOR[] = "GNU";
diff --git a/sys/ia64/ia32/ia32_trap.c b/sys/ia64/ia32/ia32_trap.c
index ba2bceb1d462..9c7f08d713aa 100644
--- a/sys/ia64/ia32/ia32_trap.c
+++ b/sys/ia64/ia32/ia32_trap.c
@@ -48,86 +48,15 @@ __FBSDID("$FreeBSD$");
#include <security/audit/audit.h>
-extern char *syscallnames[];
+#include <compat/ia32/ia32_util.h>
-static void
-ia32_syscall(struct trapframe *tf)
+void
+ia32_set_syscall_retval(struct thread *td, int error)
{
- uint64_t args64[8];
- uint32_t args[8];
- struct thread *td;
struct proc *p;
- struct sysent *callp;
- caddr_t params;
- register_t eflags;
- u_int code;
- int error, i, narg;
- ksiginfo_t ksi;
-
- PCPU_INC(cnt.v_syscall);
-
- td = curthread;
- params = (caddr_t)(tf->tf_special.sp & ((1L<<32)-1)) +
- sizeof(uint32_t);
- code = tf->tf_scratch.gr8; /* eax */
- eflags = ia64_get_eflag();
- p = td->td_proc;
-
- if (p->p_sysent->sv_prepsyscall == NULL) {
- if (code == SYS_syscall) {
- /* Code is first argument, followed by actual args. */
- code = fuword32(params);
- params += sizeof(int);
- } else if (code == SYS___syscall) {
- /*
- * Like syscall, but code is a quad, so as to maintain
- * quad alignment for the rest of the arguments. We
- * use a 32-bit fetch in case params is not aligned.
- */
- code = fuword32(params);
- params += sizeof(quad_t);
- }
- } else
- (*p->p_sysent->sv_prepsyscall)(tf, args, &code, &params);
-
- if (p->p_sysent->sv_mask)
- code &= p->p_sysent->sv_mask;
-
- if (code >= p->p_sysent->sv_size)
- callp = &p->p_sysent->sv_table[0];
- else
- callp = &p->p_sysent->sv_table[code];
+ struct trapframe *tf;
- narg = callp->sy_narg;
-
- /* copyin and the ktrsyscall()/ktrsysret() code is MP-aware */
- if (params != NULL && narg != 0)
- error = copyin(params, (caddr_t)args, narg * sizeof(int));
- else
- error = 0;
-
- for (i = 0; i < narg; i++)
- args64[i] = args[i];
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(code, narg, args64);
-#endif
- CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_proc->p_comm, code);
-
- if (error == 0) {
- td->td_retval[0] = 0;
- td->td_retval[1] = tf->tf_scratch.gr10; /* edx */
-
- STOPEVENT(p, S_SCE, narg);
-
- PTRACESTOP_SC(p, td, S_PT_SCE);
-
- AUDIT_SYSCALL_ENTER(code, td);
- error = (*callp->sy_call)(td, args64);
- AUDIT_SYSCALL_EXIT(error, td);
- }
+ tf = td->td_frame;
switch (error) {
case 0:
@@ -148,6 +77,7 @@ ia32_syscall(struct trapframe *tf)
break;
default:
+ p = td->td_proc;
if (p->p_sysent->sv_errsize) {
if (error >= p->p_sysent->sv_errsize)
error = -1; /* XXX */
@@ -158,6 +88,74 @@ ia32_syscall(struct trapframe *tf)
ia64_set_eflag(ia64_get_eflag() | PSL_C);
break;
}
+}
+
+int
+ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+{
+ struct trapframe *tf;
+ struct proc *p;
+ uint32_t args[8];
+ caddr_t params;
+ int error, i;
+
+ tf = td->td_frame;
+ p = td->td_proc;
+
+ params = (caddr_t)(tf->tf_special.sp & ((1L<<32)-1)) +
+ sizeof(uint32_t);
+ sa->code = tf->tf_scratch.gr8; /* eax */
+
+ if (sa->code == SYS_syscall) {
+ /* Code is first argument, followed by actual args. */
+ sa->code = fuword32(params);
+ params += sizeof(int);
+ } else if (sa->code == SYS___syscall) {
+ /*
+ * Like syscall, but code is a quad, so as to maintain
+ * quad alignment for the rest of the arguments. We
+ * use a 32-bit fetch in case params is not aligned.
+ */
+ sa->code = fuword32(params);
+ params += sizeof(quad_t);
+ }
+
+ if (p->p_sysent->sv_mask)
+ sa->code &= p->p_sysent->sv_mask;
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
+ else
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+ sa->narg = sa->callp->sy_narg;
+
+ if (params != NULL && sa->narg != 0)
+ error = copyin(params, (caddr_t)args, sa->narg * sizeof(int));
+ else
+ error = 0;
+
+ if (error == 0) {
+ for (i = 0; i < sa->narg; i++)
+ sa->args[i] = args[i];
+ td->td_retval[0] = 0;
+ td->td_retval[1] = tf->tf_scratch.gr10; /* edx */
+ }
+
+ return (error);
+}
+
+static void
+ia32_syscall(struct trapframe *tf)
+{
+ struct thread *td;
+ struct syscall_args sa;
+ register_t eflags;
+ int error;
+ ksiginfo_t ksi;
+
+ td = curthread;
+ eflags = ia64_get_eflag();
+
+ error = syscallenter(td, &sa);
/*
* Traced syscall.
@@ -171,37 +169,7 @@ ia32_syscall(struct trapframe *tf)
trapsignal(td, &ksi);
}
- /*
- * Check for misbehavior.
- */
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
- KASSERT(td->td_critnest == 0,
- ("System call %s returning in a critical section",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
- KASSERT(td->td_locks == 0,
- ("System call %s returning with %d locks held",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
- td->td_locks));
-
- /*
- * End of syscall tracing.
- */
- CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_proc->p_comm, code);
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(code, error, td->td_retval[0]);
-#endif
-
- /*
- * This works because errno is findable through the
- * register set. If we ever support an emulation where this
- * is not the case, this code will need to be revisited.
- */
- STOPEVENT(p, S_SCX, code);
-
- PTRACESTOP_SC(p, td, S_PT_SCX);
+ syscallret(td, error, &sa);
}
/*
diff --git a/sys/ia64/ia64/elf_machdep.c b/sys/ia64/ia64/elf_machdep.c
index 836016563bc9..87fcd4f1b135 100644
--- a/sys/ia64/ia64/elf_machdep.c
+++ b/sys/ia64/ia64/elf_machdep.c
@@ -81,7 +81,10 @@ struct sysentvec elf64_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_FREEBSD | SV_LP64
+ .sv_flags = SV_ABI_FREEBSD | SV_LP64,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = syscallnames,
};
static Elf64_Brandinfo freebsd_brand_info = {
diff --git a/sys/ia64/ia64/trap.c b/sys/ia64/ia64/trap.c
index f539097c2654..6ce56b748489 100644
--- a/sys/ia64/ia64/trap.c
+++ b/sys/ia64/ia64/trap.c
@@ -87,8 +87,6 @@ static void break_syscall(struct trapframe *tf);
*/
extern struct fpswa_iface *fpswa_iface;
-extern char *syscallnames[];
-
static const char *ia64_vector_names[] = {
"VHPT Translation", /* 0 */
"Instruction TLB", /* 1 */
@@ -899,117 +897,68 @@ break_syscall(struct trapframe *tf)
do_ast(tf);
}
-/*
- * Process a system call.
- *
- * See syscall.s for details as to how we get here. In order to support
- * the ERESTART case, we return the error to our caller. They deal with
- * the hairy details.
- */
int
-syscall(struct trapframe *tf)
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
- struct sysent *callp;
struct proc *p;
- struct thread *td;
- uint64_t *args;
- int code, error;
-
- ia64_set_fpsr(IA64_FPSR_DEFAULT);
-
- code = tf->tf_scratch.gr15;
- args = &tf->tf_scratch.gr16;
-
- PCPU_INC(cnt.v_syscall);
+ struct trapframe *tf;
+ register_t *args;
- td = curthread;
- td->td_frame = tf;
p = td->td_proc;
+ tf = td->td_frame;
- td->td_pticks = 0;
- if (td->td_ucred != p->p_ucred)
- cred_update_thread(td);
+ sa->code = tf->tf_scratch.gr15;
+ args = &tf->tf_scratch.gr16;
- if (p->p_sysent->sv_prepsyscall) {
- /* (*p->p_sysent->sv_prepsyscall)(tf, args, &code, &params); */
- panic("prepsyscall");
- } else {
+ /*
+ * syscall() and __syscall() are handled the same on
+ * the ia64, as everything is 64-bit aligned, anyway.
+ */
+ if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
/*
- * syscall() and __syscall() are handled the same on
- * the ia64, as everything is 64-bit aligned, anyway.
+ * Code is first argument, followed by actual args.
*/
- if (code == SYS_syscall || code == SYS___syscall) {
- /*
- * Code is first argument, followed by actual args.
- */
- code = args[0];
- args++;
- }
+ sa->code = args[0];
+ args++;
}
if (p->p_sysent->sv_mask)
- code &= p->p_sysent->sv_mask;
-
- if (code >= p->p_sysent->sv_size)
- callp = &p->p_sysent->sv_table[0];
- else
- callp = &p->p_sysent->sv_table[code];
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(code, callp->sy_narg, args);
-#endif
- CTR4(KTR_SYSC, "syscall enter thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, code);
+ sa->code &= p->p_sysent->sv_mask;
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
+ else
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+ sa->narg = sa->callp->sy_narg;
+ bcopy(args, sa->args, sa->narg * sizeof(sa->args[0]));
td->td_retval[0] = 0;
td->td_retval[1] = 0;
- tf->tf_scratch.gr10 = EJUSTRETURN;
- STOPEVENT(p, S_SCE, callp->sy_narg);
-
- PTRACESTOP_SC(p, td, S_PT_SCE);
-
- AUDIT_SYSCALL_ENTER(code, td);
- error = (*callp->sy_call)(td, args);
- AUDIT_SYSCALL_EXIT(error, td);
-
- cpu_set_syscall_retval(td, error);
- td->td_syscalls++;
-
- /*
- * Check for misbehavior.
- */
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
- KASSERT(td->td_critnest == 0,
- ("System call %s returning in a critical section",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
- KASSERT(td->td_locks == 0,
- ("System call %s returning with %d locks held",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
- td->td_locks));
+ return (0);
+}
- /*
- * Handle reschedule and other end-of-syscall issues
- */
- userret(td, tf);
+/*
+ * Process a system call.
+ *
+ * See syscall.s for details as to how we get here. In order to support
+ * the ERESTART case, we return the error to our caller. They deal with
+ * the hairy details.
+ */
+int
+syscall(struct trapframe *tf)
+{
+ struct syscall_args sa;
+ struct thread *td;
+ int error;
- CTR4(KTR_SYSC, "syscall exit thread %p pid %d proc %s code %d", td,
- td->td_proc->p_pid, td->td_name, code);
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(code, error, td->td_retval[0]);
-#endif
+ td = curthread;
+ td->td_frame = tf;
- /*
- * This works because errno is findable through the
- * register set. If we ever support an emulation where this
- * is not the case, this code will need to be revisited.
- */
- STOPEVENT(p, S_SCX, code);
+ ia64_set_fpsr(IA64_FPSR_DEFAULT);
+ tf->tf_scratch.gr10 = EJUSTRETURN;
- PTRACESTOP_SC(p, td, S_PT_SCX);
+ error = syscallenter(td, &sa);
+ syscallret(td, error, &sa);
return (error);
}
diff --git a/sys/ia64/include/proc.h b/sys/ia64/include/proc.h
index e9f337cbb485..574be36cc1b3 100644
--- a/sys/ia64/include/proc.h
+++ b/sys/ia64/include/proc.h
@@ -41,4 +41,14 @@ struct mdproc {
#define KINFO_PROC_SIZE 1088
#define KINFO_PROC32_SIZE 768
+#ifdef _KERNEL
+struct syscall_args {
+ u_int code;
+ struct sysent *callp;
+ register_t args[8];
+ int narg;
+};
+#define HAVE_SYSCALL_ARGS_DEF 1
+#endif
+
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
index 6c2f62752713..671013508831 100644
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -89,6 +89,10 @@ struct sysentvec aout_sysvec = {
#else
#error Choose SV_XXX flags for the platform
#endif
+ ,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = syscallnames,
};
static int
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index e9090fb077ba..d608e25e172e 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -334,6 +334,21 @@ set_boot_verbose(void *data __unused)
}
SYSINIT(boot_verbose, SI_SUB_TUNABLES, SI_ORDER_ANY, set_boot_verbose, NULL);
+static int
+null_fetch_syscall_args(struct thread *td __unused,
+ struct syscall_args *sa __unused)
+{
+
+ panic("null_fetch_syscall_args");
+}
+
+static void
+null_set_syscall_retval(struct thread *td __unused, int error __unused)
+{
+
+ panic("null_set_syscall_retval");
+}
+
struct sysentvec null_sysvec = {
.sv_size = 0,
.sv_table = NULL,
@@ -361,7 +376,11 @@ struct sysentvec null_sysvec = {
.sv_copyout_strings = NULL,
.sv_setregs = NULL,
.sv_fixlimit = NULL,
- .sv_maxssiz = NULL
+ .sv_maxssiz = NULL,
+ .sv_flags = 0,
+ .sv_set_syscall_retval = null_set_syscall_retval,
+ .sv_fetch_syscall_args = null_fetch_syscall_args,
+ .sv_syscallnames = NULL,
};
/*
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index fc87d6394040..149e6df3be65 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -871,6 +871,10 @@ exec_fail_dealloc:
free(imgp->freepath, M_TEMP);
if (error == 0) {
+ PROC_LOCK(p);
+ td->td_dbgflags |= TDB_EXEC;
+ PROC_UNLOCK(p);
+
/*
* Stop the process here if its stop event mask has
* the S_EXEC bit set.
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 789bb6125291..d52cedb35e1d 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1483,7 +1483,7 @@ kern_sigsuspend(struct thread *td, sigset_t mask)
* thread. But sigsuspend should return only on signal
* delivery.
*/
- cpu_set_syscall_retval(td, EINTR);
+ (p->p_sysent->sv_set_syscall_retval)(td, EINTR);
for (has_sig = 0; !has_sig;) {
while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "pause",
0) == 0)
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 4d20ebdc1ce1..4cc56cc73da7 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -58,15 +58,20 @@ __FBSDID("$FreeBSD$");
#include <sys/pmckern.h>
#include <sys/proc.h>
#include <sys/ktr.h>
+#include <sys/pioctl.h>
+#include <sys/ptrace.h>
#include <sys/resourcevar.h>
#include <sys/sched.h>
#include <sys/signalvar.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
#include <sys/systm.h>
#include <sys/vmmeter.h>
#ifdef KTRACE
#include <sys/uio.h>
#include <sys/ktrace.h>
#endif
+#include <security/audit/audit.h>
#include <machine/cpu.h>
#include <machine/pcb.h>
@@ -253,3 +258,160 @@ ast(struct trapframe *framep)
userret(td, framep);
mtx_assert(&Giant, MA_NOTOWNED);
}
+
+#ifdef HAVE_SYSCALL_ARGS_DEF
+static const char *syscallname(struct proc *p, u_int code) __unused;
+static const char *
+syscallname(struct proc *p, u_int code)
+{
+ static const char unknown[] = "unknown";
+
+ if (p->p_sysent->sv_syscallnames == NULL)
+ return (unknown);
+ return (p->p_sysent->sv_syscallnames[code]);
+}
+
+int
+syscallenter(struct thread *td, struct syscall_args *sa)
+{
+ struct proc *p;
+ int error, traced;
+
+ PCPU_INC(cnt.v_syscall);
+ p = td->td_proc;
+ td->td_syscalls++;
+
+ td->td_pticks = 0;
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
+ if (p->p_flag & P_TRACED) {
+ traced = 1;
+ PROC_LOCK(p);
+ td->td_dbgflags &= ~TDB_USERWR;
+ td->td_dbgflags |= TDB_SCE;
+ PROC_UNLOCK(p);
+ } else
+ traced = 0;
+ error = (p->p_sysent->sv_fetch_syscall_args)(td, sa);
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSCALL))
+ ktrsyscall(sa->code, sa->narg, sa->args);
+#endif
+
+ CTR6(KTR_SYSC,
+"syscall: td=%p pid %d %s (%#lx, %#lx, %#lx)",
+ td, td->td_proc->p_pid, syscallname(p, sa->code),
+ sa->args[0], sa->args[1], sa->args[2]);
+
+ if (error == 0) {
+ STOPEVENT(p, S_SCE, sa->narg);
+ PTRACESTOP_SC(p, td, S_PT_SCE);
+ if (td->td_dbgflags & TDB_USERWR) {
+ /*
+ * Reread syscall number and arguments if
+ * debugger modified registers or memory.
+ */
+ error = (p->p_sysent->sv_fetch_syscall_args)(td, sa);
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSCALL))
+ ktrsyscall(sa->code, sa->narg, sa->args);
+#endif
+ if (error != 0)
+ goto retval;
+ }
+
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the systrace module has registered it's probe
+ * callback and if there is a probe active for the
+ * syscall 'entry', process the probe.
+ */
+ if (systrace_probe_func != NULL && sa->callp->sy_entry != 0)
+ (*systrace_probe_func)(sa->callp->sy_entry, sa->code,
+ sa->callp, sa->args);
+#endif
+
+ AUDIT_SYSCALL_ENTER(sa->code, td);
+ error = (sa->callp->sy_call)(td, sa->args);
+ AUDIT_SYSCALL_EXIT(error, td);
+
+ /* Save the latest error return value. */
+ td->td_errno = error;
+
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the systrace module has registered it's probe
+ * callback and if there is a probe active for the
+ * syscall 'return', process the probe.
+ */
+ if (systrace_probe_func != NULL && sa->callp->sy_return != 0)
+ (*systrace_probe_func)(sa->callp->sy_return, sa->code,
+ sa->callp, sa->args);
+#endif
+ CTR4(KTR_SYSC, "syscall: p=%p error=%d return %#lx %#lx",
+ p, error, td->td_retval[0], td->td_retval[1]);
+ }
+ retval:
+ if (traced) {
+ PROC_LOCK(p);
+ td->td_dbgflags &= ~TDB_SCE;
+ PROC_UNLOCK(p);
+ }
+ (p->p_sysent->sv_set_syscall_retval)(td, error);
+ return (error);
+}
+
+void
+syscallret(struct thread *td, int error, struct syscall_args *sa __unused)
+{
+ struct proc *p;
+ int traced;
+
+ p = td->td_proc;
+
+ /*
+ * Check for misbehavior.
+ */
+ WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
+ syscallname(p, sa->code));
+ KASSERT(td->td_critnest == 0,
+ ("System call %s returning in a critical section",
+ syscallname(p, sa->code)));
+ KASSERT(td->td_locks == 0,
+ ("System call %s returning with %d locks held",
+ syscallname(p, sa->code), td->td_locks));
+
+ /*
+ * Handle reschedule and other end-of-syscall issues
+ */
+ userret(td, td->td_frame);
+
+ CTR4(KTR_SYSC, "syscall %s exit thread %p pid %d proc %s",
+ syscallname(p, sa->code), td, td->td_proc->p_pid, td->td_name);
+
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSRET))
+ ktrsysret(sa->code, error, td->td_retval[0]);
+#endif
+
+ if (p->p_flag & P_TRACED) {
+ traced = 1;
+ PROC_LOCK(p);
+ td->td_dbgflags |= TDB_SCX;
+ PROC_UNLOCK(p);
+ } else
+ traced = 0;
+ /*
+ * This works because errno is findable through the
+ * register set. If we ever support an emulation where this
+ * is not the case, this code will need to be revisited.
+ */
+ STOPEVENT(p, S_SCX, sa->code);
+ PTRACESTOP_SC(p, td, S_PT_SCX);
+ if (traced || (td->td_dbgflags & TDB_EXEC) != 0) {
+ PROC_LOCK(p);
+ td->td_dbgflags &= ~(TDB_SCX | TDB_EXEC);
+ PROC_UNLOCK(p);
+ }
+}
+#endif /* HAVE_SYSCALL_ARGS_DEF */
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index d8cc4f01d2d1..6decc0296785 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -1105,9 +1105,13 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
pl->pl_lwpid = td2->td_tid;
if (td2->td_dbgflags & TDB_XSIG)
pl->pl_event = PL_EVENT_SIGNAL;
- else
- pl->pl_event = 0;
pl->pl_flags = 0;
+ if (td2->td_dbgflags & TDB_SCE)
+ pl->pl_flags |= PL_FLAG_SCE;
+ else if (td2->td_dbgflags & TDB_SCX)
+ pl->pl_flags |= PL_FLAG_SCX;
+ if (td2->td_dbgflags & TDB_EXEC)
+ pl->pl_flags |= PL_FLAG_EXEC;
pl->pl_sigmask = td2->td_sigmask;
pl->pl_siglist = td2->td_siglist;
break;
diff --git a/sys/mips/mips/elf64_machdep.c b/sys/mips/mips/elf64_machdep.c
index d63fdbccb435..41b669196d1f 100644
--- a/sys/mips/mips/elf64_machdep.c
+++ b/sys/mips/mips/elf64_machdep.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
+#include <sys/proc.h>
#include <sys/syscall.h>
#include <sys/signalvar.h>
#include <sys/vnode.h>
@@ -77,7 +78,10 @@ struct sysentvec elf64_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_FREEBSD | SV_LP64
+ .sv_flags = SV_ABI_FREEBSD | SV_LP64,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = NULL, /* XXXKIB */
+ .sv_syscallnames = NULL,
};
static Elf64_Brandinfo freebsd_brand_gnutools_info64 = {
diff --git a/sys/mips/mips/elf_machdep.c b/sys/mips/mips/elf_machdep.c
index a7bd755fb8e4..fc1bc1569388 100644
--- a/sys/mips/mips/elf_machdep.c
+++ b/sys/mips/mips/elf_machdep.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
+#include <sys/proc.h>
#include <sys/syscall.h>
#include <sys/signalvar.h>
#include <sys/vnode.h>
@@ -77,7 +78,10 @@ struct sysentvec elf64_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_FREEBSD | SV_LP64
+ .sv_flags = SV_ABI_FREEBSD | SV_LP64,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = NULL, /* XXXKIB */
+ .sv_syscallnames = syscallnames,
};
static Elf64_Brandinfo freebsd_brand_info = {
@@ -129,7 +133,10 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_FREEBSD | SV_ILP32
+ .sv_flags = SV_ABI_FREEBSD | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = NULL, /* XXXKIB */
+ .sv_syscallnames = syscallnames,
};
static Elf32_Brandinfo freebsd_brand_info = {
diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c
index 17a6be5e7fd0..831e0182acba 100644
--- a/sys/mips/mips/trap.c
+++ b/sys/mips/mips/trap.c
@@ -261,7 +261,6 @@ SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
static int emulate_unaligned_access(struct trapframe *frame);
-extern char *syscallnames[];
extern void fswintrberr(void); /* XXX */
/*
diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c
index 35f41473e277..74e0f269c994 100644
--- a/sys/powerpc/aim/trap.c
+++ b/sys/powerpc/aim/trap.c
@@ -92,8 +92,6 @@ int setfault(faultbuf); /* defined in locore.S */
int badaddr(void *, size_t);
int badaddr_read(void *, size_t, int *);
-extern char *syscallnames[];
-
struct powerpc_exception {
u_int vector;
char *name;
@@ -320,125 +318,76 @@ handle_onfault(struct trapframe *frame)
return (0);
}
-void
-syscall(struct trapframe *frame)
+int
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
- caddr_t params;
- struct sysent *callp;
- struct thread *td;
- struct proc *p;
- int error, n;
- size_t narg;
- register_t args[10];
- u_int code;
+ struct proc *p;
+ struct trapframe *frame;
+ caddr_t params;
+ int error, n;
- td = PCPU_GET(curthread);
p = td->td_proc;
+ frame = td->td_frame;
- PCPU_INC(cnt.v_syscall);
-
- code = frame->fixreg[0];
+ sa->code = frame->fixreg[0];
params = (caddr_t)(frame->fixreg + FIRSTARG);
n = NARGREG;
- if (p->p_sysent->sv_prepsyscall) {
- /*
- * The prep code is MP aware.
- */
- (*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
- } else if (code == SYS_syscall) {
+ if (sa->code == SYS_syscall) {
/*
* code is first argument,
* followed by actual args.
*/
- code = *(u_int *) params;
+ sa->code = *(u_int *) params;
params += sizeof(register_t);
n -= 1;
- } else if (code == SYS___syscall) {
+ } else if (sa->code == SYS___syscall) {
/*
* Like syscall, but code is a quad,
* so as to maintain quad alignment
* for the rest of the args.
*/
params += sizeof(register_t);
- code = *(u_int *) params;
+ sa->code = *(u_int *) params;
params += sizeof(register_t);
n -= 2;
}
if (p->p_sysent->sv_mask)
- code &= p->p_sysent->sv_mask;
-
- if (code >= p->p_sysent->sv_size)
- callp = &p->p_sysent->sv_table[0];
- else
- callp = &p->p_sysent->sv_table[code];
-
- narg = callp->sy_narg;
-
- if (narg > n) {
- bcopy(params, args, n * sizeof(register_t));
- error = copyin(MOREARGS(frame->fixreg[1]), args + n,
- (narg - n) * sizeof(register_t));
- params = (caddr_t)args;
+ sa->code &= p->p_sysent->sv_mask;
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
+ else
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+
+ sa->narg = sa->callp->sy_narg;
+
+ bcopy(params, sa->args, n * sizeof(register_t));
+ if (sa->narg > n) {
+ error = copyin(MOREARGS(frame->fixreg[1]), sa->args + n,
+ (sa->narg - n) * sizeof(register_t));
} else
error = 0;
- CTR5(KTR_SYSC, "syscall: p=%s %s(%x %x %x)", td->td_name,
- syscallnames[code],
- frame->fixreg[FIRSTARG],
- frame->fixreg[FIRSTARG+1],
- frame->fixreg[FIRSTARG+2]);
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(code, narg, (register_t *)params);
-#endif
-
- td->td_syscalls++;
-
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame->fixreg[FIRSTARG + 1];
-
- STOPEVENT(p, S_SCE, narg);
-
- PTRACESTOP_SC(p, td, S_PT_SCE);
-
- AUDIT_SYSCALL_ENTER(code, td);
- error = (*callp->sy_call)(td, params);
- AUDIT_SYSCALL_EXIT(error, td);
-
- CTR3(KTR_SYSC, "syscall: p=%s %s ret=%x", td->td_name,
- syscallnames[code], td->td_retval[0]);
}
+ return (error);
+}
- cpu_set_syscall_retval(td, error);
-
- /*
- * Check for misbehavior.
- */
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
- KASSERT(td->td_critnest == 0,
- ("System call %s returning in a critical section",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
- KASSERT(td->td_locks == 0,
- ("System call %s returning with %d locks held",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
- td->td_locks));
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(code, error, td->td_retval[0]);
-#endif
+void
+syscall(struct trapframe *frame)
+{
+ struct thread *td;
+ struct syscall_args sa;
+ int error;
+
+ td = PCPU_GET(curthread);
+ td->td_frame = frame;
- /*
- * Does the comment in the i386 code about errno apply here?
- */
- STOPEVENT(p, S_SCX, code);
-
- PTRACESTOP_SC(p, td, S_PT_SCX);
+ error = syscallenter(td, &sa);
+ syscallret(td, error, &sa);
}
static int
diff --git a/sys/powerpc/booke/trap.c b/sys/powerpc/booke/trap.c
index db9be64fe35d..93dc597e3e13 100644
--- a/sys/powerpc/booke/trap.c
+++ b/sys/powerpc/booke/trap.c
@@ -101,8 +101,6 @@ int setfault(faultbuf); /* defined in locore.S */
int badaddr(void *, size_t);
int badaddr_read(void *, size_t, int *);
-extern char *syscallnames[];
-
struct powerpc_exception {
u_int vector;
char *name;
@@ -324,125 +322,75 @@ handle_onfault(struct trapframe *frame)
return (0);
}
-void
-syscall(struct trapframe *frame)
+int
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
- caddr_t params;
- struct sysent *callp;
- struct thread *td;
- struct proc *p;
- int error, n;
- size_t narg;
- register_t args[10];
- u_int code;
+ struct proc *p;
+ struct trapframe *frame;
+ caddr_t params;
+ int error, n;
- td = PCPU_GET(curthread);
p = td->td_proc;
+ frame = td->td_frame;
- PCPU_INC(cnt.v_syscall);
-
- code = frame->fixreg[0];
+ sa->code = frame->fixreg[0];
params = (caddr_t)(frame->fixreg + FIRSTARG);
n = NARGREG;
- if (p->p_sysent->sv_prepsyscall) {
- /*
- * The prep code is MP aware.
- */
- (*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
- } else if (code == SYS_syscall) {
+ if (sa->code == SYS_syscall) {
/*
* code is first argument,
* followed by actual args.
*/
- code = *(u_int *) params;
+ sa->code = *(u_int *) params;
params += sizeof(register_t);
n -= 1;
- } else if (code == SYS___syscall) {
+ } else if (sa->code == SYS___syscall) {
/*
* Like syscall, but code is a quad,
* so as to maintain quad alignment
* for the rest of the args.
*/
params += sizeof(register_t);
- code = *(u_int *) params;
+ sa->code = *(u_int *) params;
params += sizeof(register_t);
n -= 2;
}
if (p->p_sysent->sv_mask)
- code &= p->p_sysent->sv_mask;
-
- if (code >= p->p_sysent->sv_size)
- callp = &p->p_sysent->sv_table[0];
+ sa->code &= p->p_sysent->sv_mask;
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
else
- callp = &p->p_sysent->sv_table[code];
-
- narg = callp->sy_narg;
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+ sa->narg = sa->callp->sy_narg;
- if (narg > n) {
- bcopy(params, args, n * sizeof(register_t));
- error = copyin(MOREARGS(frame->fixreg[1]), args + n,
- (narg - n) * sizeof(register_t));
- params = (caddr_t)args;
+ bcopy(params, sa->args, n * sizeof(register_t));
+ if (sa->narg > n) {
+ error = copyin(MOREARGS(frame->fixreg[1]), sa->args + n,
+ (sa->narg - n) * sizeof(register_t));
} else
error = 0;
- CTR5(KTR_SYSC, "syscall: p=%s %s(%x %x %x)", p->p_comm,
- syscallnames[code],
- frame->fixreg[FIRSTARG],
- frame->fixreg[FIRSTARG+1],
- frame->fixreg[FIRSTARG+2]);
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(code, narg, (register_t *)params);
-#endif
-
- td->td_syscalls++;
-
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = frame->fixreg[FIRSTARG + 1];
-
- STOPEVENT(p, S_SCE, narg);
-
- PTRACESTOP_SC(p, td, S_PT_SCE);
-
- AUDIT_SYSCALL_ENTER(code, td);
- error = (*callp->sy_call)(td, params);
- AUDIT_SYSCALL_EXIT(error, td);
-
- CTR3(KTR_SYSC, "syscall: p=%s %s ret=%x", p->p_comm,
- syscallnames[code], td->td_retval[0]);
}
+ return (error);
+}
- cpu_set_syscall_retval(td, error);
-
- /*
- * Check for misbehavior.
- */
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
- KASSERT(td->td_critnest == 0,
- ("System call %s returning in a critical section",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
- KASSERT(td->td_locks == 0,
- ("System call %s returning with %d locks held",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
- td->td_locks));
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(code, error, td->td_retval[0]);
-#endif
+void
+syscall(struct trapframe *frame)
+{
+ struct thread *td;
+ struct syscall_args sa;
+ int error;
- /*
- * Does the comment in the i386 code about errno apply here?
- */
- STOPEVENT(p, S_SCX, code);
+ td = PCPU_GET(curthread);
+ td->td_frame = frame;
- PTRACESTOP_SC(p, td, S_PT_SCX);
+ error = syscallenter(td, &sa);
+ syscallret(td, error, &sa);
}
static int
diff --git a/sys/powerpc/include/proc.h b/sys/powerpc/include/proc.h
index d51116bb0139..f3bb8afc3be3 100644
--- a/sys/powerpc/include/proc.h
+++ b/sys/powerpc/include/proc.h
@@ -48,4 +48,14 @@ struct mdproc {
#define KINFO_PROC_SIZE 768
+#ifdef _KERNEL
+struct syscall_args {
+ u_int code;
+ struct sysent *callp;
+ register_t args[10];
+ int narg;
+};
+#define HAVE_SYSCALL_ARGS_DEF 1
+#endif
+
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/powerpc/powerpc/elf_machdep.c b/sys/powerpc/powerpc/elf_machdep.c
index c370309e2d2f..60fb02faa899 100644
--- a/sys/powerpc/powerpc/elf_machdep.c
+++ b/sys/powerpc/powerpc/elf_machdep.c
@@ -76,7 +76,10 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_FREEBSD | SV_ILP32
+ .sv_flags = SV_ABI_FREEBSD | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = syscallnames,
};
static Elf32_Brandinfo freebsd_brand_info = {
diff --git a/sys/sparc64/include/proc.h b/sys/sparc64/include/proc.h
index 3c236637fb97..dceea17a33e7 100644
--- a/sys/sparc64/include/proc.h
+++ b/sys/sparc64/include/proc.h
@@ -53,4 +53,16 @@ struct mdproc {
#define KINFO_PROC_SIZE 1088
+#ifdef _KERNEL
+
+struct syscall_args {
+ u_int code;
+ struct sysent *callp;
+ register_t args[8];
+ int narg;
+};
+#define HAVE_SYSCALL_ARGS_DEF 1
+
+#endif
+
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/sparc64/sparc64/elf_machdep.c b/sys/sparc64/sparc64/elf_machdep.c
index 2f9ee396e8de..8ddf4763b1c3 100644
--- a/sys/sparc64/sparc64/elf_machdep.c
+++ b/sys/sparc64/sparc64/elf_machdep.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/linker.h>
+#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/syscall.h>
@@ -88,7 +89,10 @@ static struct sysentvec elf64_freebsd_sysvec = {
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_FREEBSD | SV_LP64
+ .sv_flags = SV_ABI_FREEBSD | SV_LP64,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = syscallnames,
};
static Elf64_Brandinfo freebsd_brand_info = {
diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c
index c0772a188697..8ce6970d65d3 100644
--- a/sys/sparc64/sparc64/trap.c
+++ b/sys/sparc64/sparc64/trap.c
@@ -94,18 +94,9 @@ __FBSDID("$FreeBSD$");
#include <machine/tsb.h>
#include <machine/watch.h>
-struct syscall_args {
- u_long code;
- struct sysent *callp;
- register_t args[8];
- register_t *argp;
- int narg;
-};
-
void trap(struct trapframe *tf);
void syscall(struct trapframe *tf);
-static int fetch_syscall_args(struct thread *td, struct syscall_args *sa);
static int trap_cecc(void);
static int trap_pfault(struct thread *td, struct trapframe *tf);
@@ -123,8 +114,6 @@ extern char fas_fault[];
extern char fas_nofault_begin[];
extern char fas_nofault_end[];
-extern char *syscallnames[];
-
const char *const trap_msg[] = {
"reserved",
"instruction access exception",
@@ -579,11 +568,12 @@ trap_pfault(struct thread *td, struct trapframe *tf)
/* Maximum number of arguments that can be passed via the out registers. */
#define REG_MAXARGS 6
-static int
-fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+int
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
struct trapframe *tf;
struct proc *p;
+ register_t *argp;
int reg;
int regcnt;
int error;
@@ -595,19 +585,13 @@ fetch_syscall_args(struct thread *td, struct syscall_args *sa)
sa->code = tf->tf_global[1];
- if (p->p_sysent->sv_prepsyscall) {
-#if 0
- (*p->p_sysent->sv_prepsyscall)(tf, sa->args, &sa->code,
- &params);
-#endif
- } else if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
+ if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
sa->code = tf->tf_out[reg++];
regcnt--;
}
if (p->p_sysent->sv_mask)
sa->code &= p->p_sysent->sv_mask;
-
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
else
@@ -617,21 +601,17 @@ fetch_syscall_args(struct thread *td, struct syscall_args *sa)
KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
("Too many syscall arguments!"));
error = 0;
- sa->argp = sa->args;
+ argp = sa->args;
bcopy(&tf->tf_out[reg], sa->args, sizeof(sa->args[0]) * regcnt);
if (sa->narg > regcnt)
error = copyin((void *)(tf->tf_out[6] + SPOFF +
offsetof(struct frame, fr_pad[6])), &sa->args[regcnt],
(sa->narg - regcnt) * sizeof(sa->args[0]));
+ if (error == 0) {
+ td->td_retval[0] = 0;
+ td->td_retval[1] = 0;
+ }
- /*
- * This may result in two records if debugger modified
- * registers or memory during sleep at stop/ptrace point.
- */
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(sa->code, sa->narg, sa->argp);
-#endif
return (error);
}
@@ -644,29 +624,16 @@ fetch_syscall_args(struct thread *td, struct syscall_args *sa)
void
syscall(struct trapframe *tf)
{
- struct syscall_args sa;
struct thread *td;
- struct proc *p;
+ struct syscall_args sa;
int error;
td = curthread;
+ td->td_frame = tf;
+
KASSERT(td != NULL, ("trap: curthread NULL"));
KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
- PCPU_INC(cnt.v_syscall);
- p = td->td_proc;
- td->td_syscalls++;
-
- td->td_pticks = 0;
- td->td_frame = tf;
- if (td->td_ucred != p->p_ucred)
- cred_update_thread(td);
- if ((p->p_flag & P_TRACED) != 0) {
- PROC_LOCK(p);
- td->td_dbgflags &= ~TDB_USERWR;
- PROC_UNLOCK(p);
- }
-
/*
* For syscalls, we don't want to retry the faulting instruction
* (usually), instead we need to advance one instruction.
@@ -674,68 +641,6 @@ syscall(struct trapframe *tf)
td->td_pcb->pcb_tpc = tf->tf_tpc;
TF_DONE(tf);
- error = fetch_syscall_args(td, &sa);
- CTR5(KTR_SYSC, "syscall: td=%p %s(%#lx, %#lx, %#lx)", td,
- syscallnames[sa.code], sa.argp[0], sa.argp[1], sa.argp[2]);
-
- if (error == 0) {
- td->td_retval[0] = 0;
- td->td_retval[1] = 0;
-
- STOPEVENT(p, S_SCE, sa.narg);
- PTRACESTOP_SC(p, td, S_PT_SCE);
- if ((td->td_dbgflags & TDB_USERWR) != 0) {
- /*
- * Reread syscall number and arguments if
- * debugger modified registers or memory.
- */
- error = fetch_syscall_args(td, &sa);
- if (error != 0)
- goto retval;
- td->td_retval[1] = 0;
- }
-
- AUDIT_SYSCALL_ENTER(sa.code, td);
- error = (*sa.callp->sy_call)(td, sa.argp);
- AUDIT_SYSCALL_EXIT(error, td);
-
- CTR5(KTR_SYSC, "syscall: p=%p error=%d %s return %#lx %#lx",
- p, error, syscallnames[sa.code], td->td_retval[0],
- td->td_retval[1]);
- }
- retval:
- cpu_set_syscall_retval(td, error);
-
- /*
- * Check for misbehavior.
- */
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- syscallnames[sa.code] : "???");
- KASSERT(td->td_critnest == 0,
- ("System call %s returning in a critical section",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- syscallnames[sa.code] : "???"));
- KASSERT(td->td_locks == 0,
- ("System call %s returning with %d locks held",
- (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ?
- syscallnames[sa.code] : "???", td->td_locks));
-
- /*
- * Handle reschedule and other end-of-syscall issues.
- */
- userret(td, tf);
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(sa.code, error, td->td_retval[0]);
-#endif
- /*
- * This works because errno is findable through the
- * register set. If we ever support an emulation where this
- * is not the case, this code will need to be revisited.
- */
- STOPEVENT(p, S_SCX, sa.code);
-
- PTRACESTOP_SC(p, td, S_PT_SCX);
+ error = syscallenter(td, &sa);
+ syscallret(td, error, &sa);
}
diff --git a/sys/sun4v/include/proc.h b/sys/sun4v/include/proc.h
index 3c236637fb97..dceea17a33e7 100644
--- a/sys/sun4v/include/proc.h
+++ b/sys/sun4v/include/proc.h
@@ -53,4 +53,16 @@ struct mdproc {
#define KINFO_PROC_SIZE 1088
+#ifdef _KERNEL
+
+struct syscall_args {
+ u_int code;
+ struct sysent *callp;
+ register_t args[8];
+ int narg;
+};
+#define HAVE_SYSCALL_ARGS_DEF 1
+
+#endif
+
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/sun4v/sun4v/trap.c b/sys/sun4v/sun4v/trap.c
index 702fd5ce28fd..d099351e3e62 100644
--- a/sys/sun4v/sun4v/trap.c
+++ b/sys/sun4v/sun4v/trap.c
@@ -117,8 +117,6 @@ extern char fas_fault[];
extern char fas_nofault_begin[];
extern char fas_nofault_end[];
-extern char *syscallnames[];
-
const char *const trap_msg[] = {
"reserved",
"instruction access exception",
@@ -566,132 +564,79 @@ trap_pfault(struct thread *td, struct trapframe *tf, int64_t type, uint64_t data
/* Maximum number of arguments that can be passed via the out registers. */
#define REG_MAXARGS 6
-/*
- * Syscall handler. The arguments to the syscall are passed in the o registers
- * by the caller, and are saved in the trap frame. The syscall number is passed
- * in %g1 (and also saved in the trap frame).
- */
-void
-syscall(struct trapframe *tf)
+int
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
- struct sysent *callp;
- struct thread *td;
- register_t args[8];
- register_t *argp;
+ struct trapframe *tf;
struct proc *p;
- u_long code;
+ register_t *argp;
int reg;
int regcnt;
- int narg;
int error;
- td = curthread;
- KASSERT(td != NULL, ("trap: curthread NULL"));
- KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
-
p = td->td_proc;
-
- PCPU_INC(cnt.v_syscall);
-
- td->td_pticks = 0;
- td->td_frame = tf;
- if (td->td_ucred != p->p_ucred)
- cred_update_thread(td);
- code = tf->tf_global[1];
-
- /*
- * For syscalls, we don't want to retry the faulting instruction
- * (usually), instead we need to advance one instruction.
- */
- td->td_pcb->pcb_tpc = tf->tf_tpc;
- TF_DONE(tf);
-
+ tf = td->td_frame;
reg = 0;
regcnt = REG_MAXARGS;
- if (p->p_sysent->sv_prepsyscall) {
- /*
- * The prep code is MP aware.
- */
-#if 0
- (*p->p_sysent->sv_prepsyscall)(tf, args, &code, &params);
-#endif
- } else if (code == SYS_syscall || code == SYS___syscall) {
- code = tf->tf_out[reg++];
- regcnt--;
- }
-
- if (p->p_sysent->sv_mask)
- code &= p->p_sysent->sv_mask;
- if (code >= p->p_sysent->sv_size)
- callp = &p->p_sysent->sv_table[0];
- else
- callp = &p->p_sysent->sv_table[code];
+ sa->code = tf->tf_global[1];
- narg = callp->sy_narg;
-
- if (narg <= regcnt) {
- argp = &tf->tf_out[reg];
- error = 0;
- } else {
- KASSERT(narg <= sizeof(args) / sizeof(args[0]),
- ("Too many syscall arguments!"));
- argp = args;
- bcopy(&tf->tf_out[reg], args, sizeof(args[0]) * regcnt);
- error = copyin((void *)(tf->tf_out[6] + SPOFF +
- offsetof(struct frame, fr_pad[6])),
- &args[regcnt], (narg - regcnt) * sizeof(args[0]));
+ if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
+ sa->code = tf->tf_out[reg++];
+ regcnt--;
}
- CTR5(KTR_SYSC, "syscall: td=%p %s(%#lx, %#lx, %#lx)", td,
- syscallnames[code], argp[0], argp[1], argp[2]);
-
- /*
- * Try to run the syscall without the MP lock if the syscall
- * is MP safe.
- */
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(code, narg, argp);
-#endif
+ if (p->p_sysent->sv_mask)
+ sa->code &= p->p_sysent->sv_mask;
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
+ else
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+
+ sa->narg = sa->callp->sy_narg;
+ KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
+ ("Too many syscall arguments!"));
+ error = 0;
+ argp = sa->args;
+ bcopy(&tf->tf_out[reg], sa->args, sizeof(sa->args[0]) * regcnt);
+ if (sa->narg > regcnt)
+ error = copyin((void *)(tf->tf_out[6] + SPOFF +
+ offsetof(struct frame, fr_pad[6])), &sa->args[regcnt],
+ (sa->narg - regcnt) * sizeof(sa->args[0]));
if (error == 0) {
td->td_retval[0] = 0;
td->td_retval[1] = 0;
+ }
- STOPEVENT(p, S_SCE, narg); /* MP aware */
-
- PTRACESTOP_SC(p, td, S_PT_SCE);
-
- AUDIT_SYSCALL_ENTER(code, td);
- error = (*callp->sy_call)(td, argp);
- AUDIT_SYSCALL_EXIT(error, td);
+ return (error);
+}
- CTR5(KTR_SYSC, "syscall: p=%p error=%d %s return %#lx %#lx ", p,
- error, syscallnames[code], td->td_retval[0],
- td->td_retval[1]);
- }
+/*
+ * Syscall handler. The arguments to the syscall are passed in the o registers
+ * by the caller, and are saved in the trap frame. The syscall number is passed
+ * in %g1 (and also saved in the trap frame).
+ */
+void
+syscall(struct trapframe *tf)
+{
+ struct thread *td;
+ struct syscall_args sa;
+ int error;
- cpu_set_syscall_retval(td, error);
+ td = curthread;
+ td->td_frame = tf;
- /*
- * Handle reschedule and other end-of-syscall issues
- */
- userret(td, tf);
+ KASSERT(td != NULL, ("trap: curthread NULL"));
+ KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(code, error, td->td_retval[0]);
-#endif
/*
- * This works because errno is findable through the
- * register set. If we ever support an emulation where this
- * is not the case, this code will need to be revisited.
+ * For syscalls, we don't want to retry the faulting instruction
+ * (usually), instead we need to advance one instruction.
*/
- STOPEVENT(p, S_SCX, code);
-
- PTRACESTOP_SC(p, td, S_PT_SCX);
+ td->td_pcb->pcb_tpc = tf->tf_tpc;
+ TF_DONE(tf);
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
- mtx_assert(&Giant, MA_NOTOWNED);
+ error = syscallenter(td, &sa);
+ syscallret(td, error, &sa);
}
+
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index e32e494f00f0..1195019fc8c4 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -364,6 +364,9 @@ do { \
#define TDB_SUSPEND 0x00000001 /* Thread is suspended by debugger */
#define TDB_XSIG 0x00000002 /* Thread is exchanging signal under trace */
#define TDB_USERWR 0x00000004 /* Debugger modified memory or registers */
+#define TDB_SCE 0x00000008 /* Thread performs syscall enter */
+#define TDB_SCX 0x00000010 /* Thread performs syscall exit */
+#define TDB_EXEC 0x00000020 /* TDB_SCX from exec(2) family */
/*
* "Private" flags kept in td_pflags:
@@ -837,9 +840,14 @@ void cpu_switch(struct thread *, struct thread *, struct mtx *);
void cpu_throw(struct thread *, struct thread *) __dead2;
void unsleep(struct thread *);
void userret(struct thread *, struct trapframe *);
+struct syscall_args;
+int syscallenter(struct thread *, struct syscall_args *);
+void syscallret(struct thread *, int, struct syscall_args *);
void cpu_exit(struct thread *);
void exit1(struct thread *, int) __dead2;
+struct syscall_args;
+int cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa);
void cpu_fork(struct thread *, struct proc *, struct thread *, int);
void cpu_set_fork_handler(struct thread *, void (*)(void *), void *);
void cpu_set_syscall_retval(struct thread *, int);
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
index b30447cfb682..a6dbe2cad3e8 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -99,6 +99,9 @@ struct ptrace_lwpinfo {
int pl_flags; /* LWP flags. */
#define PL_FLAG_SA 0x01 /* M:N thread */
#define PL_FLAG_BOUND 0x02 /* M:N bound thread */
+#define PL_FLAG_SCE 0x04 /* syscall enter point */
+#define PL_FLAG_SCX 0x08 /* syscall leave point */
+#define PL_FLAG_EXEC 0x10 /* exec(2) succeeded */
sigset_t pl_sigmask; /* LWP signal mask */
sigset_t pl_siglist; /* LWP pending signal */
};
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index c3a19d82d16c..6a8f538fa618 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -65,6 +65,7 @@ struct sysent { /* system call table */
struct image_params;
struct __sigset;
+struct syscall_args;
struct trapframe;
struct vnode;
@@ -103,6 +104,10 @@ struct sysentvec {
void (*sv_fixlimit)(struct rlimit *, int);
u_long *sv_maxssiz;
u_int sv_flags;
+ void (*sv_set_syscall_retval)(struct thread *, int);
+ int (*sv_fetch_syscall_args)(struct thread *, struct
+ syscall_args *);
+ const char **sv_syscallnames;
};
#define SV_ILP32 0x000100
@@ -123,6 +128,7 @@ extern struct sysentvec aout_sysvec;
extern struct sysentvec elf_freebsd_sysvec;
extern struct sysentvec null_sysvec;
extern struct sysent sysent[];
+extern const char *syscallnames[];
#define NO_SYSCALL (-1)