Extract the code that records syscall results in the frame into MD

function cpu_set_syscall_retval().

Suggested by:	marcel
Reviewed by:	marcel, davidxu
PowerPC, ARM, ia64 changes:	marcel
Sparc64 tested and reviewed by:	marius, also sunv reviewed
MIPS tested by:	gonzo
MFC after:	1 month
This commit is contained in:
Konstantin Belousov 2009-11-10 11:43:07 +00:00
parent 1a29dc59c5
commit a7b890448c
21 changed files with 418 additions and 303 deletions

View File

@ -1007,39 +1007,7 @@ syscall(struct trapframe *frame)
#endif
}
switch (error) {
case 0:
frame->tf_rax = td->td_retval[0];
frame->tf_rdx = td->td_retval[1];
frame->tf_rflags &= ~PSL_C;
break;
case ERESTART:
/*
* Reconstruct pc, we know that 'syscall' is 2 bytes.
* We have to do a full context restore so that %r10
* (which was holding the value of %rcx) is restored for
* the next iteration.
*/
frame->tf_rip -= frame->tf_err;
frame->tf_r10 = frame->tf_rcx;
td->td_pcb->pcb_flags |= PCB_FULLCTX;
break;
case EJUSTRETURN:
break;
default:
if (p->p_sysent->sv_errsize) {
if (error >= p->p_sysent->sv_errsize)
error = -1; /* XXX */
else
error = p->p_sysent->sv_errtbl[error];
}
frame->tf_rax = error;
frame->tf_rflags |= PSL_C;
break;
}
cpu_set_syscall_retval(td, error);
/*
* Traced syscall.

View File

@ -317,6 +317,45 @@ cpu_thread_free(struct thread *td)
cpu_thread_clean(td);
}
void
cpu_set_syscall_retval(struct thread *td, int error)
{
switch (error) {
case 0:
td->td_frame->tf_rax = td->td_retval[0];
td->td_frame->tf_rdx = td->td_retval[1];
td->td_frame->tf_rflags &= ~PSL_C;
break;
case ERESTART:
/*
* Reconstruct pc, we know that 'syscall' is 2 bytes.
* We have to do a full context restore so that %r10
* (which was holding the value of %rcx) is restored
* for the next iteration.
*/
td->td_frame->tf_rip -= td->td_frame->tf_err;
td->td_frame->tf_r10 = td->td_frame->tf_rcx;
td->td_pcb->pcb_flags |= PCB_FULLCTX;
break;
case EJUSTRETURN:
break;
default:
if (td->td_proc->p_sysent->sv_errsize) {
if (error >= td->td_proc->p_sysent->sv_errsize)
error = -1; /* XXX */
else
error = td->td_proc->p_sysent->sv_errtbl[error];
}
td->td_frame->tf_rax = error;
td->td_frame->tf_rflags |= PSL_C;
break;
}
}
/*
* Initialize machine state (pcb and trap frame) for a new thread about to
* upcall. Put enough state in the new thread's PCB to get it to go back

View File

@ -932,43 +932,8 @@ syscall(struct thread *td, trapframe_t *frame, u_int32_t insn)
KASSERT(td->td_ar == NULL,
("returning from syscall with td_ar set!"));
}
switch (error) {
case 0:
#ifdef __ARMEB__
if ((insn & 0x000fffff) == SYS___syscall &&
code != SYS_freebsd6_lseek && code != SYS_lseek) {
/*
* 64-bit return, 32-bit syscall. Fixup byte order
*/
frame->tf_r0 = 0;
frame->tf_r1 = td->td_retval[0];
} else {
frame->tf_r0 = td->td_retval[0];
frame->tf_r1 = td->td_retval[1];
}
#else
frame->tf_r0 = td->td_retval[0];
frame->tf_r1 = td->td_retval[1];
#endif
frame->tf_spsr &= ~PSR_C_bit; /* carry bit */
break;
case ERESTART:
/*
* Reconstruct the pc to point at the swi.
*/
frame->tf_pc -= INSN_SIZE;
break;
case EJUSTRETURN:
/* nothing to do */
break;
default:
bad:
frame->tf_r0 = error;
frame->tf_spsr |= PSR_C_bit; /* carry bit */
break;
}
cpu_set_syscall_retval(td, error);
WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
(code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");

View File

@ -51,6 +51,8 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/socketvar.h>
#include <sys/sf_buf.h>
#include <sys/syscall.h>
#include <sys/sysent.h>
#include <sys/unistd.h>
#include <machine/cpu.h>
#include <machine/pcb.h>
@ -261,6 +263,57 @@ done:
#endif
}
void
cpu_set_syscall_retval(struct thread *td, int error)
{
trapframe_t *frame;
int fixup;
#ifdef __ARMEB__
uint32_t insn;
#endif
frame = td->td_frame;
fixup = 0;
#ifdef __ARMEB__
insn = *(u_int32_t *)(frame->tf_pc - INSN_SIZE);
if ((insn & 0x000fffff) == SYS___syscall) {
register_t *ap = &frame->tf_r0;
register_t code = ap[_QUAD_LOWWORD];
if (td->td_proc->p_sysent->sv_mask)
code &= td->td_proc->p_sysent->sv_mask;
fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek)
? 1 : 0;
}
#endif
switch (error) {
case 0:
if (fixup) {
frame->tf_r0 = 0;
frame->tf_r1 = td->td_retval[0];
} else {
frame->tf_r0 = td->td_retval[0];
frame->tf_r1 = td->td_retval[1];
}
frame->tf_spsr &= ~PSR_C_bit; /* carry bit */
break;
case ERESTART:
/*
* Reconstruct the pc to point at the swi.
*/
frame->tf_pc -= INSN_SIZE;
break;
case EJUSTRETURN:
/* nothing to do */
break;
default:
frame->tf_r0 = error;
frame->tf_spsr |= PSR_C_bit; /* carry bit */
break;
}
}
/*
* Initialize machine state (pcb and trap frame) for a new thread about to
* upcall. Put enough state in the new thread's PCB to get it to go back

View File

@ -1093,35 +1093,7 @@ syscall(struct trapframe *frame)
#endif
}
switch (error) {
case 0:
frame->tf_eax = td->td_retval[0];
frame->tf_edx = td->td_retval[1];
frame->tf_eflags &= ~PSL_C;
break;
case ERESTART:
/*
* Reconstruct pc, assuming lcall $X,y is 7 bytes,
* int 0x80 is 2 bytes. We saved this in tf_err.
*/
frame->tf_eip -= frame->tf_err;
break;
case EJUSTRETURN:
break;
default:
if (p->p_sysent->sv_errsize) {
if (error >= p->p_sysent->sv_errsize)
error = -1; /* XXX */
else
error = p->p_sysent->sv_errtbl[error];
}
frame->tf_eax = error;
frame->tf_eflags |= PSL_C;
break;
}
cpu_set_syscall_retval(td, error);
/*
* Traced syscall.

View File

@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/pioctl.h>
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/sf_buf.h>
#include <sys/smp.h>
#include <sys/sched.h>
@ -380,6 +381,41 @@ cpu_thread_free(struct thread *td)
cpu_thread_clean(td);
}
void
cpu_set_syscall_retval(struct thread *td, int error)
{
switch (error) {
case 0:
td->td_frame->tf_eax = td->td_retval[0];
td->td_frame->tf_edx = td->td_retval[1];
td->td_frame->tf_eflags &= ~PSL_C;
break;
case ERESTART:
/*
* Reconstruct pc, assuming lcall $X,y is 7 bytes, int
* 0x80 is 2 bytes. We saved this in tf_err.
*/
td->td_frame->tf_eip -= td->td_frame->tf_err;
break;
case EJUSTRETURN:
break;
default:
if (td->td_proc->p_sysent->sv_errsize) {
if (error >= td->td_proc->p_sysent->sv_errsize)
error = -1; /* XXX */
else
error = td->td_proc->p_sysent->sv_errtbl[error];
}
td->td_frame->tf_eax = error;
td->td_frame->tf_eflags |= PSL_C;
break;
}
}
/*
* Initialize machine state (pcb and trap frame) for a new thread about to
* upcall. Put enough state in the new thread's PCB to get it to go back

View File

@ -976,26 +976,7 @@ syscall(struct trapframe *tf)
error = (*callp->sy_call)(td, args);
AUDIT_SYSCALL_EXIT(error, td);
if (error != EJUSTRETURN) {
/*
* Save the "raw" error code in r10. We use this to handle
* syscall restarts (see do_ast()).
*/
tf->tf_scratch.gr10 = error;
if (error == 0) {
tf->tf_scratch.gr8 = td->td_retval[0];
tf->tf_scratch.gr9 = td->td_retval[1];
} else if (error != ERESTART) {
if (error < p->p_sysent->sv_errsize)
error = p->p_sysent->sv_errtbl[error];
/*
* Translated error codes are returned in r8. User
* processes use the translated error code.
*/
tf->tf_scratch.gr8 = error;
}
}
cpu_set_syscall_retval(td, error);
td->td_syscalls++;
/*

View File

@ -73,6 +73,7 @@
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/sysent.h>
#include <sys/vnode.h>
#include <sys/vmmeter.h>
#include <sys/kernel.h>
@ -139,6 +140,36 @@ cpu_thread_swapout(struct thread *td)
ia64_highfp_save(td);
}
void
cpu_set_syscall_retval(struct thread *td, int error)
{
struct proc *p;
struct trapframe *tf;
if (error == EJUSTRETURN)
return;
tf = td->td_frame;
/*
* Save the "raw" error code in r10. We use this to handle
* syscall restarts (see do_ast()).
*/
tf->tf_scratch.gr10 = error;
if (error == 0) {
tf->tf_scratch.gr8 = td->td_retval[0];
tf->tf_scratch.gr9 = td->td_retval[1];
} else if (error != ERESTART) {
p = td->td_proc;
if (error < p->p_sysent->sv_errsize)
error = p->p_sysent->sv_errtbl[error];
/*
* Translated error codes are returned in r8. User
*/
tf->tf_scratch.gr8 = error;
}
}
void
cpu_set_upcall(struct thread *td, struct thread *td0)
{

View File

@ -52,6 +52,7 @@ struct pcb
struct trapframe pcb_regs; /* saved CPU and registers */
label_t pcb_context; /* kernel context for resume */
int pcb_onfault; /* for copyin/copyout faults */
register_t pcb_tpc;
};
/* these match the regnum's in regnum.h

View File

@ -644,7 +644,6 @@ dofault:
struct trapframe *locr0 = td->td_frame;
struct sysent *callp;
unsigned int code;
unsigned int tpc;
int nargs, nsaved;
register_t args[8];
@ -660,7 +659,7 @@ dofault:
thread_user_enter(td);
#endif
/* compute next PC after syscall instruction */
tpc = trapframe->pc; /* Remember if restart */
td->td_pcb->pcb_tpc = trapframe->pc; /* Remember if restart */
if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
0);
@ -761,44 +760,7 @@ dofault:
locr0 = td->td_frame;
#endif
trapdebug_enter(locr0, -code);
switch (i) {
case 0:
if (quad_syscall && code != SYS_lseek) {
/*
* System call invoked through the
* SYS___syscall interface but the
* return value is really just 32
* bits.
*/
locr0->v0 = td->td_retval[0];
if (_QUAD_LOWWORD)
locr0->v1 = td->td_retval[0];
locr0->a3 = 0;
} else {
locr0->v0 = td->td_retval[0];
locr0->v1 = td->td_retval[1];
locr0->a3 = 0;
}
break;
case ERESTART:
locr0->pc = tpc;
break;
case EJUSTRETURN:
break; /* nothing to do */
default:
if (quad_syscall && code != SYS_lseek) {
locr0->v0 = i;
if (_QUAD_LOWWORD)
locr0->v1 = i;
locr0->a3 = 1;
} else {
locr0->v0 = i;
locr0->a3 = 1;
}
}
cpu_set_syscall_retval(td, i);
/*
* The sync'ing of I & D caches for SYS_ptrace() is

View File

@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/syscall.h>
#include <sys/buf.h>
#include <sys/vnode.h>
#include <sys/vmmeter.h>
@ -256,6 +257,62 @@ cpu_thread_alloc(struct thread *td)
}
}
void
cpu_set_syscall_retval(struct thread *td, int error)
{
struct trapframe *locr0 = td->td_frame;
unsigned int code;
int quad_syscall;
code = locr0->v0;
quad_syscall = 0;
if (code == SYS_syscall)
code = locr0->a0;
else if (code == SYS___syscall) {
code = _QUAD_LOWWORD ? locr0->a1 : locr0->a0;
quad_syscall = 1;
}
switch (error) {
case 0:
if (quad_syscall && code != SYS_lseek) {
/*
* System call invoked through the
* SYS___syscall interface but the
* return value is really just 32
* bits.
*/
locr0->v0 = td->td_retval[0];
if (_QUAD_LOWWORD)
locr0->v1 = td->td_retval[0];
locr0->a3 = 0;
} else {
locr0->v0 = td->td_retval[0];
locr0->v1 = td->td_retval[1];
locr0->a3 = 0;
}
break;
case ERESTART:
locr0->pc = td->td_pcb->pcb_tpc;
break;
case EJUSTRETURN:
break; /* nothing to do */
default:
if (quad_syscall && code != SYS_lseek) {
locr0->v0 = error;
if (_QUAD_LOWWORD)
locr0->v1 = error;
locr0->a3 = 1;
} else {
locr0->v0 = error;
locr0->a3 = 1;
}
}
}
/*
* Initialize machine state (pcb and trap frame) for a new thread about to
* upcall. Put enough state in the new thread's PCB to get it to go back

View File

@ -415,43 +415,8 @@ syscall(struct trapframe *frame)
CTR3(KTR_SYSC, "syscall: p=%s %s ret=%x", td->td_name,
syscallnames[code], td->td_retval[0]);
}
switch (error) {
case 0:
if (frame->fixreg[0] == SYS___syscall &&
code != SYS_freebsd6_lseek && code != SYS_lseek) {
/*
* 64-bit return, 32-bit syscall. Fixup byte order
*/
frame->fixreg[FIRSTARG] = 0;
frame->fixreg[FIRSTARG + 1] = td->td_retval[0];
} else {
frame->fixreg[FIRSTARG] = td->td_retval[0];
frame->fixreg[FIRSTARG + 1] = td->td_retval[1];
}
/* XXX: Magic number */
frame->cr &= ~0x10000000;
break;
case ERESTART:
/*
* Set user's pc back to redo the system call.
*/
frame->srr0 -= 4;
break;
case EJUSTRETURN:
/* nothing to do */
break;
default:
if (p->p_sysent->sv_errsize) {
if (error >= p->p_sysent->sv_errsize)
error = -1; /* XXX */
else
error = p->p_sysent->sv_errtbl[error];
}
frame->fixreg[FIRSTARG] = error;
/* XXX: Magic number: Carry Flag Equivalent? */
frame->cr |= 0x10000000;
break;
}
cpu_set_syscall_retval(td, error);
/*
* Check for misbehavior.

View File

@ -81,7 +81,9 @@
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/sf_buf.h>
#include <sys/syscall.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/unistd.h>
#include <machine/cpu.h>
@ -421,6 +423,59 @@ cpu_thread_swapout(struct thread *td)
{
}
void
cpu_set_syscall_retval(struct thread *td, int error)
{
struct proc *p;
struct trapframe *tf;
int fixup;
if (error == EJUSTRETURN)
return;
p = td->td_proc;
tf = td->td_frame;
if (tf->fixreg[0] == SYS___syscall) {
int code = tf->fixreg[FIRSTARG + 1];
if (p->p_sysent->sv_mask)
code &= p->p_sysent->sv_mask;
fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ?
1 : 0;
} else
fixup = 0;
switch (error) {
case 0:
if (fixup) {
/*
* 64-bit return, 32-bit syscall. Fixup byte order
*/
tf->fixreg[FIRSTARG] = 0;
tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
} else {
tf->fixreg[FIRSTARG] = td->td_retval[0];
tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
}
tf->cr &= ~0x10000000; /* XXX: Magic number */
break;
case ERESTART:
/*
* Set user's pc back to redo the system call.
*/
tf->srr0 -= 4;
break;
default:
if (p->p_sysent->sv_errsize) {
error = (error < p->p_sysent->sv_errsize) ?
p->p_sysent->sv_errtbl[error] : -1;
}
tf->fixreg[FIRSTARG] = error;
tf->cr |= 0x10000000; /* XXX: Magic number */
break;
}
}
void
cpu_set_upcall(struct thread *td, struct thread *td0)
{

View File

@ -417,42 +417,7 @@ syscall(struct trapframe *frame)
syscallnames[code], td->td_retval[0]);
}
switch (error) {
case 0:
if (frame->fixreg[0] == SYS___syscall && SYS_lseek) {
/*
* 64-bit return, 32-bit syscall. Fixup byte order
*/
frame->fixreg[FIRSTARG] = 0;
frame->fixreg[FIRSTARG + 1] = td->td_retval[0];
} else {
frame->fixreg[FIRSTARG] = td->td_retval[0];
frame->fixreg[FIRSTARG + 1] = td->td_retval[1];
}
/* XXX: Magic number */
frame->cr &= ~0x10000000;
break;
case ERESTART:
/*
* Set user's pc back to redo the system call.
*/
frame->srr0 -= 4;
break;
case EJUSTRETURN:
/* nothing to do */
break;
default:
if (p->p_sysent->sv_errsize) {
if (error >= p->p_sysent->sv_errsize)
error = -1; /* XXX */
else
error = p->p_sysent->sv_errtbl[error];
}
frame->fixreg[FIRSTARG] = error;
/* XXX: Magic number: Carry Flag Equivalent? */
frame->cr |= 0x10000000;
break;
}
cpu_set_syscall_retval(td, error);
/*
* Check for misbehavior.

View File

@ -113,7 +113,9 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/sf_buf.h>
#include <sys/syscall.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/unistd.h>
#include <machine/clock.h>
@ -422,6 +424,59 @@ cpu_thread_swapout(struct thread *td)
}
void
cpu_set_syscall_retval(struct thread *td, int error)
{
struct proc *p;
struct trapframe *tf;
int fixup;
p = td->td_proc;
tf = td->td_frame;
if (tf->fixreg[0] == SYS___syscall) {
int code = tf->fixreg[FIRSTARG + 1];
if (p->p_sysent->sv_mask)
code &= p->p_sysent->sv_mask;
fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ?
1 : 0;
} else
fixup = 0;
switch (error) {
case 0:
if (fixup) {
/*
* 64-bit return, 32-bit syscall. Fixup byte order
*/
tf->fixreg[FIRSTARG] = 0;
tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
} else {
tf->fixreg[FIRSTARG] = td->td_retval[0];
tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
}
tf->cr &= ~0x10000000; /* XXX: Magic number */
break;
case ERESTART:
/*
* Set user's pc back to redo the system call.
*/
tf->srr0 -= 4;
break;
case EJUSTRETURN:
/* nothing to do */
break;
default:
if (p->p_sysent->sv_errsize) {
error = (error < p->p_sysent->sv_errsize) ?
p->p_sysent->sv_errtbl[error] : -1;
}
tf->fixreg[FIRSTARG] = error;
tf->cr |= 0x10000000; /* XXX: Magic number */
break;
}
}
void
cpu_set_upcall(struct thread *td, struct thread *td0)
{

View File

@ -49,7 +49,8 @@ struct pcb {
uint64_t pcb_nsaved;
uint64_t pcb_pc;
uint64_t pcb_sp;
uint64_t pcb_pad[4];
uint64_t pcb_tpc;
uint64_t pcb_pad[3];
} __aligned(64);
#ifdef _KERNEL

View File

@ -538,7 +538,6 @@ syscall(struct trapframe *tf)
register_t *argp;
struct proc *p;
u_long code;
u_long tpc;
int reg;
int regcnt;
int narg;
@ -562,7 +561,7 @@ syscall(struct trapframe *tf)
* For syscalls, we don't want to retry the faulting instruction
* (usually), instead we need to advance one instruction.
*/
tpc = tf->tf_tpc;
td->td_pcb->pcb_tpc = tf->tf_tpc;
TF_DONE(tf);
reg = 0;
@ -626,39 +625,7 @@ syscall(struct trapframe *tf)
td->td_retval[1]);
}
/*
* MP SAFE (we may or may not have the MP lock at this point)
*/
switch (error) {
case 0:
tf->tf_out[0] = td->td_retval[0];
tf->tf_out[1] = td->td_retval[1];
tf->tf_tstate &= ~TSTATE_XCC_C;
break;
case ERESTART:
/*
* Undo the tpc advancement we have done above, we want to
* reexecute the system call.
*/
tf->tf_tpc = tpc;
tf->tf_tnpc -= 4;
break;
case EJUSTRETURN:
break;
default:
if (p->p_sysent->sv_errsize) {
if (error >= p->p_sysent->sv_errsize)
error = -1; /* XXX */
else
error = p->p_sysent->sv_errtbl[error];
}
tf->tf_out[0] = error;
tf->tf_tstate |= TSTATE_XCC_C;
break;
}
cpu_set_syscall_retval(td, error);
/*
* Check for misbehavior.

View File

@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/sf_buf.h>
#include <sys/sched.h>
#include <sys/sysctl.h>
@ -165,6 +166,42 @@ cpu_thread_swapout(struct thread *td)
}
void
cpu_set_syscall_retval(struct thread *td, int error)
{
switch (error) {
case 0:
td->td_frame->tf_out[0] = td->td_retval[0];
td->td_frame->tf_out[1] = td->td_retval[1];
td->td_frame->tf_tstate &= ~TSTATE_XCC_C;
break;
case ERESTART:
/*
* Undo the tpc advancement we have done on syscall
* enter, we want to reexecute the system call.
*/
td->td_frame->tf_tpc = td->td_pcb->pcb_tpc;
td->td_frame->tf_tnpc -= 4;
break;
case EJUSTRETURN:
break;
default:
if (td->td_proc->p_sysent->sv_errsize) {
if (error >= td->td_proc->p_sysent->sv_errsize)
error = -1; /* XXX */
else
error = td->td_proc->p_sysent->sv_errtbl[error];
}
td->td_frame->tf_out[0] = error;
td->td_frame->tf_tstate |= TSTATE_XCC_C;
break;
}
}
void
cpu_set_upcall(struct thread *td, struct thread *td0)
{

View File

@ -81,6 +81,7 @@
#include <machine/cpu.h>
#include <machine/frame.h>
#include <machine/intr_machdep.h>
#include <machine/pcb.h>
#include <machine/smp.h>
#include <machine/trap.h>
#include <machine/tstate.h>
@ -582,7 +583,6 @@ syscall(struct trapframe *tf)
register_t *argp;
struct proc *p;
u_long code;
u_long tpc;
int reg;
int regcnt;
int narg;
@ -606,7 +606,7 @@ syscall(struct trapframe *tf)
* For syscalls, we don't want to retry the faulting instruction
* (usually), instead we need to advance one instruction.
*/
tpc = tf->tf_tpc;
td->td_pcb->pcb_tpc = tf->tf_tpc;
TF_DONE(tf);
reg = 0;
@ -673,40 +673,8 @@ syscall(struct trapframe *tf)
error, syscallnames[code], td->td_retval[0],
td->td_retval[1]);
}
/*
* MP SAFE (we may or may not have the MP lock at this point)
*/
switch (error) {
case 0:
tf->tf_out[0] = td->td_retval[0];
tf->tf_out[1] = td->td_retval[1];
tf->tf_tstate &= ~TSTATE_XCC_C;
break;
case ERESTART:
/*
* Undo the tpc advancement we have done above, we want to
* reexecute the system call.
*/
tf->tf_tpc = tpc;
tf->tf_tnpc -= 4;
break;
case EJUSTRETURN:
break;
default:
if (p->p_sysent->sv_errsize) {
if (error >= p->p_sysent->sv_errsize)
error = -1; /* XXX */
else
error = p->p_sysent->sv_errtbl[error];
}
tf->tf_out[0] = error;
tf->tf_tstate |= TSTATE_XCC_C;
break;
}
cpu_set_syscall_retval(td, error);
/*
* Handle reschedule and other end-of-syscall issues

View File

@ -57,6 +57,7 @@
#include <sys/mutex.h>
#include <sys/sf_buf.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/unistd.h>
#include <sys/vmmeter.h>
@ -141,6 +142,42 @@ cpu_thread_swapout(struct thread *td)
{
}
void
cpu_set_syscall_retval(struct thread *td, int error)
{
switch (error) {
case 0:
td->td_frame->tf_out[0] = td->td_retval[0];
td->td_frame->tf_out[1] = td->td_retval[1];
td->td_frame->tf_tstate &= ~TSTATE_XCC_C;
break;
case ERESTART:
/*
* Undo the tpc advancement we have done on syscall
* enter, we want to reexecute the system call.
*/
td->td_frame->tf_tpc = td->td_pcb->pcb_tpc;
td->td_frame->tf_tnpc -= 4;
break;
case EJUSTRETURN:
break;
default:
if (td->td_proc->p_sysent->sv_errsize) {
if (error >= td->td_proc->p_sysent->sv_errsize)
error = -1; /* XXX */
else
error = td->td_proc->p_sysent->sv_errtbl[error];
}
td->td_frame->tf_out[0] = error;
td->td_frame->tf_tstate |= TSTATE_XCC_C;
break;
}
}
void
cpu_set_upcall(struct thread *td, struct thread *td0)
{

View File

@ -836,7 +836,7 @@ void cpu_exit(struct thread *);
void exit1(struct thread *, int) __dead2;
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);
void cpu_set_upcall(struct thread *td, struct thread *td0);
void cpu_set_upcall_kse(struct thread *, void (*)(void *), void *,
stack_t *);