Date: Tue, 17 Mar 2026 17:11:41 +0000 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: 14e97448fceb - main - arm64: Have a common call to userret Message-ID: <69b98b4d.2237d.6aa3ea3c@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=14e97448fcebbe4b038eaf5628933abe5f9e690d commit 14e97448fcebbe4b038eaf5628933abe5f9e690d Author: Andrew Turner <andrew@FreeBSD.org> AuthorDate: 2026-03-17 17:10:07 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> CommitDate: 2026-03-17 17:10:40 +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 --- 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 3ce0b29f0b82..ad461aa1bffc 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; } @@ -416,9 +416,6 @@ bad_far: frame->tf_elr, error); } } - - if (lower) - userret(td, frame); } static void @@ -672,6 +669,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, @@ -699,6 +697,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 @@ -710,7 +709,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 @@ -720,11 +718,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: @@ -746,22 +743,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: @@ -770,12 +763,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: /* @@ -786,7 +777,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); @@ -799,24 +789,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?69b98b4d.2237d.6aa3ea3c>
