From owner-dev-commits-src-all@freebsd.org Wed Mar 10 12:45:21 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 68F505AFC1D; Wed, 10 Mar 2021 12:45:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DwWy92ZTtz3GMM; Wed, 10 Mar 2021 12:45:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4B35074D8; Wed, 10 Mar 2021 12:45:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 12ACjLkK064811; Wed, 10 Mar 2021 12:45:21 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 12ACjLn7064810; Wed, 10 Mar 2021 12:45:21 GMT (envelope-from git) Date: Wed, 10 Mar 2021 12:45:21 GMT Message-Id: <202103101245.12ACjLn7064810@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Alex Richardson Subject: git: 953a7d7c61f3 - main - Arch64: Clear VFP state on execve() MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: arichardson X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 953a7d7c61f3b2f5351dfe668510ec782ae282e8 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Mar 2021 12:45:21 -0000 The branch main has been updated by arichardson: URL: https://cgit.FreeBSD.org/src/commit/?id=953a7d7c61f3b2f5351dfe668510ec782ae282e8 commit 953a7d7c61f3b2f5351dfe668510ec782ae282e8 Author: Alex Richardson AuthorDate: 2021-03-09 19:11:40 +0000 Commit: Alex Richardson CommitDate: 2021-03-10 12:44:42 +0000 Arch64: Clear VFP state on execve() I noticed that many of the math-related tests were failing on AArch64. After a lot of debugging, I noticed that the floating point exception flags were not being reset when starting a new process. This change resets the VFP inside exec_setregs() to ensure no VFP register state is leaked from parent processes to children. This commit also moves the clearing of fpcr that was added in 65618fdda0f27 from fork() to execve() since that makes more sense: fork() can retain current register values, but execve() should result in a well-defined clean state. Reviewed By: andrew MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D29060 --- sys/arm64/arm64/elf32_machdep.c | 7 +++++++ sys/arm64/arm64/machdep.c | 7 +++++++ sys/arm64/arm64/vfp.c | 21 +++++++++++++++++++++ sys/arm64/arm64/vm_machdep.c | 1 - sys/arm64/include/vfp.h | 1 + sys/arm64/linux/linux_sysvec.c | 8 ++++++++ 6 files changed, 44 insertions(+), 1 deletion(-) diff --git a/sys/arm64/arm64/elf32_machdep.c b/sys/arm64/arm64/elf32_machdep.c index 916633650d69..84b62caf8590 100644 --- a/sys/arm64/arm64/elf32_machdep.c +++ b/sys/arm64/arm64/elf32_machdep.c @@ -51,6 +51,9 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef VFP +#include +#endif #include @@ -251,6 +254,10 @@ freebsd32_setregs(struct thread *td, struct image_params *imgp, 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 index 73b06beeba7e..91f0a31ebe36 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -552,6 +552,7 @@ void 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 @@ exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack) 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 index 23c782c6dccb..5fa420e668c1 100644 --- a/sys/arm64/arm64/vfp.c +++ b/sys/arm64/arm64/vfp.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #ifdef VFP #include #include +#include #include #include #include @@ -199,6 +200,26 @@ vfp_save_state(struct thread *td, struct pcb *pcb) 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 index 9a496b40ec98..0193048e2697 100644 --- a/sys/arm64/arm64/vm_machdep.c +++ b/sys/arm64/arm64/vm_machdep.c @@ -108,7 +108,6 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) 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 index b0ba01a2a319..3632e5eaa396 100644 --- a/sys/arm64/include/vfp.h +++ b/sys/arm64/include/vfp.h @@ -68,6 +68,7 @@ struct thread; 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 index 1d628ffe6ecb..67feacfa876b 100644 --- a/sys/arm64/linux/linux_sysvec.c +++ b/sys/arm64/linux/linux_sysvec.c @@ -57,6 +57,10 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef VFP +#include +#endif + MODULE_VERSION(linux64elf, 1); const char *linux_kplatform; @@ -360,6 +364,10 @@ linux_exec_setregs(struct thread *td, struct image_params *imgp, regs->tf_lr = 0xffffffffffffffff; #endif regs->tf_elr = imgp->entry_addr; + +#ifdef VFP + vfp_reset_state(td, td->td_pcb); +#endif } int