svn commit: r317005 - in stable/11: lib/libthread_db/arch/arm sys/arm/arm sys/arm/include
Michal Meloun
mmel at FreeBSD.org
Sun Apr 16 07:33:49 UTC 2017
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 <machine/armreg.h>
#include <machine/frame.h>
-#include <machine/fp.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/undefined.h>
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 <machine/fp.h>
#include <machine/frame.h>
+#include <machine/vfp.h>
/*
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 <machine/fp.h>
-
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
More information about the svn-src-all
mailing list