Date: Thu, 21 Jul 2005 23:25:01 GMT From: Peter Wemm <peter@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 80719 for review Message-ID: <200507212325.j6LNP1bQ031386@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=80719 Change 80719 by peter@peter_daintree on 2005/07/21 23:24:36 implement getcontext/setcontext/swapcontext(2) wrappers Affected files ... .. //depot/projects/hammer/sys/amd64/ia32/ia32_signal.c#14 edit .. //depot/projects/hammer/sys/compat/freebsd32/freebsd32_proto.h#31 edit .. //depot/projects/hammer/sys/compat/freebsd32/freebsd32_syscall.h#29 edit .. //depot/projects/hammer/sys/compat/freebsd32/freebsd32_syscalls.c#29 edit .. //depot/projects/hammer/sys/compat/freebsd32/freebsd32_sysent.c#29 edit .. //depot/projects/hammer/sys/compat/freebsd32/syscalls.master#33 edit Differences ... ==== //depot/projects/hammer/sys/amd64/ia32/ia32_signal.c#14 (text+ko) ==== @@ -92,38 +92,14 @@ 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_ownedfp = fpugetregs(td, (struct savefpu *)&mcp->mc_fpstate); 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); @@ -134,31 +110,180 @@ 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. - */ + fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate); } 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 ==== //depot/projects/hammer/sys/compat/freebsd32/freebsd32_proto.h#31 (text+ko) ==== @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/compat/freebsd32/freebsd32_proto.h,v 1.39 2005/07/13 20:35:08 jhb Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.51 2005/07/13 20:32:42 jhb Exp */ @@ -225,6 +225,16 @@ struct freebsd32_sigreturn_args { char sigcntxp_l_[PADL_(const struct freebsd32_ucontext *)]; const struct freebsd32_ucontext * sigcntxp; char sigcntxp_r_[PADR_(const struct freebsd32_ucontext *)]; }; +struct freebsd32_getcontext_args { + char ucp_l_[PADL_(struct freebsd32_ucontext *)]; struct freebsd32_ucontext * ucp; char ucp_r_[PADR_(struct freebsd32_ucontext *)]; +}; +struct freebsd32_setcontext_args { + char ucp_l_[PADL_(const struct freebsd32_ucontext *)]; const struct freebsd32_ucontext * ucp; char ucp_r_[PADR_(const struct freebsd32_ucontext *)]; +}; +struct freebsd32_swapcontext_args { + char oucp_l_[PADL_(struct freebsd32_ucontext *)]; struct freebsd32_ucontext * oucp; char oucp_r_[PADR_(struct freebsd32_ucontext *)]; + char ucp_l_[PADL_(const struct freebsd32_ucontext *)]; const struct freebsd32_ucontext * ucp; char ucp_r_[PADR_(const struct freebsd32_ucontext *)]; +}; int freebsd32_wait4(struct thread *, struct freebsd32_wait4_args *); int freebsd32_sigaltstack(struct thread *, struct freebsd32_sigaltstack_args *); int freebsd32_execve(struct thread *, struct freebsd32_execve_args *); @@ -259,6 +269,9 @@ int freebsd32_sendfile(struct thread *, struct freebsd32_sendfile_args *); int freebsd32_sigaction(struct thread *, struct freebsd32_sigaction_args *); int freebsd32_sigreturn(struct thread *, struct freebsd32_sigreturn_args *); +int freebsd32_getcontext(struct thread *, struct freebsd32_getcontext_args *); +int freebsd32_setcontext(struct thread *, struct freebsd32_setcontext_args *); +int freebsd32_swapcontext(struct thread *, struct freebsd32_swapcontext_args *); #ifdef COMPAT_43 ==== //depot/projects/hammer/sys/compat/freebsd32/freebsd32_syscall.h#29 (text+ko) ==== @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/compat/freebsd32/freebsd32_syscall.h,v 1.39 2005/07/13 20:35:08 jhb Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.51 2005/07/13 20:32:42 jhb Exp */ @@ -294,6 +294,9 @@ #define FREEBSD32_SYS_fhstatfs 398 #define FREEBSD32_SYS_freebsd32_sigaction 416 #define FREEBSD32_SYS_freebsd32_sigreturn 417 +#define FREEBSD32_SYS_freebsd32_getcontext 421 +#define FREEBSD32_SYS_freebsd32_setcontext 422 +#define FREEBSD32_SYS_freebsd32_swapcontext 423 #define FREEBSD32_SYS_thr_create 430 #define FREEBSD32_SYS_thr_exit 431 #define FREEBSD32_SYS_thr_self 432 ==== //depot/projects/hammer/sys/compat/freebsd32/freebsd32_syscalls.c#29 (text+ko) ==== @@ -2,7 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/compat/freebsd32/freebsd32_syscalls.c,v 1.30 2005/07/13 20:35:08 jhb Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.51 2005/07/13 20:32:42 jhb Exp */ @@ -428,9 +428,9 @@ "#418", /* 418 = __xstat */ "#419", /* 419 = __xfstat */ "#420", /* 420 = __xlstat */ - "#421", /* 421 = getcontext */ - "#422", /* 422 = setcontext */ - "#423", /* 423 = swapcontext */ + "freebsd32_getcontext", /* 421 = freebsd32_getcontext */ + "freebsd32_setcontext", /* 422 = freebsd32_setcontext */ + "freebsd32_swapcontext", /* 423 = freebsd32_swapcontext */ "#424", /* 424 = swapoff */ "#425", /* 425 = __acl_get_link */ "#426", /* 426 = __acl_set_link */ ==== //depot/projects/hammer/sys/compat/freebsd32/freebsd32_sysent.c#29 (text+ko) ==== @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/compat/freebsd32/freebsd32_sysent.c,v 1.40 2005/07/13 20:35:08 jhb Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/compat/freebsd32/syscalls.master,v 1.51 2005/07/13 20:32:42 jhb Exp */ @@ -447,9 +447,9 @@ { 0, (sy_call_t *)nosys, AUE_NULL }, /* 418 = __xstat */ { 0, (sy_call_t *)nosys, AUE_NULL }, /* 419 = __xfstat */ { 0, (sy_call_t *)nosys, AUE_NULL }, /* 420 = __xlstat */ - { 0, (sy_call_t *)nosys, AUE_NULL }, /* 421 = getcontext */ - { 0, (sy_call_t *)nosys, AUE_NULL }, /* 422 = setcontext */ - { 0, (sy_call_t *)nosys, AUE_NULL }, /* 423 = swapcontext */ + { SYF_MPSAFE | AS(freebsd32_getcontext_args), (sy_call_t *)freebsd32_getcontext, AUE_NULL }, /* 421 = freebsd32_getcontext */ + { SYF_MPSAFE | AS(freebsd32_setcontext_args), (sy_call_t *)freebsd32_setcontext, AUE_NULL }, /* 422 = freebsd32_setcontext */ + { SYF_MPSAFE | AS(freebsd32_swapcontext_args), (sy_call_t *)freebsd32_swapcontext, AUE_NULL }, /* 423 = freebsd32_swapcontext */ { 0, (sy_call_t *)nosys, AUE_NULL }, /* 424 = swapoff */ { 0, (sy_call_t *)nosys, AUE_NULL }, /* 425 = __acl_get_link */ { 0, (sy_call_t *)nosys, AUE_NULL }, /* 426 = __acl_set_link */ ==== //depot/projects/hammer/sys/compat/freebsd32/syscalls.master#33 (text+ko) ==== @@ -693,12 +693,13 @@ 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 MSTD { int freebsd32_getcontext( \ + struct freebsd32_ucontext *ucp); } +422 AUE_NULL MSTD { int freebsd32_setcontext( \ + const struct freebsd32_ucontext *ucp); } +423 AUE_NULL MSTD { int freebsd32_swapcontext( \ + struct freebsd32_ucontext *oucp, \ + const struct freebsd32_ucontext *ucp); } 424 AUE_NULL UNIMPL swapoff 425 AUE_NULL UNIMPL __acl_get_link 426 AUE_NULL UNIMPL __acl_set_link
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200507212325.j6LNP1bQ031386>