Date: Wed, 08 Apr 2026 14:01:43 +0000 From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: f6f5d927bf75 - stable/15 - arm64: Have a common call to userret Message-ID: <69d65fc7.3b799.4acab9ef@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch stable/15 has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=f6f5d927bf756810bb16c5f90540453eb309eb21 commit f6f5d927bf756810bb16c5f90540453eb309eb21 Author: Andrew Turner <andrew@FreeBSD.org> AuthorDate: 2026-03-17 17:10:07 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> CommitDate: 2026-04-08 13:59:54 +0000 arm64: Have a common call to userret Rather than each exception calling userret use a common copy. As syscallret already calls userret we need to skip it in that case. Reviewed by: kib Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D55250 (cherry picked from commit 14e97448fcebbe4b038eaf5628933abe5f9e690d) --- sys/arm64/arm64/trap.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index b3c68fa4826f..867e5c57f8e5 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -193,17 +193,19 @@ test_bs_fault(void *addr) addr == &generic_bs_poke_8f); } -static void +static bool svc_handler(struct thread *td, struct trapframe *frame) { if ((frame->tf_esr & ESR_ELx_ISS_MASK) == 0) { syscallenter(td); syscallret(td); + /* Skip userret as syscallret already called it */ + return (true); } else { call_trapsignal(td, SIGILL, ILL_ILLOPN, (void *)frame->tf_elr, ESR_ELx_EXCEPTION(frame->tf_esr)); - userret(td, frame); + return (false); } } @@ -220,7 +222,6 @@ align_abort(struct thread *td, struct trapframe *frame, uint64_t esr, call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr, ESR_ELx_EXCEPTION(frame->tf_esr)); - userret(td, frame); } @@ -231,7 +232,6 @@ external_abort(struct thread *td, struct trapframe *frame, uint64_t esr, if (lower) { call_trapsignal(td, SIGBUS, BUS_OBJERR, (void *)far, ESR_ELx_EXCEPTION(frame->tf_esr)); - userret(td, frame); return; } @@ -411,9 +411,6 @@ bad_far: frame->tf_elr, error); } } - - if (lower) - userret(td, frame); } static void @@ -667,6 +664,7 @@ do_el0_sync(struct thread *td, struct trapframe *frame) uint32_t exception; uint64_t esr, far; int dfsc; + bool skip_userret; /* Check we have a sane environment when entering from userland */ KASSERT((uintptr_t)get_pcpu() >= VM_MIN_KERNEL_ADDRESS, @@ -694,6 +692,7 @@ do_el0_sync(struct thread *td, struct trapframe *frame) CTR4(KTR_TRAP, "%s: exception=%lu, elr=0x%lx, esr=0x%lx", __func__, exception, frame->tf_elr, esr); + skip_userret = false; switch (exception) { case EXCP_FP_SIMD: #ifdef VFP @@ -705,7 +704,6 @@ do_el0_sync(struct thread *td, struct trapframe *frame) case EXCP_TRAP_FP: #ifdef VFP fpe_trap(td, (void *)frame->tf_elr, esr); - userret(td, frame); #else panic("VFP exception in userland"); #endif @@ -715,11 +713,10 @@ do_el0_sync(struct thread *td, struct trapframe *frame) if (!sve_restore_state(td)) call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)frame->tf_elr, exception); - userret(td, frame); break; case EXCP_SVC32: case EXCP_SVC64: - svc_handler(td, frame); + skip_userret = svc_handler(td, frame); break; case EXCP_INSN_ABORT_L: case EXCP_DATA_ABORT_L: @@ -741,22 +738,18 @@ do_el0_sync(struct thread *td, struct trapframe *frame) if (!undef_insn(frame)) call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)far, exception); - userret(td, frame); break; case EXCP_FPAC: call_trapsignal(td, SIGILL, ILL_ILLOPN, (void *)frame->tf_elr, exception); - userret(td, frame); break; case EXCP_SP_ALIGN: call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_sp, exception); - userret(td, frame); break; case EXCP_PC_ALIGN: call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr, exception); - userret(td, frame); break; case EXCP_BRKPT_EL0: case EXCP_BRK: @@ -765,12 +758,10 @@ do_el0_sync(struct thread *td, struct trapframe *frame) #endif /* COMPAT_FREEBSD32 */ call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_elr, exception); - userret(td, frame); break; case EXCP_WATCHPT_EL0: call_trapsignal(td, SIGTRAP, TRAP_TRACE, (void *)far, exception); - userret(td, frame); break; case EXCP_MSR: /* @@ -781,7 +772,6 @@ do_el0_sync(struct thread *td, struct trapframe *frame) if (!undef_insn(frame)) call_trapsignal(td, SIGILL, ILL_PRVOPC, (void *)frame->tf_elr, exception); - userret(td, frame); break; case EXCP_SOFTSTP_EL0: PROC_LOCK(td->td_proc); @@ -794,24 +784,22 @@ do_el0_sync(struct thread *td, struct trapframe *frame) PROC_UNLOCK(td->td_proc); call_trapsignal(td, SIGTRAP, TRAP_TRACE, (void *)frame->tf_elr, exception); - userret(td, frame); break; case EXCP_BTI: call_trapsignal(td, SIGILL, ILL_ILLOPC, (void *)frame->tf_elr, exception); - userret(td, frame); break; case EXCP_MOE: handle_moe(td, frame, esr); - userret(td, frame); break; default: call_trapsignal(td, SIGBUS, BUS_OBJERR, (void *)frame->tf_elr, exception); - userret(td, frame); break; } + if (!skip_userret) + userret(td, frame); KASSERT( (td->td_pcb->pcb_fpflags & ~(PCB_FP_USERMASK|PCB_FP_SVEVALID)) == 0, ("Kernel VFP flags set while entering userspace"));home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69d65fc7.3b799.4acab9ef>
