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:
parent
1a29dc59c5
commit
a7b890448c
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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] : "???");
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 *);
|
||||
|
Loading…
x
Reference in New Issue
Block a user