Index: stable/6/sys/amd64/ia32/ia32_signal.c =================================================================== --- stable/6/sys/amd64/ia32/ia32_signal.c (revision 169231) +++ stable/6/sys/amd64/ia32/ia32_signal.c (revision 169232) @@ -1,599 +1,762 @@ /*- * Copyright (c) 2003 Peter Wemm * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef COMPAT_FREEBSD4 static void freebsd4_ia32_sendsig(sig_t, int, sigset_t *, u_long); #endif static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp); static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp); extern int _ucode32sel, _udatasel; #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) #define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp) { struct savefpu *addr; /* * XXX mc_fpstate might be misaligned, since its declaration is not * unportabilized using __attribute__((aligned(16))) like the * declaration of struct savemm, and anyway, alignment doesn't work * for auto variables since we don't use gcc's pessimal stack * alignment. Work around this by abusing the spare fields after * mcp->mc_fpstate. * * XXX unpessimize most cases by only aligning when fxsave might be * called, although this requires knowing too much about * fpugetregs()'s internals. */ addr = (struct savefpu *)&mcp->mc_fpstate; if (td == PCPU_GET(fpcurthread) && ((uintptr_t)(void *)addr & 0xF)) { do addr = (void *)((char *)addr + 4); while ((uintptr_t)(void *)addr & 0xF); } mcp->mc_ownedfp = fpugetregs(td, addr); if (addr != (struct savefpu *)&mcp->mc_fpstate) { bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate)); bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2)); } mcp->mc_fpformat = fpuformat(); } static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp) { struct savefpu *addr; if (mcp->mc_fpformat == _MC_FPFMT_NODEV) return (0); else if (mcp->mc_fpformat != _MC_FPFMT_XMM) return (EINVAL); else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) /* We don't care what state is left in the FPU or PCB. */ fpstate_drop(td); else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || mcp->mc_ownedfp == _MC_FPOWNED_PCB) { /* XXX align as above. */ addr = (struct savefpu *)&mcp->mc_fpstate; if (td == PCPU_GET(fpcurthread) && ((uintptr_t)(void *)addr & 0xF)) { do addr = (void *)((char *)addr + 4); while ((uintptr_t)(void *)addr & 0xF); bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate)); } /* * XXX we violate the dubious requirement that fpusetregs() * be called with interrupts disabled. */ fpusetregs(td, addr); /* * Don't bother putting things back where they were in the * misaligned case, since we know that the caller won't use * them again. */ } else return (EINVAL); return (0); } /* + * Get machine context. + */ +static int +ia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags) +{ + struct trapframe *tp; + + tp = td->td_frame; + + PROC_LOCK(curthread->td_proc); + mcp->mc_onstack = sigonstack(tp->tf_rsp); + PROC_UNLOCK(curthread->td_proc); + mcp->mc_gs = td->td_pcb->pcb_gs; + mcp->mc_fs = td->td_pcb->pcb_fs; + mcp->mc_es = td->td_pcb->pcb_es; + mcp->mc_ds = td->td_pcb->pcb_ds; + mcp->mc_edi = tp->tf_rdi; + mcp->mc_esi = tp->tf_rsi; + mcp->mc_ebp = tp->tf_rbp; + mcp->mc_isp = tp->tf_rsp; + if (flags & GET_MC_CLEAR_RET) { + mcp->mc_eax = 0; + mcp->mc_edx = 0; + } else { + mcp->mc_eax = tp->tf_rax; + mcp->mc_edx = tp->tf_rdx; + } + mcp->mc_ebx = tp->tf_rbx; + mcp->mc_ecx = tp->tf_rcx; + mcp->mc_eip = tp->tf_rip; + mcp->mc_cs = tp->tf_cs; + mcp->mc_eflags = tp->tf_rflags; + mcp->mc_esp = tp->tf_rsp; + mcp->mc_ss = tp->tf_ss; + mcp->mc_len = sizeof(*mcp); + ia32_get_fpcontext(td, mcp); + return (0); +} + +/* + * Set machine context. + * + * However, we don't set any but the user modifiable flags, and we won't + * touch the cs selector. + */ +static int +ia32_set_mcontext(struct thread *td, const struct ia32_mcontext *mcp) +{ + struct trapframe *tp; + long rflags; + int ret; + + tp = td->td_frame; + if (mcp->mc_len != sizeof(*mcp)) + return (EINVAL); + rflags = (mcp->mc_eflags & PSL_USERCHANGE) | + (tp->tf_rflags & ~PSL_USERCHANGE); + ret = ia32_set_fpcontext(td, mcp); + if (ret != 0) + return (ret); +#if 0 /* XXX deal with load_fs() and friends */ + tp->tf_fs = mcp->mc_fs; + tp->tf_es = mcp->mc_es; + tp->tf_ds = mcp->mc_ds; +#endif + tp->tf_rdi = mcp->mc_edi; + tp->tf_rsi = mcp->mc_esi; + tp->tf_rbp = mcp->mc_ebp; + tp->tf_rbx = mcp->mc_ebx; + tp->tf_rdx = mcp->mc_edx; + tp->tf_rcx = mcp->mc_ecx; + tp->tf_rax = mcp->mc_eax; + /* trapno, err */ + tp->tf_rip = mcp->mc_eip; + tp->tf_rflags = rflags; + tp->tf_rsp = mcp->mc_esp; + tp->tf_ss = mcp->mc_ss; +#if 0 /* XXX deal with load_gs() and friends */ + td->td_pcb->pcb_gs = mcp->mc_gs; +#endif + td->td_pcb->pcb_flags |= PCB_FULLCTX; + return (0); +} + +/* + * The first two fields of a ucontext_t are the signal mask and + * the machine context. The next field is uc_link; we want to + * avoid destroying the link when copying out contexts. + */ +#define UC_COPY_SIZE offsetof(struct ia32_ucontext, uc_link) + +int +freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) +{ + struct ia32_ucontext uc; + int ret; + + if (uap->ucp == NULL) + ret = EINVAL; + else { + ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); + PROC_LOCK(td->td_proc); + uc.uc_sigmask = td->td_sigmask; + PROC_UNLOCK(td->td_proc); + ret = copyout(&uc, uap->ucp, UC_COPY_SIZE); + } + return (ret); +} + +int +freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) +{ + struct ia32_ucontext uc; + int ret; + + if (uap->ucp == NULL) + ret = EINVAL; + else { + ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); + if (ret == 0) { + ret = ia32_set_mcontext(td, &uc.uc_mcontext); + if (ret == 0) { + SIG_CANTMASK(uc.uc_sigmask); + PROC_LOCK(td->td_proc); + td->td_sigmask = uc.uc_sigmask; + PROC_UNLOCK(td->td_proc); + } + } + } + return (ret == 0 ? EJUSTRETURN : ret); +} + +int +freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) +{ + struct ia32_ucontext uc; + int ret; + + if (uap->oucp == NULL || uap->ucp == NULL) + ret = EINVAL; + else { + ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); + PROC_LOCK(td->td_proc); + uc.uc_sigmask = td->td_sigmask; + PROC_UNLOCK(td->td_proc); + ret = copyout(&uc, uap->oucp, UC_COPY_SIZE); + if (ret == 0) { + ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); + if (ret == 0) { + ret = ia32_set_mcontext(td, &uc.uc_mcontext); + if (ret == 0) { + SIG_CANTMASK(uc.uc_sigmask); + PROC_LOCK(td->td_proc); + td->td_sigmask = uc.uc_sigmask; + PROC_UNLOCK(td->td_proc); + } + } + } + } + return (ret == 0 ? EJUSTRETURN : ret); +} + +/* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * at top to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ #ifdef COMPAT_FREEBSD4 static void freebsd4_ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { struct ia32_sigframe4 sf, *sfp; struct proc *p; struct thread *td; struct sigacts *psp; struct trapframe *regs; int oonstack; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_rsp); /* Save user context. */ bzero(&sf, sizeof(sf)); sf.sf_uc.uc_sigmask = *mask; sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; sf.sf_uc.uc_mcontext.mc_gs = rgs(); sf.sf_uc.uc_mcontext.mc_fs = rfs(); __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es)); __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds)); sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; /* Allocate space for the signal handler context. */ if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { sfp = (struct ia32_sigframe4 *)(td->td_sigstk.ss_sp + td->td_sigstk.ss_size - sizeof(sf)); } else sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1; PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_ucontext = (register_t)&sfp->sf_uc; if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; sf.sf_ah = (u_int32_t)(uintptr_t)catcher; /* Fill in POSIX parts */ sf.sf_si.si_signo = sig; sf.sf_si.si_code = code; sf.sf_si.si_addr = regs->tf_addr; } else { /* Old FreeBSD-style arguments. */ sf.sf_siginfo = code; sf.sf_addr = regs->tf_addr; sf.sf_ah = (u_int32_t)(uintptr_t)catcher; } mtx_unlock(&psp->ps_mtx); /* * Copy the sigframe out to the user's stack. */ if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { #ifdef DEBUG printf("process %ld has trashed its stack\n", (long)p->p_pid); #endif PROC_LOCK(p); sigexit(td, SIGILL); } regs->tf_rsp = (uintptr_t)sfp; regs->tf_rip = FREEBSD32_PS_STRINGS - sz_freebsd4_ia32_sigcode; regs->tf_rflags &= ~PSL_T; regs->tf_cs = _ucode32sel; regs->tf_ss = _udatasel; load_ds(_udatasel); td->td_pcb->pcb_ds = _udatasel; load_es(_udatasel); td->td_pcb->pcb_es = _udatasel; /* leave user %fs and %gs untouched */ PROC_LOCK(p); mtx_lock(&psp->ps_mtx); } #endif /* COMPAT_FREEBSD4 */ void ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { struct ia32_sigframe sf, *sfp; struct proc *p; struct thread *td; struct sigacts *psp; char *sp; struct trapframe *regs; int oonstack; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; #ifdef COMPAT_FREEBSD4 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { freebsd4_ia32_sendsig(catcher, sig, mask, code); return; } #endif mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; oonstack = sigonstack(regs->tf_rsp); /* Save user context. */ bzero(&sf, sizeof(sf)); sf.sf_uc.uc_sigmask = *mask; sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; sf.sf_uc.uc_mcontext.mc_gs = rgs(); sf.sf_uc.uc_mcontext.mc_fs = rfs(); __asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es)); __asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds)); sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext); fpstate_drop(td); /* Allocate space for the signal handler context. */ if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && SIGISMEMBER(psp->ps_sigonstack, sig)) { sp = td->td_sigstk.ss_sp + td->td_sigstk.ss_size - sizeof(sf); } else sp = (char *)regs->tf_rsp - sizeof(sf); /* Align to 16 bytes. */ sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF); PROC_UNLOCK(p); /* Translate the signal if appropriate. */ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; /* Build the argument list for the signal handler. */ sf.sf_signum = sig; sf.sf_ucontext = (register_t)&sfp->sf_uc; if (SIGISMEMBER(psp->ps_siginfo, sig)) { /* Signal handler installed with SA_SIGINFO. */ sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; sf.sf_ah = (u_int32_t)(uintptr_t)catcher; /* Fill in POSIX parts */ sf.sf_si.si_signo = sig; sf.sf_si.si_code = code; sf.sf_si.si_addr = regs->tf_addr; } else { /* Old FreeBSD-style arguments. */ sf.sf_siginfo = code; sf.sf_addr = regs->tf_addr; sf.sf_ah = (u_int32_t)(uintptr_t)catcher; } mtx_unlock(&psp->ps_mtx); /* * Copy the sigframe out to the user's stack. */ if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { #ifdef DEBUG printf("process %ld has trashed its stack\n", (long)p->p_pid); #endif PROC_LOCK(p); sigexit(td, SIGILL); } regs->tf_rsp = (uintptr_t)sfp; regs->tf_rip = FREEBSD32_PS_STRINGS - *(p->p_sysent->sv_szsigcode); regs->tf_rflags &= ~PSL_T; regs->tf_cs = _ucode32sel; regs->tf_ss = _udatasel; load_ds(_udatasel); td->td_pcb->pcb_ds = _udatasel; load_es(_udatasel); td->td_pcb->pcb_es = _udatasel; /* leave user %fs and %gs untouched */ PROC_LOCK(p); mtx_lock(&psp->ps_mtx); } /* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * state to gain improper privileges. */ #ifdef COMPAT_FREEBSD4 /* * MPSAFE */ int freebsd4_freebsd32_sigreturn(td, uap) struct thread *td; struct freebsd4_freebsd32_sigreturn_args /* { const struct freebsd4_freebsd32_ucontext *sigcntxp; } */ *uap; { struct ia32_ucontext4 uc; struct proc *p = td->td_proc; struct trapframe *regs; const struct ia32_ucontext4 *ucp; int cs, eflags, error; error = copyin(uap->sigcntxp, &uc, sizeof(uc)); if (error != 0) return (error); ucp = &uc; regs = td->td_frame; eflags = ucp->uc_mcontext.mc_eflags; /* * Don't allow users to change privileged or reserved flags. */ /* * XXX do allow users to change the privileged flag PSL_RF. * The cpu sets PSL_RF in tf_eflags for faults. Debuggers * should sometimes set it there too. tf_eflags is kept in * the signal context during signal handling and there is no * other place to remember it, so the PSL_RF bit may be * corrupted by the signal handler without us knowing. * Corruption of the PSL_RF bit at worst causes one more or * one less debugger trap, so allowing it is fairly harmless. */ if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { printf("freebsd4_freebsd32_sigreturn: eflags = 0x%x\n", eflags); return (EINVAL); } /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("freebsd4_sigreturn: cs = 0x%x\n", cs); trapsignal(td, SIGBUS, T_PROTFLT); return (EINVAL); } /* Segment selectors restored by sigtramp.S */ regs->tf_rdi = ucp->uc_mcontext.mc_edi; regs->tf_rsi = ucp->uc_mcontext.mc_esi; regs->tf_rbp = ucp->uc_mcontext.mc_ebp; regs->tf_rbx = ucp->uc_mcontext.mc_ebx; regs->tf_rdx = ucp->uc_mcontext.mc_edx; regs->tf_rcx = ucp->uc_mcontext.mc_ecx; regs->tf_rax = ucp->uc_mcontext.mc_eax; regs->tf_trapno = ucp->uc_mcontext.mc_trapno; regs->tf_err = ucp->uc_mcontext.mc_err; regs->tf_rip = ucp->uc_mcontext.mc_eip; regs->tf_cs = cs; regs->tf_rflags = ucp->uc_mcontext.mc_eflags; regs->tf_rsp = ucp->uc_mcontext.mc_esp; regs->tf_ss = ucp->uc_mcontext.mc_ss; PROC_LOCK(p); td->td_sigmask = ucp->uc_sigmask; SIG_CANTMASK(td->td_sigmask); signotify(td); PROC_UNLOCK(p); return (EJUSTRETURN); } #endif /* COMPAT_FREEBSD4 */ /* * MPSAFE */ int freebsd32_sigreturn(td, uap) struct thread *td; struct freebsd32_sigreturn_args /* { const struct freebsd32_ucontext *sigcntxp; } */ *uap; { struct ia32_ucontext uc; struct proc *p = td->td_proc; struct trapframe *regs; const struct ia32_ucontext *ucp; int cs, eflags, error, ret; error = copyin(uap->sigcntxp, &uc, sizeof(uc)); if (error != 0) return (error); ucp = &uc; regs = td->td_frame; eflags = ucp->uc_mcontext.mc_eflags; /* * Don't allow users to change privileged or reserved flags. */ /* * XXX do allow users to change the privileged flag PSL_RF. * The cpu sets PSL_RF in tf_eflags for faults. Debuggers * should sometimes set it there too. tf_eflags is kept in * the signal context during signal handling and there is no * other place to remember it, so the PSL_RF bit may be * corrupted by the signal handler without us knowing. * Corruption of the PSL_RF bit at worst causes one more or * one less debugger trap, so allowing it is fairly harmless. */ if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) { printf("freebsd32_sigreturn: eflags = 0x%x\n", eflags); return (EINVAL); } /* * Don't allow users to load a valid privileged %cs. Let the * hardware check for invalid selectors, excess privilege in * other selectors, invalid %eip's and invalid %esp's. */ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("sigreturn: cs = 0x%x\n", cs); trapsignal(td, SIGBUS, T_PROTFLT); return (EINVAL); } ret = ia32_set_fpcontext(td, &ucp->uc_mcontext); if (ret != 0) return (ret); /* Segment selectors restored by sigtramp.S */ regs->tf_rdi = ucp->uc_mcontext.mc_edi; regs->tf_rsi = ucp->uc_mcontext.mc_esi; regs->tf_rbp = ucp->uc_mcontext.mc_ebp; regs->tf_rbx = ucp->uc_mcontext.mc_ebx; regs->tf_rdx = ucp->uc_mcontext.mc_edx; regs->tf_rcx = ucp->uc_mcontext.mc_ecx; regs->tf_rax = ucp->uc_mcontext.mc_eax; regs->tf_trapno = ucp->uc_mcontext.mc_trapno; regs->tf_err = ucp->uc_mcontext.mc_err; regs->tf_rip = ucp->uc_mcontext.mc_eip; regs->tf_cs = cs; regs->tf_rflags = ucp->uc_mcontext.mc_eflags; regs->tf_rsp = ucp->uc_mcontext.mc_esp; regs->tf_ss = ucp->uc_mcontext.mc_ss; PROC_LOCK(p); td->td_sigmask = ucp->uc_sigmask; SIG_CANTMASK(td->td_sigmask); signotify(td); PROC_UNLOCK(p); return (EJUSTRETURN); } /* * Clear registers on exec */ void ia32_setregs(td, entry, stack, ps_strings) struct thread *td; u_long entry; u_long stack; u_long ps_strings; { struct trapframe *regs = td->td_frame; struct pcb *pcb = td->td_pcb; wrmsr(MSR_FSBASE, 0); wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */ pcb->pcb_fsbase = 0; pcb->pcb_gsbase = 0; load_ds(_udatasel); load_es(_udatasel); load_fs(_udatasel); load_gs(_udatasel); pcb->pcb_ds = _udatasel; pcb->pcb_es = _udatasel; pcb->pcb_fs = _udatasel; pcb->pcb_gs = _udatasel; bzero((char *)regs, sizeof(struct trapframe)); regs->tf_rip = entry; regs->tf_rsp = stack; regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); regs->tf_ss = _udatasel; regs->tf_cs = _ucode32sel; regs->tf_rbx = ps_strings; load_cr0(rcr0() | CR0_MP | CR0_TS); fpstate_drop(td); /* Return via doreti so that we can change to a different %cs */ pcb->pcb_flags |= PCB_FULLCTX; td->td_retval[1] = 0; } Index: stable/6/sys/compat/freebsd32/syscalls.master =================================================================== --- stable/6/sys/compat/freebsd32/syscalls.master (revision 169231) +++ stable/6/sys/compat/freebsd32/syscalls.master (revision 169232) @@ -1,752 +1,753 @@ $FreeBSD$ ; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94 ; from: src/sys/kern/syscalls.master 1.107 ; ; System call name/number master file. ; Processed to created init_sysent.c, syscalls.c and syscall.h. ; Columns: number [M]type nargs name alt{name,tag,rtyp}/comments ; number system call number, must be in order ; audit the audit event associated with the system call ; A value of AUE_NULL means no auditing, but it also means that ; there is no audit event for the call at this time. For the ; case where the event exists, but we don't want auditing, the ; event should be #defined to AUE_NULL in audit_kevents.h. ; type one of [M]STD, [M]OBSOL, [M]UNIMPL, [M]COMPAT, [M]CPT_NOA, ; [M]LIBCOMPAT, [M]NODEF, [M]NOARGS, [M]NOPROTO, [M]NOIMPL, ; [M]NOSTD ; name psuedo-prototype of syscall routine ; If one of the following alts is different, then all appear: ; altname name of system call if different ; alttag name of args struct tag if different from [o]`name'"_args" ; altrtyp return type if not int (bogus - syscalls always return int) ; for UNIMPL/OBSOL, name continues with comments ; types: ; [M] e.g. like MSTD -- means the system call is MP-safe. If no ; M prefix is used, the syscall wrapper will obtain the Giant ; lock for the syscall. ; STD always included ; COMPAT included on COMPAT #ifdef ; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h ; OBSOL obsolete, not included in system, only specifies name ; UNIMPL not implemented, placeholder only ; NOSTD implemented but as a lkm that can be statically ; compiled in sysent entry will be filled with lkmsys ; so the SYSCALL_MODULE macro works ; #ifdef's, etc. may be included, and are copied to the output files. #include #include #include #include #include #include ; Reserved/unimplemented system calls in the range 0-150 inclusive ; are reserved for use in future Berkeley releases. ; Additional system calls implemented in vendor and other ; redistributions should be placed in the reserved range at the end ; of the current calls. 0 AUE_NULL MNOPROTO { int nosys(void); } syscall nosys_args int 1 AUE_EXIT MNOPROTO { void sys_exit(int rval); } exit \ sys_exit_args void 2 AUE_FORK MNOPROTO { int fork(void); } 3 AUE_READ MNOPROTO { ssize_t read(int fd, void *buf, \ size_t nbyte); } 4 AUE_WRITE MNOPROTO { ssize_t write(int fd, const void *buf, \ size_t nbyte); } 5 AUE_OPEN_RWTC MNOPROTO { int open(char *path, int flags, \ int mode); } 6 AUE_CLOSE MNOPROTO { int close(int fd); } 7 AUE_WAIT4 MSTD { int freebsd32_wait4(int pid, int *status, \ int options, struct rusage32 *rusage); } 8 AUE_CREAT OBSOL old creat 9 AUE_LINK MNOPROTO { int link(char *path, char *link); } 10 AUE_UNLINK MNOPROTO { int unlink(char *path); } 11 AUE_NULL OBSOL execv 12 AUE_CHDIR MNOPROTO { int chdir(char *path); } 13 AUE_FCHDIR MNOPROTO { int fchdir(int fd); } 14 AUE_MKNOD MNOPROTO { int mknod(char *path, int mode, int dev); } 15 AUE_CHMOD MNOPROTO { int chmod(char *path, int mode); } 16 AUE_CHOWN MNOPROTO { int chown(char *path, int uid, int gid); } 17 AUE_NULL MNOPROTO { int obreak(char *nsize); } break \ obreak_args int 18 AUE_GETFSSTAT MCOMPAT4 { int freebsd32_getfsstat( \ struct statfs32 *buf, long bufsize, \ int flags); } 19 AUE_LSEEK OBSOL olseek 20 AUE_GETPID MNOPROTO { pid_t getpid(void); } 21 AUE_MOUNT NOPROTO { int mount(char *type, char *path, \ int flags, caddr_t data); } 22 AUE_UMOUNT NOPROTO { int unmount(char *path, int flags); } 23 AUE_SETUID MNOPROTO { int setuid(uid_t uid); } 24 AUE_GETUID MNOPROTO { uid_t getuid(void); } 25 AUE_GETEUID MNOPROTO { uid_t geteuid(void); } 26 AUE_PTRACE MNOPROTO { int ptrace(int req, pid_t pid, \ caddr_t addr, int data); } ; XXX implement 27 AUE_RECVMSG MSTD { int freebsd32_recvmsg(int s, struct msghdr32 *msg, \ int flags); } 28 AUE_SENDMSG MSTD { int freebsd32_sendmsg(int s, struct msghdr32 *msg, \ int flags); } 29 AUE_RECVFROM MSTD { int freebsd32_recvfrom(int s, u_int32_t buf, \ u_int32_t len, int flags, u_int32_t from, \ u_int32_t fromlenaddr); } 30 AUE_ACCEPT MNOPROTO { int accept(int s, caddr_t name, \ int *anamelen); } 31 AUE_GETPEERNAME MNOPROTO { int getpeername(int fdes, caddr_t asa, \ int *alen); } 32 AUE_GETSOCKNAME MNOPROTO { int getsockname(int fdes, caddr_t asa, \ int *alen); } 33 AUE_ACCESS MNOPROTO { int access(char *path, int flags); } 34 AUE_CHFLAGS MNOPROTO { int chflags(char *path, int flags); } 35 AUE_FCHFLAGS MNOPROTO { int fchflags(int fd, int flags); } 36 AUE_SYNC MNOPROTO { int sync(void); } 37 AUE_KILL MNOPROTO { int kill(int pid, int signum); } 38 AUE_STAT UNIMPL ostat 39 AUE_GETPPID MNOPROTO { pid_t getppid(void); } 40 AUE_LSTAT UNIMPL olstat 41 AUE_DUP MNOPROTO { int dup(u_int fd); } 42 AUE_PIPE MNOPROTO { int pipe(void); } 43 AUE_GETEGID MNOPROTO { gid_t getegid(void); } 44 AUE_PROFILE MNOPROTO { int profil(caddr_t samples, size_t size, \ size_t offset, u_int scale); } 45 AUE_KTRACE MNOPROTO { int ktrace(const char *fname, int ops, \ int facs, int pid); } 46 AUE_SIGACTION MCOMPAT { int freebsd32_sigaction( int signum, \ struct osigaction32 *nsa, \ struct osigaction32 *osa); } 47 AUE_GETGID MNOPROTO { gid_t getgid(void); } 48 AUE_SIGPROCMASK MCOMPAT { int freebsd32_sigprocmask(int how, \ osigset_t mask); } 49 AUE_GETLOGIN MNOPROTO { int getlogin(char *namebuf, \ u_int namelen); } 50 AUE_SETLOGIN MNOPROTO { int setlogin(char *namebuf); } 51 AUE_ACCT MNOPROTO { int acct(char *path); } 52 AUE_SIGPENDING MCOMPAT { int freebsd32_sigpending(void); } 53 AUE_SIGALTSTACK MSTD { int freebsd32_sigaltstack( \ struct sigaltstack32 *ss, \ struct sigaltstack32 *oss); } 54 AUE_IOCTL MNOPROTO { int ioctl(int fd, u_long com, \ caddr_t data); } 55 AUE_REBOOT MNOPROTO { int reboot(int opt); } 56 AUE_REVOKE MNOPROTO { int revoke(char *path); } 57 AUE_SYMLINK MNOPROTO { int symlink(char *path, char *link); } 58 AUE_READLINK MNOPROTO { int readlink(char *path, char *buf, \ int count); } 59 AUE_EXECVE MSTD { int freebsd32_execve(char *fname, \ u_int32_t *argv, u_int32_t *envv); } 60 AUE_UMASK MNOPROTO { int umask(int newmask); } umask \ umask_args int 61 AUE_CHROOT MNOPROTO { int chroot(char *path); } 62 AUE_FSTAT OBSOL ofstat 63 AUE_NULL OBSOL ogetkerninfo 64 AUE_NULL OBSOL ogetpagesize ; XXX implement (not OBSOL at all) 65 AUE_MSYNC MNOPROTO { int msync(void *addr, size_t len, \ int flags); } 66 AUE_VFORK MNOPROTO { int vfork(void); } 67 AUE_NULL OBSOL vread 68 AUE_NULL OBSOL vwrite 69 AUE_SBRK MNOPROTO { int sbrk(int incr); } 70 AUE_SSTK MNOPROTO { int sstk(int incr); } 71 AUE_MMAP OBSOL ommap 72 AUE_O_VADVISE MNOPROTO { int ovadvise(int anom); } vadvise \ ovadvise_args int 73 AUE_MUNMAP MNOPROTO { int munmap(void *addr, size_t len); } 74 AUE_MPROTECT MNOPROTO { int mprotect(const void *addr, \ size_t len, int prot); } 75 AUE_MADVISE MNOPROTO { int madvise(void *addr, size_t len, \ int behav); } 76 AUE_NULL OBSOL vhangup 77 AUE_NULL OBSOL vlimit 78 AUE_MINCORE MNOPROTO { int mincore(const void *addr, size_t len, \ char *vec); } 79 AUE_GETGROUPS MNOPROTO { int getgroups(u_int gidsetsize, \ gid_t *gidset); } 80 AUE_SETGROUPS MNOPROTO { int setgroups(u_int gidsetsize, \ gid_t *gidset); } 81 AUE_GETPGRP MNOPROTO { int getpgrp(void); } 82 AUE_SETPGRP MNOPROTO { int setpgid(int pid, int pgid); } 83 AUE_SETITIMER MSTD { int freebsd32_setitimer(u_int which, \ struct itimerval32 *itv, \ struct itimerval32 *oitv); } 84 AUE_NULL OBSOL owait ; XXX implement 85 AUE_SWAPON OBSOL oswapon 86 AUE_GETITIMER MSTD { int freebsd32_getitimer(u_int which, \ struct itimerval32 *itv); } 87 AUE_O_GETHOSTNAME OBSOL ogethostname 88 AUE_O_SETHOSTNAME OBSOL osethostname 89 AUE_GETDTABLESIZE MNOPROTO { int getdtablesize(void); } 90 AUE_DUP2 MNOPROTO { int dup2(u_int from, u_int to); } 91 AUE_NULL UNIMPL getdopt 92 AUE_FCNTL MNOPROTO { int fcntl(int fd, int cmd, long arg); } 93 AUE_SELECT MSTD { int freebsd32_select(int nd, fd_set *in, \ fd_set *ou, fd_set *ex, \ struct timeval32 *tv); } ; XXX need to override for big-endian - little-endian should work fine. 94 AUE_NULL UNIMPL setdopt 95 AUE_FSYNC MNOPROTO { int fsync(int fd); } 96 AUE_SETPRIORITY MNOPROTO { int setpriority(int which, int who, \ int prio); } 97 AUE_SOCKET MNOPROTO { int socket(int domain, int type, \ int protocol); } 98 AUE_CONNECT MNOPROTO { int connect(int s, caddr_t name, \ int namelen); } 99 AUE_NULL OBSOL oaccept 100 AUE_GETPRIORITY MNOPROTO { int getpriority(int which, int who); } 101 AUE_NULL OBSOL osend 102 AUE_NULL OBSOL orecv 103 AUE_NULL OBSOL osigreturn 104 AUE_BIND MNOPROTO { int bind(int s, caddr_t name, \ int namelen); } 105 AUE_SETSOCKOPT MNOPROTO { int setsockopt(int s, int level, \ int name, caddr_t val, int valsize); } 106 AUE_LISTEN MNOPROTO { int listen(int s, int backlog); } 107 AUE_NULL OBSOL vtimes 108 AUE_O_SIGVEC MCOMPAT { int freebsd32_sigvec(int signum, \ struct sigvec32 *nsv, \ struct sigvec32 *osv); } 109 AUE_O_SIGBLOCK MCOMPAT { int freebsd32_sigblock(int mask); } 110 AUE_O_SIGSETMASK MCOMPAT { int freebsd32_sigsetmask( int mask); } 111 AUE_SIGSUSPEND MCOMPAT { int freebsd32_sigsuspend( int mask); } 112 AUE_O_SIGSTACK MCOMPAT { int freebsd32_sigstack( \ struct sigstack32 *nss, \ struct sigstack32 *oss); } 113 AUE_NULL OBSOL orecvmsg 114 AUE_NULL OBSOL osendmsg 115 AUE_NULL OBSOL vtrace 116 AUE_GETTIMEOFDAY MSTD { int freebsd32_gettimeofday( \ struct timeval32 *tp, \ struct timezone *tzp); } 117 AUE_GETRUSAGE MSTD { int freebsd32_getrusage(int who, \ struct rusage32 *rusage); } 118 AUE_GETSOCKOPT MNOPROTO { int getsockopt(int s, int level, \ int name, caddr_t val, int *avalsize); } 119 AUE_NULL UNIMPL resuba (BSD/OS 2.x) 120 AUE_READV MSTD { int freebsd32_readv(int fd, \ struct iovec32 *iovp, u_int iovcnt); } 121 AUE_WRITEV MSTD { int freebsd32_writev(int fd, \ struct iovec32 *iovp, u_int iovcnt); } 122 AUE_SETTIMEOFDAY MSTD { int freebsd32_settimeofday( \ struct timeval32 *tv, \ struct timezone *tzp); } 123 AUE_FCHOWN MNOPROTO { int fchown(int fd, int uid, int gid); } 124 AUE_FCHMOD MNOPROTO { int fchmod(int fd, int mode); } 125 AUE_RECVFROM OBSOL orecvfrom 126 AUE_SETREUID MNOPROTO { int setreuid(int ruid, int euid); } 127 AUE_SETREGID MNOPROTO { int setregid(int rgid, int egid); } 128 AUE_RENAME MNOPROTO { int rename(char *from, char *to); } 129 AUE_TRUNCATE OBSOL otruncate 130 AUE_FTRUNCATE OBSOL ftruncate 131 AUE_FLOCK MNOPROTO { int flock(int fd, int how); } 132 AUE_MKFIFO MNOPROTO { int mkfifo(char *path, int mode); } 133 AUE_SENDTO MNOPROTO { int sendto(int s, caddr_t buf, \ size_t len, int flags, caddr_t to, \ int tolen); } 134 AUE_SHUTDOWN MNOPROTO { int shutdown(int s, int how); } 135 AUE_SOCKETPAIR MNOPROTO { int socketpair(int domain, int type, \ int protocol, int *rsv); } 136 AUE_MKDIR MNOPROTO { int mkdir(char *path, int mode); } 137 AUE_RMDIR MNOPROTO { int rmdir(char *path); } 138 AUE_UTIMES MSTD { int freebsd32_utimes(char *path, \ struct timeval32 *tptr); } 139 AUE_NULL OBSOL 4.2 sigreturn 140 AUE_ADJTIME MSTD { int freebsd32_adjtime( \ struct timeval32 *delta, \ struct timeval32 *olddelta); } 141 AUE_GETPEERNAME OBSOL ogetpeername 142 AUE_SYSCTL OBSOL ogethostid 143 AUE_SYSCTL OBSOL sethostid 144 AUE_GETRLIMIT OBSOL getrlimit 145 AUE_SETRLIMIT OBSOL setrlimit 146 AUE_KILLPG OBSOL killpg 147 AUE_SETSID MNOPROTO { int setsid(void); } 148 AUE_QUOTACTL MNOPROTO { int quotactl(char *path, int cmd, int uid, \ caddr_t arg); } 149 AUE_O_QUOTA OBSOL oquota 150 AUE_GETSOCKNAME OBSOL ogetsockname ; Syscalls 151-180 inclusive are reserved for vendor-specific ; system calls. (This includes various calls added for compatibity ; with other Unix variants.) ; Some of these calls are now supported by BSD... 151 AUE_NULL UNIMPL sem_lock (BSD/OS 2.x) 152 AUE_NULL UNIMPL sem_wakeup (BSD/OS 2.x) 153 AUE_NULL UNIMPL asyncdaemon (BSD/OS 2.x) 154 AUE_NULL UNIMPL nosys ; 155 is initialized by the NFS code, if present. ; XXX this is a problem!!! 155 AUE_NFS_SVC UNIMPL nfssvc 156 AUE_GETDIRENTRIES OBSOL ogetdirentries 157 AUE_STATFS MCOMPAT4 { int freebsd32_statfs(char *path, \ struct statfs32 *buf); } 158 AUE_FSTATFS MCOMPAT4 { int freebsd32_fstatfs(int fd, \ struct statfs32 *buf); } 159 AUE_NULL UNIMPL nosys 160 AUE_NULL UNIMPL nosys 161 AUE_NFS_GETFH MNOPROTO { int getfh(char *fname, \ struct fhandle *fhp); } 162 AUE_SYSCTL MNOPROTO { int getdomainname(char *domainname, \ int len); } 163 AUE_SYSCTL MNOPROTO { int setdomainname(char *domainname, \ int len); } 164 AUE_NULL MNOPROTO { int uname(struct utsname *name); } 165 AUE_SYSARCH MNOPROTO { int sysarch(int op, char *parms); } 166 AUE_RTPRIO MNOPROTO { int rtprio(int function, pid_t pid, \ struct rtprio *rtp); } 167 AUE_NULL UNIMPL nosys 168 AUE_NULL UNIMPL nosys 169 AUE_SEMSYS MSTD { int freebsd32_semsys(int which, int a2, \ int a3, int a4, int a5); } 170 AUE_MSGSYS MSTD { int freebsd32_msgsys(int which, int a2, \ int a3, int a4, int a5, int a6); } 171 AUE_SHMSYS MSTD { int freebsd32_shmsys(int which, uint32_t a2, \ uint32_t a3, uint32_t a4); } 172 AUE_NULL UNIMPL nosys 173 AUE_PREAD MSTD { ssize_t freebsd32_pread(int fd, void *buf, \ size_t nbyte, int pad, \ u_int32_t offsetlo, u_int32_t offsethi); } ; XXX note - bigendian is different 174 AUE_PWRITE MSTD { ssize_t freebsd32_pwrite(int fd, \ const void *buf, size_t nbyte, int pad, \ u_int32_t offsetlo, u_int32_t offsethi); } ; XXX note - bigendian is different 175 AUE_NULL UNIMPL nosys 176 AUE_NTP_ADJTIME MNOPROTO { int ntp_adjtime(struct timex *tp); } 177 AUE_NULL UNIMPL sfork (BSD/OS 2.x) 178 AUE_NULL UNIMPL getdescriptor (BSD/OS 2.x) 179 AUE_NULL UNIMPL setdescriptor (BSD/OS 2.x) 180 AUE_NULL UNIMPL nosys ; Syscalls 181-199 are used by/reserved for BSD 181 AUE_SETGID MNOPROTO { int setgid(gid_t gid); } 182 AUE_SETEGID MNOPROTO { int setegid(gid_t egid); } 183 AUE_SETEUID MNOPROTO { int seteuid(uid_t euid); } 184 AUE_NULL UNIMPL lfs_bmapv 185 AUE_NULL UNIMPL lfs_markv 186 AUE_NULL UNIMPL lfs_segclean 187 AUE_NULL UNIMPL lfs_segwait 188 AUE_STAT MSTD { int freebsd32_stat(char *path, \ struct stat32 *ub); } 189 AUE_FSTAT MSTD { int freebsd32_fstat(int fd, \ struct stat32 *ub); } 190 AUE_LSTAT MSTD { int freebsd32_lstat(char *path, \ struct stat32 *ub); } 191 AUE_PATHCONF MNOPROTO { int pathconf(char *path, int name); } 192 AUE_FPATHCONF MNOPROTO { int fpathconf(int fd, int name); } 193 AUE_NULL UNIMPL nosys 194 AUE_GETRLIMIT MNOPROTO { int getrlimit(u_int which, \ struct rlimit *rlp); } getrlimit \ __getrlimit_args int 195 AUE_SETRLIMIT MNOPROTO { int setrlimit(u_int which, \ struct rlimit *rlp); } setrlimit \ __setrlimit_args int 196 AUE_GETDIRENTRIES MNOPROTO { int getdirentries(int fd, char *buf, \ u_int count, long *basep); } 197 AUE_MMAP MSTD { caddr_t freebsd32_mmap(caddr_t addr, \ size_t len, int prot, int flags, int fd, \ int pad, u_int32_t poslo, \ u_int32_t poshi); } 198 AUE_NULL MNOPROTO { int nosys(void); } __syscall \ __syscall_args int ; XXX note - bigendian is different 199 AUE_LSEEK MSTD { off_t freebsd32_lseek(int fd, int pad, \ u_int32_t offsetlo, u_int32_t offsethi, \ int whence); } ; XXX note - bigendian is different 200 AUE_TRUNCATE MSTD { int freebsd32_truncate(char *path, \ int pad, u_int32_t lengthlo, \ u_int32_t lengthhi); } ; XXX note - bigendian is different 201 AUE_FTRUNCATE MSTD { int freebsd32_ftruncate(int fd, int pad, \ u_int32_t lengthlo, u_int32_t lengthhi); } 202 AUE_SYSCTL MSTD { int freebsd32_sysctl(int *name, \ u_int namelen, void *old, \ u_int32_t *oldlenp, void *new, \ u_int32_t newlen); } 203 AUE_MLOCK MNOPROTO { int mlock(const void *addr, \ size_t len); } 204 AUE_MUNLOCK MNOPROTO { int munlock(const void *addr, \ size_t len); } 205 AUE_UNDELETE MNOPROTO { int undelete(char *path); } 206 AUE_FUTIMES MSTD { int freebsd32_futimes(int fd, \ struct timeval32 *tptr); } 207 AUE_GETPGID MNOPROTO { int getpgid(pid_t pid); } 208 AUE_NULL UNIMPL newreboot (NetBSD) 209 AUE_POLL MNOPROTO { int poll(struct pollfd *fds, u_int nfds, \ int timeout); } ; ; The following are reserved for loadable syscalls ; 210 AUE_NULL UNIMPL 211 AUE_NULL UNIMPL 212 AUE_NULL UNIMPL 213 AUE_NULL UNIMPL 214 AUE_NULL UNIMPL 215 AUE_NULL UNIMPL 216 AUE_NULL UNIMPL 217 AUE_NULL UNIMPL 218 AUE_NULL UNIMPL 219 AUE_NULL UNIMPL ; ; The following were introduced with NetBSD/4.4Lite-2 ; They are initialized by thier respective modules/sysinits ; XXX PROBLEM!! 220 AUE_SEMCTL MNOPROTO { int __semctl(int semid, int semnum, \ int cmd, union semun *arg); } 221 AUE_SEMGET MNOPROTO { int semget(key_t key, int nsems, \ int semflg); } 222 AUE_SEMOP MNOPROTO { int semop(int semid, struct sembuf *sops, \ u_int nsops); } 223 AUE_NULL UNIMPL semconfig 224 AUE_MSGCTL MNOPROTO { int msgctl(int msqid, int cmd, \ struct msqid_ds *buf); } 225 AUE_MSGGET MNOPROTO { int msgget(key_t key, int msgflg); } 226 AUE_MSGSND MNOPROTO { int msgsnd(int msqid, void *msgp, \ size_t msgsz, int msgflg); } 227 AUE_MSGRCV MNOPROTO { int msgrcv(int msqid, void *msgp, \ size_t msgsz, long msgtyp, int msgflg); } 228 AUE_SHMAT MNOPROTO { int shmat(int shmid, void *shmaddr, \ int shmflg); } 229 AUE_SHMCTL MSTD { int freebsd32_shmctl(int shmid, int cmd, \ struct shmid_ds32 *buf); } 230 AUE_SHMDT MNOPROTO { int shmdt(void *shmaddr); } 231 AUE_SHMGET MNOPROTO { int shmget(key_t key, int size, \ int shmflg); } ; 232 AUE_NULL MSTD { int freebsd32_clock_gettime(clockid_t clock_id, \ struct timespec32 *tp); } 233 AUE_CLOCK_SETTIME MSTD { int freebsd32_clock_settime(clockid_t clock_id, \ const struct timespec32 *tp); } 234 AUE_NULL MSTD { int freebsd32_clock_getres(clockid_t clock_id, \ struct timespec32 *tp); } 235 AUE_NULL UNIMPL timer_create 236 AUE_NULL UNIMPL timer_delete 237 AUE_NULL UNIMPL timer_settime 238 AUE_NULL UNIMPL timer_gettime 239 AUE_NULL UNIMPL timer_getoverrun 240 AUE_NULL MSTD { int freebsd32_nanosleep( \ const struct timespec32 *rqtp, \ struct timespec32 *rmtp); } 241 AUE_NULL UNIMPL nosys 242 AUE_NULL UNIMPL nosys 243 AUE_NULL UNIMPL nosys 244 AUE_NULL UNIMPL nosys 245 AUE_NULL UNIMPL nosys 246 AUE_NULL UNIMPL nosys 247 AUE_NULL UNIMPL nosys 248 AUE_NULL UNIMPL ntp_gettime 249 AUE_NULL UNIMPL nosys ; syscall numbers initially used in OpenBSD 250 AUE_MINHERIT MNOPROTO { int minherit(void *addr, size_t len, \ int inherit); } 251 AUE_RFORK MNOPROTO { int rfork(int flags); } 252 AUE_POLL MNOPROTO { int openbsd_poll(struct pollfd *fds, \ u_int nfds, int timeout); } 253 AUE_ISSETUGID MNOPROTO { int issetugid(void); } 254 AUE_LCHOWN MNOPROTO { int lchown(char *path, int uid, int gid); } 255 AUE_NULL UNIMPL nosys 256 AUE_NULL UNIMPL nosys 257 AUE_NULL UNIMPL nosys 258 AUE_NULL UNIMPL nosys 259 AUE_NULL UNIMPL nosys 260 AUE_NULL UNIMPL nosys 261 AUE_NULL UNIMPL nosys 262 AUE_NULL UNIMPL nosys 263 AUE_NULL UNIMPL nosys 264 AUE_NULL UNIMPL nosys 265 AUE_NULL UNIMPL nosys 266 AUE_NULL UNIMPL nosys 267 AUE_NULL UNIMPL nosys 268 AUE_NULL UNIMPL nosys 269 AUE_NULL UNIMPL nosys 270 AUE_NULL UNIMPL nosys 271 AUE_NULL UNIMPL nosys 272 AUE_O_GETDENTS MNOPROTO { int getdents(int fd, char *buf, \ size_t count); } 273 AUE_NULL UNIMPL nosys 274 AUE_LCHMOD MNOPROTO { int lchmod(char *path, mode_t mode); } 275 AUE_LCHOWN MNOPROTO { int lchown(char *path, uid_t uid, \ gid_t gid); } netbsd_lchown \ lchown_args int 276 AUE_LUTIMES MSTD { int freebsd32_lutimes(char *path, \ struct timeval32 *tptr); } 277 AUE_MSYNC MNOPROTO { int msync(void *addr, size_t len, \ int flags); } netbsd_msync msync_args int 278 AUE_STAT MNOPROTO { int nstat(char *path, struct nstat *ub); } 279 AUE_FSTAT MNOPROTO { int nfstat(int fd, struct nstat *sb); } 280 AUE_LSTAT MNOPROTO { int nlstat(char *path, struct nstat *ub); } 281 AUE_NULL UNIMPL nosys 282 AUE_NULL UNIMPL nosys 283 AUE_NULL UNIMPL nosys 284 AUE_NULL UNIMPL nosys 285 AUE_NULL UNIMPL nosys 286 AUE_NULL UNIMPL nosys 287 AUE_NULL UNIMPL nosys 288 AUE_NULL UNIMPL nosys ; 289 and 290 from NetBSD (OpenBSD: 267 and 268) 289 AUE_PREADV MSTD { ssize_t freebsd32_preadv(int fd, \ struct iovec32 *iovp, \ u_int iovcnt, off_t offset); } ; XXX note - bigendian is different 290 AUE_PWRITEV MSTD { ssize_t freebsd32_pwritev(int fd, \ struct iovec32 *iovp, \ u_int iovcnt, off_t offset); } ; XXX note - bigendian is different 291 AUE_NULL UNIMPL nosys 292 AUE_NULL UNIMPL nosys 293 AUE_NULL UNIMPL nosys 294 AUE_NULL UNIMPL nosys 295 AUE_NULL UNIMPL nosys 296 AUE_NULL UNIMPL nosys ; XXX 297 is 300 in NetBSD 297 AUE_FHSTATFS MCOMPAT4 { int freebsd32_fhstatfs( \ const struct fhandle *u_fhp, \ struct statfs32 *buf); } 298 AUE_FHOPEN MNOPROTO { int fhopen(const struct fhandle *u_fhp, \ int flags); } 299 AUE_FHSTAT MNOPROTO { int fhstat(const struct fhandle *u_fhp, \ struct stat *sb); } ; syscall numbers for FreeBSD 300 AUE_NULL MNOPROTO { int modnext(int modid); } 301 AUE_NULL MSTD { int freebsd32_modstat(int modid, \ struct module_stat32* stat); } 302 AUE_NULL MNOPROTO { int modfnext(int modid); } 303 AUE_NULL MNOPROTO { int modfind(const char *name); } 304 AUE_MODLOAD MNOPROTO { int kldload(const char *file); } 305 AUE_MODUNLOAD MNOPROTO { int kldunload(int fileid); } 306 AUE_NULL MNOPROTO { int kldfind(const char *file); } 307 AUE_NULL MNOPROTO { int kldnext(int fileid); } 308 AUE_NULL MNOPROTO { int kldstat(int fileid, \ struct kld_file_stat* stat); } 309 AUE_NULL MNOPROTO { int kldfirstmod(int fileid); } 310 AUE_GETSID MNOPROTO { int getsid(pid_t pid); } 311 AUE_SETRESUID MNOPROTO { int setresuid(uid_t ruid, uid_t euid, \ uid_t suid); } 312 AUE_SETRESGID MNOPROTO { int setresgid(gid_t rgid, gid_t egid, \ gid_t sgid); } 313 AUE_NULL OBSOL signanosleep 314 AUE_NULL UNIMPL aio_return 315 AUE_NULL UNIMPL aio_suspend 316 AUE_NULL UNIMPL aio_cancel 317 AUE_NULL UNIMPL aio_error 318 AUE_NULL UNIMPL aio_read 319 AUE_NULL UNIMPL aio_write 320 AUE_NULL UNIMPL lio_listio 321 AUE_NULL MNOPROTO { int yield(void); } 322 AUE_NULL OBSOL thr_sleep 323 AUE_NULL OBSOL thr_wakeup 324 AUE_MLOCKALL MNOPROTO { int mlockall(int how); } 325 AUE_MUNLOCKALL MNOPROTO { int munlockall(void); } 326 AUE_GETCWD MNOPROTO { int __getcwd(u_char *buf, u_int buflen); } 327 AUE_NULL MNOPROTO { int sched_setparam (pid_t pid, \ const struct sched_param *param); } 328 AUE_NULL MNOPROTO { int sched_getparam (pid_t pid, \ struct sched_param *param); } 329 AUE_NULL MNOPROTO { int sched_setscheduler (pid_t pid, \ int policy, \ const struct sched_param *param); } 330 AUE_NULL MNOPROTO { int sched_getscheduler (pid_t pid); } 331 AUE_NULL MNOPROTO { int sched_yield (void); } 332 AUE_NULL MNOPROTO { int sched_get_priority_max (int policy); } 333 AUE_NULL MNOPROTO { int sched_get_priority_min (int policy); } 334 AUE_NULL MNOPROTO { int sched_rr_get_interval (pid_t pid, \ struct timespec *interval); } 335 AUE_NULL MNOPROTO { int utrace(const void *addr, size_t len); } ; XXX note - bigendian is different 336 AUE_SENDFILE MCOMPAT4 { int freebsd32_sendfile(int fd, int s, \ u_int32_t offsetlo, u_int32_t offsethi, \ size_t nbytes, struct sf_hdtr32 *hdtr, \ off_t *sbytes, int flags); } 337 AUE_NULL MNOPROTO { int kldsym(int fileid, int cmd, \ void *data); } 338 AUE_JAIL MNOPROTO { int jail(struct jail *jail); } 339 AUE_NULL UNIMPL pioctl 340 AUE_SIGPROCMASK MNOPROTO { int sigprocmask(int how, \ const sigset_t *set, sigset_t *oset); } 341 AUE_SIGSUSPEND MNOPROTO { int sigsuspend(const sigset_t *sigmask); } 342 AUE_SIGACTION MCOMPAT4 { int freebsd32_sigaction(int sig, \ struct sigaction32 *act, \ struct sigaction32 *oact); } 343 AUE_SIGPENDING MNOPROTO { int sigpending(sigset_t *set); } 344 AUE_SIGRETURN MCOMPAT4 { int freebsd32_sigreturn( \ const struct freebsd4_freebsd32_ucontext *sigcntxp); } ; XXX implement 345 AUE_SIGWAIT UNIMPL sigtimedwait ; XXX implement 346 AUE_NULL UNIMPL sigwaitinfo 347 AUE_NULL MNOPROTO { int __acl_get_file(const char *path, \ acl_type_t type, struct acl *aclp); } 348 AUE_NULL MNOPROTO { int __acl_set_file(const char *path, \ acl_type_t type, struct acl *aclp); } 349 AUE_NULL MNOPROTO { int __acl_get_fd(int filedes, \ acl_type_t type, struct acl *aclp); } 350 AUE_NULL MNOPROTO { int __acl_set_fd(int filedes, \ acl_type_t type, struct acl *aclp); } 351 AUE_NULL MNOPROTO { int __acl_delete_file(const char *path, \ acl_type_t type); } 352 AUE_NULL MNOPROTO { int __acl_delete_fd(int filedes, \ acl_type_t type); } 353 AUE_NULL MNOPROTO { int __acl_aclcheck_file(const char *path, \ acl_type_t type, struct acl *aclp); } 354 AUE_NULL MNOPROTO { int __acl_aclcheck_fd(int filedes, \ acl_type_t type, struct acl *aclp); } 355 AUE_EXTATTRCTL NOPROTO { int extattrctl(const char *path, int cmd, \ const char *filename, int attrnamespace, \ const char *attrname); } 356 AUE_EXTATTR_SET_FILE NOPROTO { int extattr_set_file( \ const char *path, int attrnamespace, \ const char *attrname, void *data, \ size_t nbytes); } 357 AUE_EXTATTR_GET_FILE NOPROTO { ssize_t extattr_get_file( \ const char *path, int attrnamespace, \ const char *attrname, void *data, \ size_t nbytes); } 358 AUE_EXTATTR_DELETE_FILE NOPROTO { int extattr_delete_file( \ const char *path, int attrnamespace, \ const char *attrname); } 359 AUE_NULL UNIMPL aio_waitcomplete 360 AUE_GETRESUID MNOPROTO { int getresuid(uid_t *ruid, uid_t *euid, \ uid_t *suid); } 361 AUE_GETRESGID MNOPROTO { int getresgid(gid_t *rgid, gid_t *egid, \ gid_t *sgid); } 362 AUE_KQUEUE MNOPROTO { int kqueue(void); } 363 AUE_NULL MSTD { int freebsd32_kevent(int fd, \ const struct kevent32 *changelist, \ int nchanges, \ struct kevent32 *eventlist, int nevents, \ const struct timespec32 *timeout); } 364 AUE_NULL UNIMPL __cap_get_proc 365 AUE_NULL UNIMPL __cap_set_proc 366 AUE_NULL UNIMPL __cap_get_fd 367 AUE_NULL UNIMPL __cap_get_file 368 AUE_NULL UNIMPL __cap_set_fd 369 AUE_NULL UNIMPL __cap_set_file 370 AUE_NULL UNIMPL lkmressys 371 AUE_EXTATTR_SET_FD NOPROTO { int extattr_set_fd(int fd, \ int attrnamespace, const char *attrname, \ void *data, size_t nbytes); } 372 AUE_EXTATTR_GET_FD NOPROTO { ssize_t extattr_get_fd(int fd, \ int attrnamespace, const char *attrname, \ void *data, size_t nbytes); } 373 AUE_EXTATTR_DELETE_FD NOPROTO { int extattr_delete_fd(int fd, \ int attrnamespace, \ const char *attrname); } 374 AUE_NULL MNOPROTO { int __setugid(int flag); } 375 AUE_NULL UNIMPL nfsclnt 376 AUE_EACCESS MNOPROTO { int eaccess(char *path, int flags); } 377 AUE_NULL UNIMPL afs_syscall 378 AUE_NMOUNT NOPROTO { int nmount(struct iovec *iovp, \ unsigned int iovcnt, int flags); } 379 AUE_NULL MNOPROTO { int kse_exit(void); } 380 AUE_NULL MNOPROTO { int kse_wakeup(struct kse_mailbox *mbx); } 381 AUE_NULL MNOPROTO { int kse_create(struct kse_mailbox *mbx, \ int newgroup); } 382 AUE_NULL MNOPROTO { int kse_thr_interrupt( \ struct kse_thr_mailbox *tmbx); } 383 AUE_NULL MNOPROTO { int kse_release(void); } 384 AUE_NULL UNIMPL __mac_get_proc 385 AUE_NULL UNIMPL __mac_set_proc 386 AUE_NULL UNIMPL __mac_get_fd 387 AUE_NULL UNIMPL __mac_get_file 388 AUE_NULL UNIMPL __mac_set_fd 389 AUE_NULL UNIMPL __mac_set_file 390 AUE_NULL MNOPROTO { int kenv(int what, const char *name, \ char *value, int len); } 391 AUE_LCHFLAGS MNOPROTO { int lchflags(const char *path, int flags); } 392 AUE_NULL MNOPROTO { int uuidgen(struct uuid *store, \ int count); } 393 AUE_SENDFILE MSTD { int freebsd32_sendfile(int fd, int s, \ u_int32_t offsetlo, u_int32_t offsethi, \ size_t nbytes, struct sf_hdtr32 *hdtr, \ off_t *sbytes, int flags); } 394 AUE_NULL UNIMPL mac_syscall 395 AUE_GETFSSTAT MNOPROTO { int getfsstat(struct statfs *buf, \ long bufsize, int flags); } 396 AUE_STATFS MNOPROTO { int statfs(char *path, \ struct statfs *buf); } 397 AUE_FSTATFS MNOPROTO { int fstatfs(int fd, struct statfs *buf); } 398 AUE_FHSTATFS MNOPROTO { int fhstatfs(const struct fhandle *u_fhp, \ struct statfs *buf); } 399 AUE_NULL UNIMPL nosys ; XXX implement these? 400 AUE_NULL UNIMPL ksem_close 401 AUE_NULL UNIMPL ksem_post 402 AUE_NULL UNIMPL ksem_wait 403 AUE_NULL UNIMPL ksem_trywait 404 AUE_NULL UNIMPL ksem_init 405 AUE_NULL UNIMPL ksem_open 406 AUE_NULL UNIMPL ksem_unlink 407 AUE_NULL UNIMPL ksem_getvalue 408 AUE_NULL UNIMPL ksem_destroy 409 AUE_NULL UNIMPL __mac_get_pid 410 AUE_NULL UNIMPL __mac_get_link 411 AUE_NULL UNIMPL __mac_set_link 412 AUE_EXTATTR_SET_LINK UNIMPL extattr_set_link 413 AUE_EXTATTR_GET_LINK UNIMPL extattr_get_link 414 AUE_EXTATTR_DELETE_LINK UNIMPL extattr_delete_link 415 AUE_NULL UNIMPL __mac_execve 416 AUE_SIGACTION MSTD { int freebsd32_sigaction(int sig, \ struct sigaction32 *act, \ struct sigaction32 *oact); } 417 AUE_SIGRETURN MSTD { int freebsd32_sigreturn( \ const struct freebsd32_ucontext *sigcntxp); } 418 AUE_NULL UNIMPL __xstat 419 AUE_NULL UNIMPL __xfstat 420 AUE_NULL UNIMPL __xlstat -; XXX implement -421 AUE_NULL UNIMPL getcontext -; XXX implement -422 AUE_NULL UNIMPL setcontext -; XXX implement -423 AUE_NULL UNIMPL swapcontext +421 AUE_NULL STD { int freebsd32_getcontext( \ + struct freebsd32_ucontext *ucp); } +422 AUE_NULL STD { int freebsd32_setcontext( \ + const struct freebsd32_ucontext *ucp); } +423 AUE_NULL STD { int freebsd32_swapcontext( \ + struct freebsd32_ucontext *oucp, \ + const struct freebsd32_ucontext *ucp); } 424 AUE_SWAPOFF UNIMPL swapoff 425 AUE_NULL UNIMPL __acl_get_link 426 AUE_NULL UNIMPL __acl_set_link 427 AUE_NULL UNIMPL __acl_delete_link 428 AUE_NULL UNIMPL __acl_aclcheck_link ; XXX implement 429 AUE_SIGWAIT UNIMPL sigwait 430 AUE_NULL MNOPROTO { int thr_create(ucontext_t *ctx, long *id, \ int flag s); } 431 AUE_NULL MNOPROTO { void thr_exit(long *state); } 432 AUE_NULL MNOPROTO { int thr_self(long *id); } 433 AUE_NULL MNOPROTO { int thr_kill(long id, int sig); } 434 AUE_NULL MNOPROTO { int _umtx_lock(struct umtx *umtx); } 435 AUE_NULL MNOPROTO { int _umtx_unlock(struct umtx *umtx); } 436 AUE_NULL MNOPROTO { int jail_attach(int jid); } 437 AUE_EXTATTR_LIST_FD UNIMPL extattr_list_fd 438 AUE_EXTATTR_LIST_FILE UNIMPL extattr_list_file 439 AUE_EXTATTR_LIST_LINK UNIMPL extattr_list_link 440 AUE_NULL UNIMPL kse_switchin 441 AUE_NULL UNIMPL ksem_timedwait 442 AUE_NULL MNOPROTO { int thr_suspend( \ const struct timespec *timeout); } 443 AUE_NULL MNOPROTO { int thr_wake(long id); } 444 AUE_MODUNLOAD MNOPROTO { int kldunloadf(int fileid, int flags); } 445 AUE_AUDIT MNOPROTO { int audit(const void *record, \ u_int length); } 446 AUE_AUDITON MNOPROTO { int auditon(int cmd, void *data, \ u_int length); } 447 AUE_GETAUID MNOPROTO { int getauid(uid_t *auid); } 448 AUE_SETAUID MNOPROTO { int setauid(uid_t *auid); } 449 AUE_GETAUDIT MNOPROTO { int getaudit(struct auditinfo *auditinfo); } 450 AUE_SETAUDIT MNOPROTO { int setaudit(struct auditinfo *auditinfo); } 451 AUE_GETAUDIT_ADDR MNOPROTO { int getaudit_addr( \ struct auditinfo_addr *auditinfo_addr, \ u_int length); } 452 AUE_SETAUDIT_ADDR MNOPROTO { int setaudit_addr( \ struct auditinfo_addr *auditinfo_addr, \ u_int length); } 453 AUE_AUDITCTL MNOPROTO { int auditctl(char *path); } 454 AUE_NULL UNIMPL _umtx_op Index: stable/6/sys/ia64/ia32/ia32_signal.c =================================================================== --- stable/6/sys/ia64/ia32/ia32_signal.c (revision 169231) +++ stable/6/sys/ia64/ia32/ia32_signal.c (revision 169232) @@ -1,249 +1,270 @@ /*- * Copyright (c) 2002 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_compat.h" #define __ELF_WORD_SIZE 32 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Signal sending has not been implemented on ia64. This causes * the sigtramp code to not understand the arguments and the application * will generally crash if it tries to handle a signal. Calling * sendsig() means that at least untrapped signals will work. */ void ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) { sendsig(catcher, sig, mask, code); } #ifdef COMPAT_FREEBSD4 int freebsd4_freebsd32_sigreturn(struct thread *td, struct freebsd4_freebsd32_sigreturn_args *uap) { return (sigreturn(td, (struct sigreturn_args *)uap)); } #endif int freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap) { return (sigreturn(td, (struct sigreturn_args *)uap)); } void ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) { struct trapframe *tf = td->td_frame; vm_offset_t gdt, ldt; u_int64_t codesel, datasel, ldtsel; u_int64_t codeseg, dataseg, gdtseg, ldtseg; struct segment_descriptor desc; struct vmspace *vmspace = td->td_proc->p_vmspace; exec_setregs(td, entry, stack, ps_strings); /* Non-syscall frames are cleared by exec_setregs() */ if (tf->tf_flags & FRAME_SYSCALL) { bzero(&tf->tf_scratch, sizeof(tf->tf_scratch)); bzero(&tf->tf_scratch_fp, sizeof(tf->tf_scratch_fp)); } else tf->tf_special.ndirty = 0; tf->tf_special.psr |= IA64_PSR_IS; tf->tf_special.sp = stack; /* Point the RSE backstore to something harmless. */ tf->tf_special.bspstore = (FREEBSD32_PS_STRINGS - sz_ia32_sigcode - SPARE_USRSPACE + 15) & ~15; codesel = LSEL(LUCODE_SEL, SEL_UPL); datasel = LSEL(LUDATA_SEL, SEL_UPL); ldtsel = GSEL(GLDT_SEL, SEL_UPL); /* Setup ia32 segment registers. */ tf->tf_scratch.gr16 = (datasel << 48) | (datasel << 32) | (datasel << 16) | datasel; tf->tf_scratch.gr17 = (ldtsel << 32) | (datasel << 16) | codesel; /* * Build the GDT and LDT. */ gdt = FREEBSD32_USRSTACK; vm_map_find(&vmspace->vm_map, 0, 0, &gdt, IA32_PAGE_SIZE << 1, 0, VM_PROT_ALL, VM_PROT_ALL, 0); ldt = gdt + IA32_PAGE_SIZE; desc.sd_lolimit = 8*NLDT-1; desc.sd_lobase = ldt & 0xffffff; desc.sd_type = SDT_SYSLDT; desc.sd_dpl = SEL_UPL; desc.sd_p = 1; desc.sd_hilimit = 0; desc.sd_def32 = 0; desc.sd_gran = 0; desc.sd_hibase = ldt >> 24; copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc)); desc.sd_lolimit = ((FREEBSD32_USRSTACK >> 12) - 1) & 0xffff; desc.sd_lobase = 0; desc.sd_type = SDT_MEMERA; desc.sd_dpl = SEL_UPL; desc.sd_p = 1; desc.sd_hilimit = ((FREEBSD32_USRSTACK >> 12) - 1) >> 16; desc.sd_def32 = 1; desc.sd_gran = 1; desc.sd_hibase = 0; copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc)); desc.sd_type = SDT_MEMRWA; copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc)); codeseg = 0 /* base */ + (((FREEBSD32_USRSTACK >> 12) - 1) << 32) /* limit */ + ((long)SDT_MEMERA << 52) + ((long)SEL_UPL << 57) + (1L << 59) /* present */ + (1L << 62) /* 32 bits */ + (1L << 63); /* page granularity */ dataseg = 0 /* base */ + (((FREEBSD32_USRSTACK >> 12) - 1) << 32) /* limit */ + ((long)SDT_MEMRWA << 52) + ((long)SEL_UPL << 57) + (1L << 59) /* present */ + (1L << 62) /* 32 bits */ + (1L << 63); /* page granularity */ tf->tf_scratch.csd = codeseg; tf->tf_scratch.ssd = dataseg; tf->tf_scratch.gr24 = dataseg; /* ESD */ tf->tf_scratch.gr27 = dataseg; /* DSD */ tf->tf_scratch.gr28 = dataseg; /* FSD */ tf->tf_scratch.gr29 = dataseg; /* GSD */ gdtseg = gdt /* base */ + ((8L*NGDT - 1) << 32) /* limit */ + ((long)SDT_SYSNULL << 52) + ((long)SEL_UPL << 57) + (1L << 59) /* present */ + (0L << 62) /* 16 bits */ + (0L << 63); /* byte granularity */ ldtseg = ldt /* base */ + ((8L*NLDT - 1) << 32) /* limit */ + ((long)SDT_SYSLDT << 52) + ((long)SEL_UPL << 57) + (1L << 59) /* present */ + (0L << 62) /* 16 bits */ + (0L << 63); /* byte granularity */ tf->tf_scratch.gr30 = ldtseg; /* LDTD */ tf->tf_scratch.gr31 = gdtseg; /* GDTD */ /* Set ia32 control registers on this processor. */ ia64_set_cflg(CR0_PE | CR0_PG | ((long)(CR4_XMM | CR4_FXSR) << 32)); ia64_set_eflag(PSL_USER); /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ tf->tf_scratch.gr11 = FREEBSD32_PS_STRINGS; /* * XXX - Linux emulator * Make sure sure edx is 0x0 on entry. Linux binaries depend * on it. */ td->td_retval[1] = 0; } void ia32_restorectx(struct pcb *pcb) { ia64_set_cflg(pcb->pcb_ia32_cflg); ia64_set_eflag(pcb->pcb_ia32_eflag); ia64_set_fcr(pcb->pcb_ia32_fcr); ia64_set_fdr(pcb->pcb_ia32_fdr); ia64_set_fir(pcb->pcb_ia32_fir); ia64_set_fsr(pcb->pcb_ia32_fsr); } void ia32_savectx(struct pcb *pcb) { pcb->pcb_ia32_cflg = ia64_get_cflg(); pcb->pcb_ia32_eflag = ia64_get_eflag(); pcb->pcb_ia32_fcr = ia64_get_fcr(); pcb->pcb_ia32_fdr = ia64_get_fdr(); pcb->pcb_ia32_fir = ia64_get_fir(); pcb->pcb_ia32_fsr = ia64_get_fsr(); } + +int +freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) +{ + + return (nosys(td, NULL)); +} + +int +freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) +{ + + return (nosys(td, NULL)); +} + +int +freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) +{ + + return (nosys(td, NULL)); +}