git: 4a06b28a15ad - main - Add compat support for struct reg on arm64
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 23 Mar 2023 19:02:48 UTC
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