aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2010-05-23 18:32:02 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2010-05-23 18:32:02 +0000
commitafe1a68827e6810d86163cc8919247f26a9c45b2 (patch)
tree56fad7d2ceb7c32121f981b707c967936cda94bf /sys
parentfa1ed4bd1ae8cfc4626b6e641390288ed9e4de6c (diff)
downloadsrc-afe1a68827e6810d86163cc8919247f26a9c45b2.tar.gz
src-afe1a68827e6810d86163cc8919247f26a9c45b2.zip
Reorganize syscall entry and leave handling.
Extend struct sysvec with three new elements: sv_fetch_syscall_args - the method to fetch syscall arguments from usermode into struct syscall_args. The structure is machine-depended (this might be reconsidered after all architectures are converted). sv_set_syscall_retval - the method to set a return value for usermode from the syscall. It is a generalization of cpu_set_syscall_retval(9) to allow ABIs to override the way to set a return value. sv_syscallnames - the table of syscall names. Use sv_set_syscall_retval in kern_sigsuspend() instead of hardcoding the call to cpu_set_syscall_retval(). The new functions syscallenter(9) and syscallret(9) are provided that use sv_*syscall* pointers and contain the common repeated code from the syscall() implementations for the architecture-specific syscall trap handlers. Syscallenter() fetches arguments, calls syscall implementation from ABI sysent table, and set up return frame. The end of syscall bookkeeping is done by syscallret(). Take advantage of single place for MI syscall handling code and implement ptrace_lwpinfo pl_flags PL_FLAG_SCE, PL_FLAG_SCX and PL_FLAG_EXEC. The SCE and SCX flags notify the debugger that the thread is stopped at syscall entry or return point respectively. The EXEC flag augments SCX and notifies debugger that the process address space was changed by one of exec(2)-family syscalls. The i386, amd64, sparc64, sun4v, powerpc and ia64 syscall()s are changed to use syscallenter()/syscallret(). MIPS and arm are not converted and use the mostly unchanged syscall() implementation. Reviewed by: jhb, marcel, marius, nwhitehorn, stas Tested by: marcel (ia64), marius (sparc64), nwhitehorn (powerpc), stas (mips) MFC after: 1 month
Notes
Notes: svn path=/head/; revision=208453
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)