diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index c97985d..3f7ea81 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -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. diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c index 51d1d62..6e56740 100644 --- a/sys/amd64/amd64/vm_machdep.c +++ b/sys/amd64/amd64/vm_machdep.c @@ -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 diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c index e6150c0..348ec5a 100644 --- a/sys/arm/arm/trap.c +++ b/sys/arm/arm/trap.c @@ -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] : "???"); diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c index 6bd5799..95b9ca8 100644 --- a/sys/arm/arm/vm_machdep.c +++ b/sys/arm/arm/vm_machdep.c @@ -51,6 +51,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #include @@ -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 diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index f4df668..f8d0ea0 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -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. diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c index e7f55a1..2948eb7 100644 --- a/sys/i386/i386/vm_machdep.c +++ b/sys/i386/i386/vm_machdep.c @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -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 diff --git a/sys/ia64/ia64/trap.c b/sys/ia64/ia64/trap.c index 2633ad2..2a4dca8 100644 --- a/sys/ia64/ia64/trap.c +++ b/sys/ia64/ia64/trap.c @@ -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++; /* diff --git a/sys/ia64/ia64/vm_machdep.c b/sys/ia64/ia64/vm_machdep.c index e5088a5..37af94b 100644 --- a/sys/ia64/ia64/vm_machdep.c +++ b/sys/ia64/ia64/vm_machdep.c @@ -73,6 +73,7 @@ #include #include #include +#include #include #include #include @@ -140,6 +141,36 @@ cpu_thread_swapout(struct thread *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) { struct pcb *pcb; diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index e174df1..412e00d 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1471,21 +1471,19 @@ kern_sigsuspend(struct thread *td, sigset_t mask) * thread. But sigsuspend should return only on signal * delivery. */ + cpu_set_syscall_retval(td, EINTR); for (has_sig = 0; !has_sig;) { while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "pause", 0) == 0) /* void */; thread_suspend_check(0); mtx_lock(&p->p_sigacts->ps_mtx); - while ((sig = cursig(td, SIG_STOP_ALLOWED)) != 0) { - postsig(sig); - has_sig = 1; - } + while ((sig = cursig(td, SIG_STOP_ALLOWED)) != 0) + has_sig += postsig(sig); mtx_unlock(&p->p_sigacts->ps_mtx); } PROC_UNLOCK(p); - /* always return EINTR rather than ERESTART... */ - return (EINTR); + return (EJUSTRETURN); } #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ @@ -2670,7 +2668,7 @@ thread_stopped(struct proc *p) * Take the action for the specified signal * from the current set of pending signals. */ -void +int postsig(sig) register int sig; { @@ -2689,7 +2687,7 @@ postsig(sig) ksiginfo_init(&ksi); if (sigqueue_get(&td->td_sigqueue, sig, &ksi) == 0 && sigqueue_get(&p->p_sigqueue, sig, &ksi) == 0) - return; + return (0); ksi.ksi_signo = sig; if (ksi.ksi_code == SI_TIMER) itimer_accept(p, ksi.ksi_timerid, &ksi); @@ -2757,6 +2755,7 @@ postsig(sig) } (*p->p_sysent->sv_sendsig)(action, &ksi, &returnmask); } + return (1); } /* diff --git a/sys/mips/include/pcb.h b/sys/mips/include/pcb.h index 16d274d..f54f2d7 100644 --- a/sys/mips/include/pcb.h +++ b/sys/mips/include/pcb.h @@ -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 diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c index 6d047cc..1124b1c 100644 --- a/sys/mips/mips/trap.c +++ b/sys/mips/mips/trap.c @@ -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 diff --git a/sys/mips/mips/vm_machdep.c b/sys/mips/mips/vm_machdep.c index 26b6477..918c5f0 100644 --- a/sys/mips/mips/vm_machdep.c +++ b/sys/mips/mips/vm_machdep.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -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 diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c index ee9c7d3..60c6bb0 100644 --- a/sys/powerpc/aim/trap.c +++ b/sys/powerpc/aim/trap.c @@ -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. diff --git a/sys/powerpc/aim/vm_machdep.c b/sys/powerpc/aim/vm_machdep.c index af83854..3967176 100644 --- a/sys/powerpc/aim/vm_machdep.c +++ b/sys/powerpc/aim/vm_machdep.c @@ -81,7 +81,9 @@ #include #include #include +#include #include +#include #include #include @@ -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; + + 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) { struct pcb *pcb2; diff --git a/sys/powerpc/booke/trap.c b/sys/powerpc/booke/trap.c index 0e746f4..d98efb9 100644 --- a/sys/powerpc/booke/trap.c +++ b/sys/powerpc/booke/trap.c @@ -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. diff --git a/sys/powerpc/booke/vm_machdep.c b/sys/powerpc/booke/vm_machdep.c index 178b863..7d2b88b 100644 --- a/sys/powerpc/booke/vm_machdep.c +++ b/sys/powerpc/booke/vm_machdep.c @@ -113,7 +113,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -423,6 +425,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) { struct pcb *pcb2; diff --git a/sys/sparc64/include/pcb.h b/sys/sparc64/include/pcb.h index 7e8294a..f23c1f2 100644 --- a/sys/sparc64/include/pcb.h +++ b/sys/sparc64/include/pcb.h @@ -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 diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index 702e4f1..0c07eaf 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -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. diff --git a/sys/sparc64/sparc64/vm_machdep.c b/sys/sparc64/sparc64/vm_machdep.c index 76521a6..009f45d 100644 --- a/sys/sparc64/sparc64/vm_machdep.c +++ b/sys/sparc64/sparc64/vm_machdep.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -166,6 +167,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) { struct trapframe *tf; diff --git a/sys/sun4v/sun4v/trap.c b/sys/sun4v/sun4v/trap.c index ffa0e8c..353462d 100644 --- a/sys/sun4v/sun4v/trap.c +++ b/sys/sun4v/sun4v/trap.c @@ -81,6 +81,7 @@ #include #include #include +#include #include #include #include @@ -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 diff --git a/sys/sun4v/sun4v/vm_machdep.c b/sys/sun4v/sun4v/vm_machdep.c index 63a002f..5e02aec 100644 --- a/sys/sun4v/sun4v/vm_machdep.c +++ b/sys/sun4v/sun4v/vm_machdep.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -142,6 +143,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) { struct trapframe *tf; diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 384f280..3eb6ea6 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -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 *); diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index c27a128..65d9cf5 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -330,7 +330,7 @@ void gsignal(int pgid, int sig); void killproc(struct proc *p, char *why); void pgsigio(struct sigio **, int signum, int checkctty); void pgsignal(struct pgrp *pgrp, int sig, int checkctty); -void postsig(int sig); +int postsig(int sig); void psignal(struct proc *p, int sig); int psignal_event(struct proc *p, struct sigevent *, ksiginfo_t *); struct sigacts *sigacts_alloc(void);