Skip site navigation (1)Skip section navigation (2)
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>