From owner-svn-src-all@freebsd.org Sun Apr 16 07:33:49 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 43CCCD40EA2; Sun, 16 Apr 2017 07:33:49 +0000 (UTC) (envelope-from mmel@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 11E601475; Sun, 16 Apr 2017 07:33:48 +0000 (UTC) (envelope-from mmel@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v3G7Xm4T085455; Sun, 16 Apr 2017 07:33:48 GMT (envelope-from mmel@FreeBSD.org) Received: (from mmel@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v3G7Xlja085445; Sun, 16 Apr 2017 07:33:47 GMT (envelope-from mmel@FreeBSD.org) Message-Id: <201704160733.v3G7Xlja085445@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mmel set sender to mmel@FreeBSD.org using -f From: Michal Meloun Date: Sun, 16 Apr 2017 07:33:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r317005 - in stable/11: lib/libthread_db/arch/arm sys/arm/arm sys/arm/include X-SVN-Group: stable-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 16 Apr 2017 07:33:49 -0000 Author: mmel Date: Sun Apr 16 07:33:47 2017 New Revision: 317005 URL: https://svnweb.freebsd.org/changeset/base/317005 Log: MFC r315900,r315973,r315974: r315900: Cleanup structures related to VFP and/or mcontext_t. - in mcontext_t, rename newer used 'union __vfp' to equaly sized 'mc_spare'. Space allocated by 'union __vfp' is too small and cannot hold full VFP context. - move structures defined in fp.h to more appropriate headers. - remove all unused VFP structures. r315973: Save VFP state on fork(). Update the copy of VFP state in PCB before it is cloned for new process. r315974: Preserve VFP state across signal delivery. Deleted: stable/11/sys/arm/include/fp.h Modified: stable/11/lib/libthread_db/arch/arm/libpthread_md.c stable/11/sys/arm/arm/machdep.c stable/11/sys/arm/arm/vfp.c stable/11/sys/arm/arm/vm_machdep.c stable/11/sys/arm/include/frame.h stable/11/sys/arm/include/pcb.h stable/11/sys/arm/include/reg.h stable/11/sys/arm/include/ucontext.h stable/11/sys/arm/include/vfp.h Directory Properties: stable/11/ (props changed) Modified: stable/11/lib/libthread_db/arch/arm/libpthread_md.c ============================================================================== --- stable/11/lib/libthread_db/arch/arm/libpthread_md.c Sun Apr 16 07:21:20 2017 (r317004) +++ stable/11/lib/libthread_db/arch/arm/libpthread_md.c Sun Apr 16 07:33:47 2017 (r317005) @@ -90,7 +90,9 @@ pt_fpreg_to_ucontext(const struct fpreg mcontext_t *mc = &uc->uc_mcontext; /* XXX */ - memset(&mc->__fpu, 0, sizeof(mc->__fpu)); + mc->mc_vfp_size = 0; + mc->mc_vfp_ptr = NULL; + memset(mc->mc_spare, 0, sizeof(mc->mc_spare)); } void Modified: stable/11/sys/arm/arm/machdep.c ============================================================================== --- stable/11/sys/arm/arm/machdep.c Sun Apr 16 07:21:20 2017 (r317004) +++ stable/11/sys/arm/arm/machdep.c Sun Apr 16 07:33:47 2017 (r317005) @@ -146,105 +146,6 @@ static delay_func *delay_impl; static void *delay_arg; #endif -void -sendsig(catcher, ksi, mask) - sig_t catcher; - ksiginfo_t *ksi; - sigset_t *mask; -{ - struct thread *td; - struct proc *p; - struct trapframe *tf; - struct sigframe *fp, frame; - struct sigacts *psp; - struct sysentvec *sysent; - int onstack; - int sig; - int code; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - sig = ksi->ksi_signo; - code = ksi->ksi_code; - psp = p->p_sigacts; - mtx_assert(&psp->ps_mtx, MA_OWNED); - tf = td->td_frame; - onstack = sigonstack(tf->tf_usr_sp); - - CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, - catcher, sig); - - /* Allocate and validate space for the signal handler context. */ - if ((td->td_pflags & TDP_ALTSTACK) != 0 && !(onstack) && - SIGISMEMBER(psp->ps_sigonstack, sig)) { - fp = (struct sigframe *)((uintptr_t)td->td_sigstk.ss_sp + - td->td_sigstk.ss_size); -#if defined(COMPAT_43) - td->td_sigstk.ss_flags |= SS_ONSTACK; -#endif - } else - fp = (struct sigframe *)td->td_frame->tf_usr_sp; - - /* make room on the stack */ - fp--; - - /* make the stack aligned */ - fp = (struct sigframe *)STACKALIGN(fp); - /* Populate the siginfo frame. */ - get_mcontext(td, &frame.sf_uc.uc_mcontext, 0); - frame.sf_si = ksi->ksi_info; - frame.sf_uc.uc_sigmask = *mask; - frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK ) - ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE; - frame.sf_uc.uc_stack = td->td_sigstk; - mtx_unlock(&psp->ps_mtx); - PROC_UNLOCK(td->td_proc); - - /* Copy the sigframe out to the user's stack. */ - if (copyout(&frame, fp, sizeof(*fp)) != 0) { - /* Process has trashed its stack. Kill it. */ - CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp); - PROC_LOCK(p); - sigexit(td, SIGILL); - } - - /* - * Build context to run handler in. We invoke the handler - * directly, only returning via the trampoline. Note the - * trampoline version numbers are coordinated with machine- - * dependent code in libc. - */ - - tf->tf_r0 = sig; - tf->tf_r1 = (register_t)&fp->sf_si; - tf->tf_r2 = (register_t)&fp->sf_uc; - - /* the trampoline uses r5 as the uc address */ - tf->tf_r5 = (register_t)&fp->sf_uc; - tf->tf_pc = (register_t)catcher; - tf->tf_usr_sp = (register_t)fp; - sysent = p->p_sysent; - if (sysent->sv_sigcode_base != 0) - tf->tf_usr_lr = (register_t)sysent->sv_sigcode_base; - else - tf->tf_usr_lr = (register_t)(sysent->sv_psstrings - - *(sysent->sv_szsigcode)); - /* Set the mode to enter in the signal handler */ -#if __ARM_ARCH >= 7 - if ((register_t)catcher & 1) - tf->tf_spsr |= PSR_T; - else - tf->tf_spsr &= ~PSR_T; -#endif - - CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_usr_lr, - tf->tf_usr_sp); - - PROC_LOCK(p); - mtx_lock(&psp->ps_mtx); -} - struct kva_md_info kmi; /* @@ -488,6 +389,47 @@ exec_setregs(struct thread *td, struct i tf->tf_spsr = PSR_USR32_MODE; } + +#ifdef VFP +/* + * Get machine VFP context. + */ +static void +get_vfpcontext(struct thread *td, mcontext_vfp_t *vfp) +{ + struct pcb *curpcb; + + curpcb = curthread->td_pcb; + critical_enter(); + + vfp_store(&curpcb->pcb_vfpstate, false); + memcpy(vfp->mcv_reg, curpcb->pcb_vfpstate.reg, + sizeof(vfp->mcv_reg)); + vfp->mcv_fpscr = curpcb->pcb_vfpstate.fpscr; + + critical_exit(); +} + +/* + * Set machine VFP context. + */ +static void +set_vfpcontext(struct thread *td, mcontext_vfp_t *vfp) +{ + struct pcb *curpcb; + + curpcb = curthread->td_pcb; + critical_enter(); + + vfp_discard(td); + memcpy(curpcb->pcb_vfpstate.reg, vfp->mcv_reg, + sizeof(curpcb->pcb_vfpstate.reg)); + curpcb->pcb_vfpstate.fpscr = vfp->mcv_fpscr; + + critical_exit(); +} +#endif + /* * Get machine context. */ @@ -520,6 +462,10 @@ get_mcontext(struct thread *td, mcontext gr[_REG_LR] = tf->tf_usr_lr; gr[_REG_PC] = tf->tf_pc; + mcp->mc_vfp_size = 0; + mcp->mc_vfp_ptr = NULL; + memset(&mcp->mc_spare, 0, sizeof(mcp->mc_spare)); + return (0); } @@ -532,9 +478,29 @@ get_mcontext(struct thread *td, mcontext int set_mcontext(struct thread *td, mcontext_t *mcp) { + mcontext_vfp_t mc_vfp, *vfp; struct trapframe *tf = td->td_frame; const __greg_t *gr = mcp->__gregs; +#ifdef WITNESS + if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_size != sizeof(mc_vfp)) { + printf("%s: %s: Malformed mc_vfp_size: %d (0x%08X)\n", + td->td_proc->p_comm, __func__, + mcp->mc_vfp_size, mcp->mc_vfp_size); + } else if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_ptr == NULL) { + printf("%s: %s: c_vfp_size != 0 but mc_vfp_ptr == NULL\n", + td->td_proc->p_comm, __func__); + } +#endif + + if (mcp->mc_vfp_size == sizeof(mc_vfp) && mcp->mc_vfp_ptr != NULL) { + if (copyin(mcp->mc_vfp_ptr, &mc_vfp, sizeof(mc_vfp)) != 0) + return (EFAULT); + vfp = &mc_vfp; + } else { + vfp = NULL; + } + tf->tf_r0 = gr[_REG_R0]; tf->tf_r1 = gr[_REG_R1]; tf->tf_r2 = gr[_REG_R2]; @@ -552,10 +518,120 @@ set_mcontext(struct thread *td, mcontext tf->tf_usr_lr = gr[_REG_LR]; tf->tf_pc = gr[_REG_PC]; tf->tf_spsr = gr[_REG_CPSR]; - +#ifdef VFP + if (vfp != NULL) + set_vfpcontext(td, vfp); +#endif return (0); } +void +sendsig(catcher, ksi, mask) + sig_t catcher; + ksiginfo_t *ksi; + sigset_t *mask; +{ + struct thread *td; + struct proc *p; + struct trapframe *tf; + struct sigframe *fp, frame; + struct sigacts *psp; + struct sysentvec *sysent; + int onstack; + int sig; + int code; + + td = curthread; + p = td->td_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; + code = ksi->ksi_code; + psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); + tf = td->td_frame; + onstack = sigonstack(tf->tf_usr_sp); + + CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, + catcher, sig); + + /* Allocate and validate space for the signal handler context. */ + if ((td->td_pflags & TDP_ALTSTACK) != 0 && !(onstack) && + SIGISMEMBER(psp->ps_sigonstack, sig)) { + fp = (struct sigframe *)((uintptr_t)td->td_sigstk.ss_sp + + td->td_sigstk.ss_size); +#if defined(COMPAT_43) + td->td_sigstk.ss_flags |= SS_ONSTACK; +#endif + } else + fp = (struct sigframe *)td->td_frame->tf_usr_sp; + + /* make room on the stack */ + fp--; + + /* make the stack aligned */ + fp = (struct sigframe *)STACKALIGN(fp); + /* Populate the siginfo frame. */ + get_mcontext(td, &frame.sf_uc.uc_mcontext, 0); +#ifdef VFP + get_vfpcontext(td, &frame.sf_vfp); + frame.sf_uc.uc_mcontext.mc_vfp_size = sizeof(fp->sf_vfp); + frame.sf_uc.uc_mcontext.mc_vfp_ptr = &fp->sf_vfp; +#else + frame.sf_uc.uc_mcontext.mc_vfp_size = 0; + frame.sf_uc.uc_mcontext.mc_vfp_ptr = NULL; +#endif + frame.sf_si = ksi->ksi_info; + frame.sf_uc.uc_sigmask = *mask; + frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK ) + ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE; + frame.sf_uc.uc_stack = td->td_sigstk; + mtx_unlock(&psp->ps_mtx); + PROC_UNLOCK(td->td_proc); + + /* Copy the sigframe out to the user's stack. */ + if (copyout(&frame, fp, sizeof(*fp)) != 0) { + /* Process has trashed its stack. Kill it. */ + CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp); + PROC_LOCK(p); + sigexit(td, SIGILL); + } + + /* + * Build context to run handler in. We invoke the handler + * directly, only returning via the trampoline. Note the + * trampoline version numbers are coordinated with machine- + * dependent code in libc. + */ + + tf->tf_r0 = sig; + tf->tf_r1 = (register_t)&fp->sf_si; + tf->tf_r2 = (register_t)&fp->sf_uc; + + /* the trampoline uses r5 as the uc address */ + tf->tf_r5 = (register_t)&fp->sf_uc; + tf->tf_pc = (register_t)catcher; + tf->tf_usr_sp = (register_t)fp; + sysent = p->p_sysent; + if (sysent->sv_sigcode_base != 0) + tf->tf_usr_lr = (register_t)sysent->sv_sigcode_base; + else + tf->tf_usr_lr = (register_t)(sysent->sv_psstrings - + *(sysent->sv_szsigcode)); + /* Set the mode to enter in the signal handler */ +#if __ARM_ARCH >= 7 + if ((register_t)catcher & 1) + tf->tf_spsr |= PSR_T; + else + tf->tf_spsr &= ~PSR_T; +#endif + + CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_usr_lr, + tf->tf_usr_sp); + + PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); +} + int sys_sigreturn(td, uap) struct thread *td; @@ -578,7 +654,7 @@ sys_sigreturn(td, uap) if ((spsr & PSR_MODE) != PSR_USR32_MODE || (spsr & (PSR_I | PSR_F)) != 0) return (EINVAL); - /* Restore register context. */ + /* Restore register context. */ set_mcontext(td, &uc.uc_mcontext); /* Restore signal mask. */ Modified: stable/11/sys/arm/arm/vfp.c ============================================================================== --- stable/11/sys/arm/arm/vfp.c Sun Apr 16 07:21:20 2017 (r317004) +++ stable/11/sys/arm/arm/vfp.c Sun Apr 16 07:33:47 2017 (r317005) @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include Modified: stable/11/sys/arm/arm/vm_machdep.c ============================================================================== --- stable/11/sys/arm/arm/vm_machdep.c Sun Apr 16 07:21:20 2017 (r317004) +++ stable/11/sys/arm/arm/vm_machdep.c Sun Apr 16 07:33:47 2017 (r317005) @@ -111,6 +111,14 @@ cpu_fork(register struct thread *td1, re pmap_use_minicache(td2->td_kstack, td2->td_kstack_pages * PAGE_SIZE); #endif #endif +#ifdef VFP + /* Store actual state of VFP */ + if (curthread == td1) { + critical_enter(); + vfp_store(&td1->td_pcb->pcb_vfpstate, false); + critical_exit(); + } +#endif td2->td_pcb = pcb2; /* Clone td1's pcb */ Modified: stable/11/sys/arm/include/frame.h ============================================================================== --- stable/11/sys/arm/include/frame.h Sun Apr 16 07:21:20 2017 (r317004) +++ stable/11/sys/arm/include/frame.h Sun Apr 16 07:33:47 2017 (r317005) @@ -94,6 +94,7 @@ struct trapframe { struct sigframe { siginfo_t sf_si; /* actual saved siginfo */ ucontext_t sf_uc; /* actual saved ucontext */ + mcontext_vfp_t sf_vfp; /* actual saved VFP context */ }; Modified: stable/11/sys/arm/include/pcb.h ============================================================================== --- stable/11/sys/arm/include/pcb.h Sun Apr 16 07:21:20 2017 (r317004) +++ stable/11/sys/arm/include/pcb.h Sun Apr 16 07:33:47 2017 (r317005) @@ -38,8 +38,8 @@ #ifndef _MACHINE_PCB_H_ #define _MACHINE_PCB_H_ -#include #include +#include /* Modified: stable/11/sys/arm/include/reg.h ============================================================================== --- stable/11/sys/arm/include/reg.h Sun Apr 16 07:21:20 2017 (r317004) +++ stable/11/sys/arm/include/reg.h Sun Apr 16 07:33:47 2017 (r317005) @@ -3,8 +3,6 @@ #ifndef MACHINE_REG_H #define MACHINE_REG_H -#include - struct reg { unsigned int r[13]; unsigned int r_sp; @@ -13,6 +11,14 @@ struct reg { unsigned int r_cpsr; }; +struct fp_extended_precision { + u_int32_t fp_exponent; + u_int32_t fp_mantissa_hi; + u_int32_t fp_mantissa_lo; +}; + +typedef struct fp_extended_precision fp_reg_t; + struct fpreg { unsigned int fpr_fpsr; fp_reg_t fpr[8]; Modified: stable/11/sys/arm/include/ucontext.h ============================================================================== --- stable/11/sys/arm/include/ucontext.h Sun Apr 16 07:21:20 2017 (r317004) +++ stable/11/sys/arm/include/ucontext.h Sun Apr 16 07:33:47 2017 (r317005) @@ -66,35 +66,22 @@ typedef __greg_t __gregset_t[_NGREG]; /* * Floating point register state */ -/* Note: the storage layout of this structure must be identical to ARMFPE! */ typedef struct { - unsigned int __fp_fpsr; - struct { - unsigned int __fp_exponent; - unsigned int __fp_mantissa_hi; - unsigned int __fp_mantissa_lo; - } __fp_fr[8]; -} __fpregset_t; - -typedef struct { - unsigned int __vfp_fpscr; - unsigned int __vfp_fstmx[33]; - unsigned int __vfp_fpsid; -} __vfpregset_t; + __uint64_t mcv_reg[32]; + __uint32_t mcv_fpscr; +} mcontext_vfp_t; typedef struct { __gregset_t __gregs; - union { - __fpregset_t __fpregs; - __vfpregset_t __vfpregs; - } __fpu; -} mcontext_t; -/* Machine-dependent uc_flags */ -#define _UC_ARM_VFP 0x00010000 /* FPU field is VFP */ - -/* used by signal delivery to indicate status of signal stack */ -#define _UC_SETSTACK 0x00020000 -#define _UC_CLRSTACK 0x00040000 + /* + * Originally, rest of this structure was named __fpu, 35 * 4 bytes + * long, never accessed from kernel. + */ + size_t mc_vfp_size; + void *mc_vfp_ptr; + unsigned int mc_spare[33]; +} mcontext_t; +#define UC_ #endif /* !_MACHINE_MCONTEXT_H_ */ Modified: stable/11/sys/arm/include/vfp.h ============================================================================== --- stable/11/sys/arm/include/vfp.h Sun Apr 16 07:21:20 2017 (r317004) +++ stable/11/sys/arm/include/vfp.h Sun Apr 16 07:33:47 2017 (r317005) @@ -133,9 +133,19 @@ #define COPROC11 (0x3 << 22) #ifndef LOCORE +struct vfp_state { + uint64_t reg[32]; + uint32_t fpscr; + uint32_t fpexec; + uint32_t fpinst; + uint32_t fpinst2; +}; + +#ifdef _KERNEL void vfp_init(void); void vfp_store(struct vfp_state *, boolean_t); void vfp_discard(struct thread *); -#endif +#endif /* _KERNEL */ +#endif /* LOCORE */ #endif