Page MenuHomeFreeBSD

D38698.diff
No OneTemporary

D38698.diff

diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -380,6 +380,7 @@
thread0.td_pcb->pcb_fpflags = 0;
thread0.td_pcb->pcb_vfpcpu = -1;
thread0.td_pcb->pcb_vfpstate.fpscr = VFPSCR_DN;
+ thread0.td_pcb->pcb_vfpsaved = &thread0.td_pcb->pcb_vfpstate;
thread0.td_frame = &proc0_tf;
pcpup->pc_curpcb = thread0.td_pcb;
}
diff --git a/sys/arm/arm/vfp.c b/sys/arm/arm/vfp.c
--- a/sys/arm/arm/vfp.c
+++ b/sys/arm/arm/vfp.c
@@ -34,6 +34,7 @@
#ifdef VFP
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/limits.h>
#include <sys/proc.h>
#include <sys/imgact_elf.h>
#include <sys/kernel.h>
@@ -251,17 +252,45 @@
curpcb = curthread->td_pcb;
cpu = PCPU_GET(cpuid);
if (curpcb->pcb_vfpcpu != cpu || curthread != PCPU_GET(fpcurthread)) {
- if (curpcb->pcb_vfpsaved == NULL)
- curpcb->pcb_vfpsaved = &curpcb->pcb_vfpstate;
vfp_restore(curpcb->pcb_vfpsaved);
curpcb->pcb_vfpcpu = cpu;
PCPU_SET(fpcurthread, curthread);
}
critical_exit();
+
+ KASSERT(curpcb->pcb_vfpsaved == &curpcb->pcb_vfpstate,
+ ("Kernel VFP state in use when entering userspace"));
+
return (0);
}
+/*
+ * Update the VFP state for a forked process or new thread. The PCB will
+ * have been copied from the old thread.
+ * The code is heavily based on arm64 logic.
+ */
+void
+vfp_new_thread(struct thread *newtd, struct thread *oldtd, bool fork)
+{
+ struct pcb *newpcb;
+
+ newpcb = newtd->td_pcb;
+
+ /* Kernel threads start with clean VFP */
+ if ((oldtd->td_pflags & TDP_KTHREAD) != 0) {
+ newpcb->pcb_fpflags &=
+ ~(PCB_FP_STARTED | PCB_FP_KERN | PCB_FP_NOSAVE);
+ } else {
+ MPASS((newpcb->pcb_fpflags & (PCB_FP_KERN|PCB_FP_NOSAVE)) == 0);
+ if (!fork) {
+ newpcb->pcb_fpflags &= ~PCB_FP_STARTED;
+ }
+ }
+
+ newpcb->pcb_vfpsaved = &newpcb->pcb_vfpstate;
+ newpcb->pcb_vfpcpu = UINT_MAX;
+}
/*
* Restore the given state to the VFP hardware.
*/
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -137,9 +137,9 @@
pcb2->pcb_regs.sf_sp = STACKALIGN(td2->td_frame);
pcb2->pcb_regs.sf_tpidrurw = (register_t)get_tls();
- pcb2->pcb_vfpcpu = -1;
- pcb2->pcb_vfpsaved = &pcb2->pcb_vfpstate;
- pcb2->pcb_vfpstate.fpscr = initial_fpscr;
+#ifdef VFP
+ vfp_new_thread(td2, td1, true);
+#endif
tf = td2->td_frame;
tf->tf_spsr &= ~PSR_C;
@@ -216,6 +216,10 @@
td->td_frame->tf_spsr &= ~PSR_C;
td->td_frame->tf_r0 = 0;
+#ifdef VFP
+ vfp_new_thread(td, td0, false);
+#endif
+
/* Setup to release spin count in fork_exit(). */
td->td_md.md_spinlock_count = 1;
td->td_md.md_saved_cspr = PSR_SVC32_MODE;
diff --git a/sys/arm/include/vfp.h b/sys/arm/include/vfp.h
--- a/sys/arm/include/vfp.h
+++ b/sys/arm/include/vfp.h
@@ -157,6 +157,7 @@
void get_vfpcontext(struct thread *, mcontext_vfp_t *);
void set_vfpcontext(struct thread *, mcontext_vfp_t *);
void vfp_init(void);
+void vfp_new_thread(struct thread*, struct thread*, bool);
void vfp_store(struct vfp_state *, boolean_t);
void vfp_discard(struct thread *);
void vfp_restore_state(void);

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 16, 3:38 PM (20 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14660781
Default Alt Text
D38698.diff (3 KB)

Event Timeline