Page MenuHomeFreeBSD

D29060.diff
No OneTemporary

D29060.diff

diff --git a/sys/arm64/arm64/elf32_machdep.c b/sys/arm64/arm64/elf32_machdep.c
--- a/sys/arm64/arm64/elf32_machdep.c
+++ b/sys/arm64/arm64/elf32_machdep.c
@@ -51,6 +51,9 @@
#include <sys/vnode.h>
#include <machine/elf.h>
+#ifdef VFP
+#include <machine/vfp.h>
+#endif
#include <compat/freebsd32/freebsd32_util.h>
@@ -251,6 +254,10 @@
tf->tf_x[14] = imgp->entry_addr;
tf->tf_elr = imgp->entry_addr;
tf->tf_spsr = PSR_M_32;
+
+#ifdef VFP
+ vfp_reset_state(td, td->td_pcb);
+#endif
}
void
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -552,6 +552,7 @@
exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
{
struct trapframe *tf = td->td_frame;
+ struct pcb *pcb = td->td_pcb;
memset(tf, 0, sizeof(struct trapframe));
@@ -559,6 +560,12 @@
tf->tf_sp = STACKALIGN(stack);
tf->tf_lr = imgp->entry_addr;
tf->tf_elr = imgp->entry_addr;
+
+#ifdef VFP
+ vfp_reset_state(td, pcb);
+#endif
+
+ /* TODO: Shouldn't we also reset pcb_dbg_regs? */
}
/* Sanity check these are the same size, they will be memcpy'd to and fro */
diff --git a/sys/arm64/arm64/vfp.c b/sys/arm64/arm64/vfp.c
--- a/sys/arm64/arm64/vfp.c
+++ b/sys/arm64/arm64/vfp.c
@@ -33,6 +33,7 @@
#ifdef VFP
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/limits.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/pcpu.h>
@@ -199,6 +200,26 @@
critical_exit();
}
+/*
+ * Reset the FP state to avoid leaking state from the parent process across
+ * execve() (and to ensure that we get a consistent floating point environment
+ * in every new process).
+ */
+void
+vfp_reset_state(struct thread *td, struct pcb *pcb)
+{
+ critical_enter();
+ bzero(&pcb->pcb_fpustate.vfp_regs, sizeof(pcb->pcb_fpustate.vfp_regs));
+ KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate,
+ ("pcb_fpusaved should point to pcb_fpustate."));
+ pcb->pcb_fpustate.vfp_fpcr = initial_fpcr;
+ pcb->pcb_fpustate.vfp_fpsr = 0;
+ pcb->pcb_vfpcpu = UINT_MAX;
+ pcb->pcb_fpflags = 0;
+ vfp_discard(td);
+ critical_exit();
+}
+
void
vfp_restore_state(void)
{
diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c
--- a/sys/arm64/arm64/vm_machdep.c
+++ b/sys/arm64/arm64/vm_machdep.c
@@ -108,7 +108,6 @@
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;
- td2->td_pcb->pcb_fpusaved->vfp_fpcr = initial_fpcr;
/* Setup to release spin count in fork_exit(). */
td2->td_md.md_spinlock_count = 1;
diff --git a/sys/arm64/include/vfp.h b/sys/arm64/include/vfp.h
--- a/sys/arm64/include/vfp.h
+++ b/sys/arm64/include/vfp.h
@@ -68,6 +68,7 @@
void vfp_init(void);
void vfp_discard(struct thread *);
+void vfp_reset_state(struct thread *, struct pcb *);
void vfp_restore_state(void);
void vfp_save_state(struct thread *, struct pcb *);
diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -57,6 +57,10 @@
#include <compat/linux/linux_util.h>
#include <compat/linux/linux_vdso.h>
+#ifdef VFP
+#include <machine/vfp.h>
+#endif
+
MODULE_VERSION(linux64elf, 1);
const char *linux_kplatform;
@@ -360,6 +364,10 @@
regs->tf_lr = 0xffffffffffffffff;
#endif
regs->tf_elr = imgp->entry_addr;
+
+#ifdef VFP
+ vfp_reset_state(td, td->td_pcb);
+#endif
}
int

File Metadata

Mime Type
text/plain
Expires
Wed, Oct 2, 3:42 PM (21 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13362863
Default Alt Text
D29060.diff (3 KB)

Event Timeline