Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 Mar 2023 19:02:48 GMT
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 4a06b28a15ad - main - Add compat support for struct reg on arm64
Message-ID:  <202303231902.32NJ2mS3039346@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=4a06b28a15ad2e33cc2b8c16ce2b946a517d758a

commit 4a06b28a15ad2e33cc2b8c16ce2b946a517d758a
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2023-03-20 17:38:39 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2023-03-23 18:56:26 +0000

    Add compat support for struct reg on arm64
    
    The size of the spsr field in struct reg has changed. Mask the bits
    that userspace doesn't know about out as they may be invalid.
    
    While here add a comment why we don't need compat support in set_regs.
    
    Sponsored by:   Arm Ltd
---
 sys/arm64/arm64/exec_machdep.c | 29 ++++++++++++++++++++++++++++-
 sys/sys/param.h                |  1 +
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/sys/arm64/arm64/exec_machdep.c b/sys/arm64/arm64/exec_machdep.c
index 7ead30a05663..a51ff3aeca86 100644
--- a/sys/arm64/arm64/exec_machdep.c
+++ b/sys/arm64/arm64/exec_machdep.c
@@ -125,6 +125,13 @@ set_regs(struct thread *td, struct reg *regs)
 #endif
 	{
 		frame->tf_elr = regs->elr;
+		/*
+		 * frame->tf_spsr and regs->spsr on FreeBSD 13 was 32-bit
+		 * where from 14 they are 64 bit. As PSR_SETTABLE_64 clears
+		 * the upper 32 bits no compatibility handling is needed,
+		 * however if this is ever not the case we will need to add
+		 * these, similar to how it is done in set_mcontext.
+		 */
 		frame->tf_spsr &= ~PSR_SETTABLE_64;
 		frame->tf_spsr |= regs->spsr & PSR_SETTABLE_64;
 		/* Enable single stepping if userspace asked fot it */
@@ -456,10 +463,22 @@ get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
 int
 set_mcontext(struct thread *td, mcontext_t *mcp)
 {
+#define	PSR_13_MASK	0xfffffffful
 	struct trapframe *tf = td->td_frame;
 	uint64_t spsr;
 
 	spsr = mcp->mc_gpregs.gp_spsr;
+#ifdef COMPAT_FREEBSD13
+	if (td->td_proc->p_osrel < P_OSREL_ARM64_SPSR) {
+		/*
+		 * Before FreeBSD 14 gp_spsr was 32 bit. The size of mc_gpregs
+		 * was identical because of padding so mask of the upper bits
+		 * that may be invalid on earlier releases.
+		 */
+		spsr &= PSR_13_MASK;
+	}
+#endif
+
 	if ((spsr & PSR_M_MASK) != PSR_M_EL0t ||
 	    (spsr & PSR_AARCH32) != 0 ||
 	    (spsr & PSR_DAIF) != (td->td_frame->tf_spsr & PSR_DAIF))
@@ -470,7 +489,14 @@ set_mcontext(struct thread *td, mcontext_t *mcp)
 	tf->tf_sp = mcp->mc_gpregs.gp_sp;
 	tf->tf_lr = mcp->mc_gpregs.gp_lr;
 	tf->tf_elr = mcp->mc_gpregs.gp_elr;
-	tf->tf_spsr = mcp->mc_gpregs.gp_spsr;
+#ifdef COMPAT_FREEBSD13
+	if (td->td_proc->p_osrel < P_OSREL_ARM64_SPSR) {
+		/* Keep the upper 32 bits of spsr on older releases */
+		tf->tf_spsr &= ~PSR_13_MASK;
+		tf->tf_spsr |= spsr;
+	} else
+#endif
+		tf->tf_spsr = spsr;
 	if ((tf->tf_spsr & PSR_SS) != 0) {
 		td->td_pcb->pcb_flags |= PCB_SINGLE_STEP;
 
@@ -481,6 +507,7 @@ set_mcontext(struct thread *td, mcontext_t *mcp)
 	set_fpcontext(td, mcp);
 
 	return (0);
+#undef PSR_13_MASK
 }
 
 static void
diff --git a/sys/sys/param.h b/sys/sys/param.h
index a613dbf7f2b1..d3bdca7c42e7 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -108,6 +108,7 @@
 #define	P_OSREL_CK_INODE		1300005
 #define	P_OSREL_POWERPC_NEW_AUX_ARGS	1300070
 #define	P_OSREL_TIDPID			1400079
+#define	P_OSREL_ARM64_SPSR		1400084
 
 #define	P_OSREL_MAJOR(x)		((x) / 100000)
 #endif



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