Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 16 Apr 2017 07:33:47 +0000 (UTC)
From:      Michal Meloun <mmel@FreeBSD.org>
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
Message-ID:  <201704160733.v3G7Xlja085445@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201704160733.v3G7Xlja085445>