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
This commit is contained in:
Andrew Turner 2023-03-20 17:38:39 +00:00 committed by Oscar Zhao
parent 76d8efc2b5
commit 032a1ed4bc
2 changed files with 29 additions and 1 deletions

View File

@ -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

View File

@ -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