From nobody Mon Feb 07 15:25:06 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 36AAF19AD05E; Mon, 7 Feb 2022 15:25:07 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4JsqhM0ml1z4XRl; Mon, 7 Feb 2022 15:25:07 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1644247507; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LiamEtfff9ZP5WT7nqbMIDybKu/jS2STpKiPYsTuqTw=; b=B6nebFZmVlgdzp82DSjqD3CifvUxA/cNPTW/H0HFGhPpcMTekemo/AzjXR87A0x9rtvJRE W0VecjxqnXlQ32sYmoTWGmowxjO4A1XQwcur6p0fbG61qIMSv5C/D7AE1VN2W3yKfaw+Pn kOrXEtuKdJ1tVOXMU/R7fn5uvQIAxKOTKFPN/4dS7Xm4pQbW06irL6Aefu9H9V+e8wekle 78pUwXKJkvVa58Tzf8zP2fCc6Dm957itUJrTDisO4tjQ7en9xsQzdQ8ON+M2BmMZgadfU0 hY0lcSZ/PF7HaRmx7JtIfi6qtxvRNKiI1ZTTcIU72+Pfk+CylE4j0f8aUMZptw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id EEAE827EE4; Mon, 7 Feb 2022 15:25:06 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 217FP6LP007010; Mon, 7 Feb 2022 15:25:06 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 217FP6kx007009; Mon, 7 Feb 2022 15:25:06 GMT (envelope-from git) Date: Mon, 7 Feb 2022 15:25:06 GMT Message-Id: <202202071525.217FP6kx007009@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Andrew Turner Subject: git: 31cf95cec738 - main - Stop single stepping in signal handers on arm64 List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: andrew X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 31cf95cec738bdb51a652689e2f829addc3b984b Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1644247507; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LiamEtfff9ZP5WT7nqbMIDybKu/jS2STpKiPYsTuqTw=; b=S/mQQCpcWs5cSKjP+Skvql39TVJh77JO7N6JAf+SPv3WliMyAjOHvTQk4zS//ICjPTNvSf ARk6KwwsR1M3/SmR8qFJHQTalCb0d6lj+OIDSlGiPeCWQfgvSTCDIsJQeL9F71/GDz9IdF uVZrOEn8/8KnUYt7/CIDY31z3h7hriRQgKSXbtC/3nUfNUew8wJjYMwLlmYWFCKcbjXJgt CQDT6rHY5XdVtkMNJuzyoEYx0WFSSvrnNbcU8ioWmgik7Nvl4fyFUOYZFX//uh8vS57WaJ NRFlSZWmRE7zIoSO7w7DdRg9UQg0jNUxBj+vuIOwj1qMJ26+Bzp2Vi/ct8QYKg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1644247507; a=rsa-sha256; cv=none; b=uAWYueKaz/79VW3bvJODp8YTbkO1r0SX6KDu4UGfiEf2P2zpM5OtR2JnAjII3t20Ds7ce0 DZ7bjuFCHxK6JwrFirtAB4s09Y8biwFRNciZFi2DOT5pDhPzgz3YFa+bajhjdgJeusDbSH IBQBi94m/S6KhuZGyUaqBRusxbnH9RY0jxRsA/vBO9Jhrvm8yZDPWd8gTvOW3FrOL5rkeJ t+sWfXOBHqOqGvfMY34QkwoNi1rFF/U3MnTaE/crbwsiFn2dK1BjJpw6cuRPZe/cfSAEj8 eXIbdUJN1WEuKS75azz1WUVvLT7fCOJHfomKg93tonws91m40br0nvyM1vfwcQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=31cf95cec738bdb51a652689e2f829addc3b984b commit 31cf95cec738bdb51a652689e2f829addc3b984b Author: Andrew Turner AuthorDate: 2022-01-26 14:25:48 +0000 Commit: Andrew Turner CommitDate: 2022-02-07 15:03:23 +0000 Stop single stepping in signal handers on arm64 We should clear the single step flag when entering a signal hander and set it when returning. This fixes the ptrace__PT_STEP_with_signal test. While here add support for userspace to set the single step bit as on x86. This can be used by userspace for self tracing. Reviewed by: kib Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D34170 --- sys/arm64/arm64/exec_machdep.c | 39 +++++++++++++++++++--- sys/arm64/arm64/freebsd32_machdep.c | 30 ++++++++++++++++- sys/arm64/arm64/ptrace_machdep.c | 12 ++++--- sys/arm64/arm64/trap.c | 12 ++++--- sys/arm64/include/armreg.h | 3 ++ tests/sys/kern/basic_signal.c | 66 +++++++++++++++++++++++++++++++++++++ 6 files changed, 148 insertions(+), 14 deletions(-) diff --git a/sys/arm64/arm64/exec_machdep.c b/sys/arm64/arm64/exec_machdep.c index 820bb4a68108..d29ddabd23bf 100644 --- a/sys/arm64/arm64/exec_machdep.c +++ b/sys/arm64/arm64/exec_machdep.c @@ -97,7 +97,6 @@ set_regs(struct thread *td, struct reg *regs) frame = td->td_frame; frame->tf_sp = regs->sp; frame->tf_lr = regs->lr; - frame->tf_spsr &= ~PSR_FLAGS; memcpy(frame->tf_x, regs->x, sizeof(frame->tf_x)); @@ -109,12 +108,27 @@ set_regs(struct thread *td, struct reg *regs) * it put it. */ frame->tf_elr = regs->x[15]; - frame->tf_spsr |= regs->x[16] & PSR_FLAGS; + frame->tf_spsr &= ~PSR_SETTABLE_32; + frame->tf_spsr |= regs->x[16] & PSR_SETTABLE_32; + /* Don't allow userspace to ask to continue single stepping. + * The SPSR.SS field doesn't exist when the EL1 is AArch32. + * As the SPSR.DIT field has moved in its place don't + * allow userspace to set the SPSR.SS field. + */ } else #endif { frame->tf_elr = regs->elr; - frame->tf_spsr |= regs->spsr & PSR_FLAGS; + frame->tf_spsr &= ~PSR_SETTABLE_64; + frame->tf_spsr |= regs->spsr & PSR_SETTABLE_64; + /* Enable single stepping if userspace asked fot it */ + if ((frame->tf_spsr & PSR_SS) != 0) { + td->td_pcb->pcb_flags |= PCB_SINGLE_STEP; + + WRITE_SPECIALREG(mdscr_el1, + READ_SPECIALREG(mdscr_el1) | MDSCR_SS); + isb(); + } } return (0); } @@ -333,8 +347,8 @@ set_regs32(struct thread *td, struct reg32 *regs) tf->tf_x[13] = regs->r_sp; tf->tf_x[14] = regs->r_lr; tf->tf_elr = regs->r_pc; - tf->tf_spsr &= ~PSR_FLAGS; - tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS; + tf->tf_spsr &= ~PSR_SETTABLE_32; + tf->tf_spsr |= regs->r_cpsr & PSR_SETTABLE_32; return (0); } @@ -450,6 +464,13 @@ set_mcontext(struct thread *td, mcontext_t *mcp) tf->tf_lr = mcp->mc_gpregs.gp_lr; tf->tf_elr = mcp->mc_gpregs.gp_elr; tf->tf_spsr = mcp->mc_gpregs.gp_spsr; + if ((tf->tf_spsr & PSR_SS) != 0) { + td->td_pcb->pcb_flags |= PCB_SINGLE_STEP; + + WRITE_SPECIALREG(mdscr_el1, + READ_SPECIALREG(mdscr_el1) | MDSCR_SS); + isb(); + } set_fpcontext(td, mcp); return (0); @@ -604,6 +625,14 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) tf->tf_sp = (register_t)fp; tf->tf_lr = (register_t)p->p_sysent->sv_sigcode_base; + /* Clear the single step flag while in the signal handler */ + if ((td->td_pcb->pcb_flags & PCB_SINGLE_STEP) != 0) { + td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP; + WRITE_SPECIALREG(mdscr_el1, + READ_SPECIALREG(mdscr_el1) & ~MDSCR_SS); + isb(); + } + CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_elr, tf->tf_sp); diff --git a/sys/arm64/arm64/freebsd32_machdep.c b/sys/arm64/arm64/freebsd32_machdep.c index 251b124d24c6..c43d8f4ad8e6 100644 --- a/sys/arm64/arm64/freebsd32_machdep.c +++ b/sys/arm64/arm64/freebsd32_machdep.c @@ -198,14 +198,34 @@ set_mcontext32(struct thread *td, mcontext32_t *mcp) { struct trapframe *tf; mcontext32_vfp_t mc_vfp; + uint32_t spsr; int i; tf = td->td_frame; + spsr = mcp->mc_gregset[16]; + /* + * There is no PSR_SS in the 32-bit kernel so ignore it if it's set + * as we will set it later if needed. + */ + if ((spsr & ~(PSR_SETTABLE_32 | PSR_SS)) != + (tf->tf_spsr & ~(PSR_SETTABLE_32 | PSR_SS))) + return (EINVAL); + + spsr &= PSR_SETTABLE_32; + spsr |= tf->tf_spsr & ~PSR_SETTABLE_32; + + if ((td->td_dbgflags & TDB_STEP) != 0) { + spsr |= PSR_SS; + td->td_pcb->pcb_flags |= PCB_SINGLE_STEP; + WRITE_SPECIALREG(mdscr_el1, + READ_SPECIALREG(mdscr_el1) | MDSCR_SS); + } + for (i = 0; i < 15; i++) tf->tf_x[i] = mcp->mc_gregset[i]; tf->tf_elr = mcp->mc_gregset[15]; - tf->tf_spsr = mcp->mc_gregset[16]; + tf->tf_spsr = spsr; #ifdef VFP if (mcp->mc_vfp_size == sizeof(mc_vfp) && mcp->mc_vfp_ptr != 0) { if (copyin((void *)(uintptr_t)mcp->mc_vfp_ptr, &mc_vfp, @@ -404,6 +424,14 @@ freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) else tf->tf_spsr &= ~PSR_T; + /* Clear the single step flag while in the signal handler */ + if ((td->td_pcb->pcb_flags & PCB_SINGLE_STEP) != 0) { + td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP; + WRITE_SPECIALREG(mdscr_el1, + READ_SPECIALREG(mdscr_el1) & ~MDSCR_SS); + isb(); + } + CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_x[14], tf->tf_x[13]); diff --git a/sys/arm64/arm64/ptrace_machdep.c b/sys/arm64/arm64/ptrace_machdep.c index e36ae38d5d68..3f362e5343cd 100644 --- a/sys/arm64/arm64/ptrace_machdep.c +++ b/sys/arm64/arm64/ptrace_machdep.c @@ -59,18 +59,22 @@ ptrace_set_pc(struct thread *td, u_long addr) int ptrace_single_step(struct thread *td) { - - td->td_frame->tf_spsr |= PSR_SS; - td->td_pcb->pcb_flags |= PCB_SINGLE_STEP; + PROC_LOCK_ASSERT(td->td_proc, MA_OWNED); + if ((td->td_frame->tf_spsr & PSR_SS) == 0) { + td->td_frame->tf_spsr |= PSR_SS; + td->td_pcb->pcb_flags |= PCB_SINGLE_STEP; + td->td_dbgflags |= TDB_STEP; + } return (0); } int ptrace_clear_single_step(struct thread *td) { - + PROC_LOCK_ASSERT(td->td_proc, MA_OWNED); td->td_frame->tf_spsr &= ~PSR_SS; td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP; + td->td_dbgflags &= ~TDB_STEP; return (0); } diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index 4a2a6b2f7c7c..93167f4d2347 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -620,10 +620,14 @@ do_el0_sync(struct thread *td, struct trapframe *frame) userret(td, frame); break; case EXCP_SOFTSTP_EL0: - td->td_frame->tf_spsr &= ~PSR_SS; - td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP; - WRITE_SPECIALREG(mdscr_el1, - READ_SPECIALREG(mdscr_el1) & ~MDSCR_SS); + PROC_LOCK(td->td_proc); + if ((td->td_dbgflags & TDB_STEP) != 0) { + td->td_frame->tf_spsr &= ~PSR_SS; + td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP; + WRITE_SPECIALREG(mdscr_el1, + READ_SPECIALREG(mdscr_el1) & ~MDSCR_SS); + } + PROC_UNLOCK(td->td_proc); call_trapsignal(td, SIGTRAP, TRAP_TRACE, (void *)frame->tf_elr, exception); userret(td, frame); diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index 79473a41099e..c1da3abbde0f 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -1315,6 +1315,9 @@ #define PSR_Z 0x40000000 #define PSR_N 0x80000000 #define PSR_FLAGS 0xf0000000 +/* PSR fields that can be set from 32-bit and 64-bit processes */ +#define PSR_SETTABLE_32 PSR_FLAGS +#define PSR_SETTABLE_64 (PSR_FLAGS | PSR_SS) /* TCR_EL1 - Translation Control Register */ /* Bits 63:59 are reserved */ diff --git a/tests/sys/kern/basic_signal.c b/tests/sys/kern/basic_signal.c index b94ebeb1ba23..1dcb9ff064fc 100644 --- a/tests/sys/kern/basic_signal.c +++ b/tests/sys/kern/basic_signal.c @@ -10,6 +10,20 @@ #include #include +#if defined(__aarch64__) +#include +#define SET_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_gpregs.gp_spsr |= PSR_SS +#define CLR_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_gpregs.gp_spsr &= ~PSR_SS +#elif defined(__amd64__) +#include +#define SET_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_rflags |= PSL_T +#define CLR_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_rflags &= ~PSL_T +#elif defined(__i386__) +#include +#define SET_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_eflags |= PSL_T +#define CLR_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_eflags &= ~PSL_T +#endif + static volatile sig_atomic_t signal_fired = 0; static void @@ -62,6 +76,55 @@ ATF_TC_BODY(signal_test, tc) ATF_CHECK(signal_fired == 3); } +/* + * Check setting the machine dependent single step flag works when supported. + */ +#ifdef SET_TRACE_FLAG +static volatile sig_atomic_t trap_signal_fired = 0; + +static void +trap_sig_handler(int signo, siginfo_t *info __unused, void *_ucp) +{ + ucontext_t *ucp = _ucp; + + if (trap_signal_fired < 9) { + SET_TRACE_FLAG(ucp); + } else { + CLR_TRACE_FLAG(ucp); + } + trap_signal_fired++; +} + +ATF_TC(trap_signal_test); + +ATF_TC_HEAD(trap_signal_test, tc) +{ + + atf_tc_set_md_var(tc, "descr", + "Testing signal handler setting the MD single step flag"); +} + +ATF_TC_BODY(trap_signal_test, tc) +{ + /* + * Setup the signal handlers + */ + struct sigaction sa = { + .sa_sigaction = trap_sig_handler, + .sa_flags = SA_SIGINFO, + }; + ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0); + ATF_REQUIRE(sigaction(SIGTRAP, &sa, NULL) == 0); + + /* + * Fire SIGTRAP + */ + ATF_CHECK(trap_signal_fired == 0); + ATF_REQUIRE(raise(SIGTRAP) == 0); + ATF_CHECK(trap_signal_fired == 10); +} +#endif + /* * Special tests for 32-bit arm. We can call thumb code (really just t32) from * normal (a32) mode and vice versa. Likewise, signals can interrupt a T32 @@ -150,6 +213,9 @@ ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, signal_test); +#ifdef SET_TRACE_FLAG + ATF_TP_ADD_TC(tp, trap_signal_test); +#endif #ifdef __arm__ ATF_TP_ADD_TC(tp, signal_test_T32_to_A32); ATF_TP_ADD_TC(tp, signal_test_A32_to_T32);