svn commit: r307321 - in head/sys/arm64: arm64 include
Andrew Turner
andrew at FreeBSD.org
Fri Oct 14 15:53:50 UTC 2016
Author: andrew
Date: Fri Oct 14 15:53:48 2016
New Revision: 307321
URL: https://svnweb.freebsd.org/changeset/base/307321
Log:
Rework how we store the VFP registers in the pcb. This will be used when
creating a floating-point context within the kernel without having to move
the stored values in memory.
Sponsored by: The FreeBSD Foundation
Modified:
head/sys/arm64/arm64/machdep.c
head/sys/arm64/arm64/vfp.c
head/sys/arm64/arm64/vm_machdep.c
head/sys/arm64/include/pcb.h
head/sys/arm64/include/vfp.h
Modified: head/sys/arm64/arm64/machdep.c
==============================================================================
--- head/sys/arm64/arm64/machdep.c Fri Oct 14 15:16:44 2016 (r307320)
+++ head/sys/arm64/arm64/machdep.c Fri Oct 14 15:53:48 2016 (r307321)
@@ -192,9 +192,12 @@ fill_fpregs(struct thread *td, struct fp
*/
vfp_save_state(td, pcb);
- memcpy(regs->fp_q, pcb->pcb_vfp, sizeof(regs->fp_q));
- regs->fp_cr = pcb->pcb_fpcr;
- regs->fp_sr = pcb->pcb_fpsr;
+ KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate,
+ ("Called fill_fpregs while the kernel is using the VFP"));
+ memcpy(regs->fp_q, pcb->pcb_fpustate.vfp_regs,
+ sizeof(regs->fp_q));
+ regs->fp_cr = pcb->pcb_fpustate.vfp_fpcr;
+ regs->fp_sr = pcb->pcb_fpustate.vfp_fpsr;
} else
#endif
memset(regs->fp_q, 0, sizeof(regs->fp_q));
@@ -208,9 +211,11 @@ set_fpregs(struct thread *td, struct fpr
struct pcb *pcb;
pcb = td->td_pcb;
- memcpy(pcb->pcb_vfp, regs->fp_q, sizeof(regs->fp_q));
- pcb->pcb_fpcr = regs->fp_cr;
- pcb->pcb_fpsr = regs->fp_sr;
+ KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate,
+ ("Called set_fpregs while the kernel is using the VFP"));
+ memcpy(pcb->pcb_fpustate.vfp_regs, regs->fp_q, sizeof(regs->fp_q));
+ pcb->pcb_fpustate.vfp_fpcr = regs->fp_cr;
+ pcb->pcb_fpustate.vfp_fpsr = regs->fp_sr;
#endif
return (0);
}
@@ -334,10 +339,12 @@ get_fpcontext(struct thread *td, mcontex
*/
vfp_save_state(td, curpcb);
- memcpy(mcp->mc_fpregs.fp_q, curpcb->pcb_vfp,
+ KASSERT(curpcb->pcb_fpusaved == &curpcb->pcb_fpustate,
+ ("Called get_fpcontext while the kernel is using the VFP"));
+ memcpy(mcp->mc_fpregs.fp_q, curpcb->pcb_fpustate.vfp_regs,
sizeof(mcp->mc_fpregs));
- mcp->mc_fpregs.fp_cr = curpcb->pcb_fpcr;
- mcp->mc_fpregs.fp_sr = curpcb->pcb_fpsr;
+ mcp->mc_fpregs.fp_cr = curpcb->pcb_fpustate.vfp_fpcr;
+ mcp->mc_fpregs.fp_sr = curpcb->pcb_fpustate.vfp_fpsr;
mcp->mc_fpregs.fp_flags = curpcb->pcb_fpflags;
mcp->mc_flags |= _MC_FP_VALID;
}
@@ -363,10 +370,12 @@ set_fpcontext(struct thread *td, mcontex
*/
vfp_discard(td);
- memcpy(curpcb->pcb_vfp, mcp->mc_fpregs.fp_q,
+ KASSERT(curpcb->pcb_fpusaved == &curpcb->pcb_fpustate,
+ ("Called set_fpcontext while the kernel is using the VFP"));
+ memcpy(curpcb->pcb_fpustate.vfp_regs, mcp->mc_fpregs.fp_q,
sizeof(mcp->mc_fpregs));
- curpcb->pcb_fpcr = mcp->mc_fpregs.fp_cr;
- curpcb->pcb_fpsr = mcp->mc_fpregs.fp_sr;
+ curpcb->pcb_fpustate.vfp_fpcr = mcp->mc_fpregs.fp_cr;
+ curpcb->pcb_fpustate.vfp_fpsr = mcp->mc_fpregs.fp_sr;
curpcb->pcb_fpflags = mcp->mc_fpregs.fp_flags;
}
@@ -607,6 +616,7 @@ init_proc0(vm_offset_t kstack)
thread0.td_kstack = kstack;
thread0.td_pcb = (struct pcb *)(thread0.td_kstack) - 1;
thread0.td_pcb->pcb_fpflags = 0;
+ thread0.td_pcb->pcb_fpusaved = &thread0.td_pcb->pcb_fpustate;
thread0.td_pcb->pcb_vfpcpu = UINT_MAX;
thread0.td_frame = &proc0_tf;
pcpup->pc_curpcb = thread0.td_pcb;
Modified: head/sys/arm64/arm64/vfp.c
==============================================================================
--- head/sys/arm64/arm64/vfp.c Fri Oct 14 15:16:44 2016 (r307320)
+++ head/sys/arm64/arm64/vfp.c Fri Oct 14 15:53:48 2016 (r307321)
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
@@ -42,7 +43,10 @@ __FBSDID("$FreeBSD$");
#include <machine/vfp.h>
/* Sanity check we can store all the VFP registers */
-CTASSERT(sizeof(((struct pcb *)0)->pcb_vfp) == 16 * 32);
+CTASSERT(sizeof(((struct pcb *)0)->pcb_fpustate.vfp_regs) == 16 * 32);
+
+static MALLOC_DEFINE(M_FPUKERN_CTX, "fpukern_ctx",
+ "Kernel contexts for VFP state");
static void
vfp_enable(void)
@@ -81,11 +85,73 @@ vfp_discard(struct thread *td)
vfp_disable();
}
-void
-vfp_save_state(struct thread *td, struct pcb *pcb)
+static void
+vfp_store(struct vfpstate *state)
+{
+ __int128_t *vfp_state;
+ uint64_t fpcr, fpsr;
+
+ vfp_state = state->vfp_regs;
+ __asm __volatile(
+ "mrs %0, fpcr \n"
+ "mrs %1, fpsr \n"
+ "stp q0, q1, [%2, #16 * 0]\n"
+ "stp q2, q3, [%2, #16 * 2]\n"
+ "stp q4, q5, [%2, #16 * 4]\n"
+ "stp q6, q7, [%2, #16 * 6]\n"
+ "stp q8, q9, [%2, #16 * 8]\n"
+ "stp q10, q11, [%2, #16 * 10]\n"
+ "stp q12, q13, [%2, #16 * 12]\n"
+ "stp q14, q15, [%2, #16 * 14]\n"
+ "stp q16, q17, [%2, #16 * 16]\n"
+ "stp q18, q19, [%2, #16 * 18]\n"
+ "stp q20, q21, [%2, #16 * 20]\n"
+ "stp q22, q23, [%2, #16 * 22]\n"
+ "stp q24, q25, [%2, #16 * 24]\n"
+ "stp q26, q27, [%2, #16 * 26]\n"
+ "stp q28, q29, [%2, #16 * 28]\n"
+ "stp q30, q31, [%2, #16 * 30]\n"
+ : "=&r"(fpcr), "=&r"(fpsr) : "r"(vfp_state));
+
+ state->vfp_fpcr = fpcr;
+ state->vfp_fpsr = fpsr;
+}
+
+static void
+vfp_restore(struct vfpstate *state)
{
__int128_t *vfp_state;
uint64_t fpcr, fpsr;
+
+ vfp_state = state->vfp_regs;
+ fpcr = state->vfp_fpcr;
+ fpsr = state->vfp_fpsr;
+
+ __asm __volatile(
+ "ldp q0, q1, [%2, #16 * 0]\n"
+ "ldp q2, q3, [%2, #16 * 2]\n"
+ "ldp q4, q5, [%2, #16 * 4]\n"
+ "ldp q6, q7, [%2, #16 * 6]\n"
+ "ldp q8, q9, [%2, #16 * 8]\n"
+ "ldp q10, q11, [%2, #16 * 10]\n"
+ "ldp q12, q13, [%2, #16 * 12]\n"
+ "ldp q14, q15, [%2, #16 * 14]\n"
+ "ldp q16, q17, [%2, #16 * 16]\n"
+ "ldp q18, q19, [%2, #16 * 18]\n"
+ "ldp q20, q21, [%2, #16 * 20]\n"
+ "ldp q22, q23, [%2, #16 * 22]\n"
+ "ldp q24, q25, [%2, #16 * 24]\n"
+ "ldp q26, q27, [%2, #16 * 26]\n"
+ "ldp q28, q29, [%2, #16 * 28]\n"
+ "ldp q30, q31, [%2, #16 * 30]\n"
+ "msr fpcr, %0 \n"
+ "msr fpsr, %1 \n"
+ : : "r"(fpcr), "r"(fpsr), "r"(vfp_state));
+}
+
+void
+vfp_save_state(struct thread *td, struct pcb *pcb)
+{
uint32_t cpacr;
KASSERT(pcb != NULL, ("NULL vfp pcb"));
@@ -104,31 +170,7 @@ vfp_save_state(struct thread *td, struct
KASSERT(PCPU_GET(fpcurthread) == td,
("Storing an invalid VFP state"));
- vfp_state = pcb->pcb_vfp;
- __asm __volatile(
- "mrs %0, fpcr \n"
- "mrs %1, fpsr \n"
- "stp q0, q1, [%2, #16 * 0]\n"
- "stp q2, q3, [%2, #16 * 2]\n"
- "stp q4, q5, [%2, #16 * 4]\n"
- "stp q6, q7, [%2, #16 * 6]\n"
- "stp q8, q9, [%2, #16 * 8]\n"
- "stp q10, q11, [%2, #16 * 10]\n"
- "stp q12, q13, [%2, #16 * 12]\n"
- "stp q14, q15, [%2, #16 * 14]\n"
- "stp q16, q17, [%2, #16 * 16]\n"
- "stp q18, q19, [%2, #16 * 18]\n"
- "stp q20, q21, [%2, #16 * 20]\n"
- "stp q22, q23, [%2, #16 * 22]\n"
- "stp q24, q25, [%2, #16 * 24]\n"
- "stp q26, q27, [%2, #16 * 26]\n"
- "stp q28, q29, [%2, #16 * 28]\n"
- "stp q30, q31, [%2, #16 * 30]\n"
- : "=&r"(fpcr), "=&r"(fpsr) : "r"(vfp_state));
-
- pcb->pcb_fpcr = fpcr;
- pcb->pcb_fpsr = fpsr;
-
+ vfp_store(pcb->pcb_fpusaved);
dsb(ish);
vfp_disable();
}
@@ -138,8 +180,6 @@ vfp_save_state(struct thread *td, struct
void
vfp_restore_state(void)
{
- __int128_t *vfp_state;
- uint64_t fpcr, fpsr;
struct pcb *curpcb;
u_int cpu;
@@ -158,31 +198,7 @@ vfp_restore_state(void)
*/
if (PCPU_GET(fpcurthread) != curthread || cpu != curpcb->pcb_vfpcpu) {
- vfp_state = curthread->td_pcb->pcb_vfp;
- fpcr = curthread->td_pcb->pcb_fpcr;
- fpsr = curthread->td_pcb->pcb_fpsr;
-
- __asm __volatile(
- "ldp q0, q1, [%2, #16 * 0]\n"
- "ldp q2, q3, [%2, #16 * 2]\n"
- "ldp q4, q5, [%2, #16 * 4]\n"
- "ldp q6, q7, [%2, #16 * 6]\n"
- "ldp q8, q9, [%2, #16 * 8]\n"
- "ldp q10, q11, [%2, #16 * 10]\n"
- "ldp q12, q13, [%2, #16 * 12]\n"
- "ldp q14, q15, [%2, #16 * 14]\n"
- "ldp q16, q17, [%2, #16 * 16]\n"
- "ldp q18, q19, [%2, #16 * 18]\n"
- "ldp q20, q21, [%2, #16 * 20]\n"
- "ldp q22, q23, [%2, #16 * 22]\n"
- "ldp q24, q25, [%2, #16 * 24]\n"
- "ldp q26, q27, [%2, #16 * 26]\n"
- "ldp q28, q29, [%2, #16 * 28]\n"
- "ldp q30, q31, [%2, #16 * 30]\n"
- "msr fpcr, %0 \n"
- "msr fpsr, %1 \n"
- : : "r"(fpcr), "r"(fpsr), "r"(vfp_state));
-
+ vfp_restore(curthread->td_pcb->pcb_fpusaved);
PCPU_SET(fpcurthread, curthread);
curpcb->pcb_vfpcpu = cpu;
}
Modified: head/sys/arm64/arm64/vm_machdep.c
==============================================================================
--- head/sys/arm64/arm64/vm_machdep.c Fri Oct 14 15:16:44 2016 (r307320)
+++ head/sys/arm64/arm64/vm_machdep.c Fri Oct 14 15:53:48 2016 (r307321)
@@ -101,6 +101,7 @@ cpu_fork(struct thread *td1, struct proc
td2->td_pcb->pcb_x[9] = (uintptr_t)td2;
td2->td_pcb->pcb_x[PCB_LR] = (uintptr_t)fork_trampoline;
td2->td_pcb->pcb_sp = (uintptr_t)td2->td_frame;
+ td2->td_pcb->pcb_fpusaved = &td2->td_pcb->pcb_fpustate;
td2->td_pcb->pcb_vfpcpu = UINT_MAX;
/* Setup to release spin count in fork_exit(). */
@@ -169,6 +170,7 @@ cpu_copy_thread(struct thread *td, struc
td->td_pcb->pcb_x[9] = (uintptr_t)td;
td->td_pcb->pcb_x[PCB_LR] = (uintptr_t)fork_trampoline;
td->td_pcb->pcb_sp = (uintptr_t)td->td_frame;
+ td->td_pcb->pcb_fpusaved = &td->td_pcb->pcb_fpustate;
td->td_pcb->pcb_vfpcpu = UINT_MAX;
/* Setup to release spin count in fork_exit(). */
@@ -246,6 +248,7 @@ cpu_fork_kthread_handler(struct thread *
td->td_pcb->pcb_x[9] = (uintptr_t)arg;
td->td_pcb->pcb_x[PCB_LR] = (uintptr_t)fork_trampoline;
td->td_pcb->pcb_sp = (uintptr_t)td->td_frame;
+ td->td_pcb->pcb_fpusaved = &td->td_pcb->pcb_fpustate;
td->td_pcb->pcb_vfpcpu = UINT_MAX;
}
Modified: head/sys/arm64/include/pcb.h
==============================================================================
--- head/sys/arm64/include/pcb.h Fri Oct 14 15:16:44 2016 (r307320)
+++ head/sys/arm64/include/pcb.h Fri Oct 14 15:53:48 2016 (r307321)
@@ -31,6 +31,8 @@
#ifndef LOCORE
+#include <machine/vfp.h>
+
struct trapframe;
#define PCB_LR 30
@@ -49,13 +51,17 @@ struct pcb {
#define PCB_SINGLE_STEP_SHIFT 0
#define PCB_SINGLE_STEP (1 << PCB_SINGLE_STEP_SHIFT)
- /* Place last to simplify the asm to access the rest if the struct */
- __uint128_t pcb_vfp[32];
- uint32_t pcb_fpcr;
- uint32_t pcb_fpsr;
+ struct vfpstate *pcb_fpusaved;
int pcb_fpflags;
#define PCB_FP_STARTED 0x01
u_int pcb_vfpcpu; /* Last cpu this thread ran VFP code */
+
+ /*
+ * The userspace VFP state. The pcb_fpusaved pointer will point to
+ * this unless the kernel has allocated a VFP context.
+ * Place last to simplify the asm to access the rest if the struct.
+ */
+ struct vfpstate pcb_fpustate;
};
#ifdef _KERNEL
Modified: head/sys/arm64/include/vfp.h
==============================================================================
--- head/sys/arm64/include/vfp.h Fri Oct 14 15:16:44 2016 (r307320)
+++ head/sys/arm64/include/vfp.h Fri Oct 14 15:53:48 2016 (r307321)
@@ -35,6 +35,12 @@
#ifdef _KERNEL
#ifndef LOCORE
+struct vfpstate {
+ __uint128_t vfp_regs[32];
+ uint32_t vfp_fpcr;
+ uint32_t vfp_fpsr;
+};
+
void vfp_init(void);
void vfp_discard(struct thread *);
void vfp_restore_state(void);
More information about the svn-src-all
mailing list