Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102138973
D34170.id102454.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D34170.id102454.diff
View Options
Index: sys/arm64/arm64/exec_machdep.c
===================================================================
--- sys/arm64/arm64/exec_machdep.c
+++ sys/arm64/arm64/exec_machdep.c
@@ -97,7 +97,6 @@
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 @@
* 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 @@
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 @@
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 @@
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);
Index: sys/arm64/arm64/freebsd32_machdep.c
===================================================================
--- sys/arm64/arm64/freebsd32_machdep.c
+++ sys/arm64/arm64/freebsd32_machdep.c
@@ -198,14 +198,34 @@
{
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 @@
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]);
Index: sys/arm64/arm64/ptrace_machdep.c
===================================================================
--- sys/arm64/arm64/ptrace_machdep.c
+++ sys/arm64/arm64/ptrace_machdep.c
@@ -59,18 +59,22 @@
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);
}
Index: sys/arm64/arm64/trap.c
===================================================================
--- sys/arm64/arm64/trap.c
+++ sys/arm64/arm64/trap.c
@@ -620,10 +620,14 @@
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);
Index: sys/arm64/include/armreg.h
===================================================================
--- sys/arm64/include/armreg.h
+++ 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 */
Index: tests/sys/kern/basic_signal.c
===================================================================
--- tests/sys/kern/basic_signal.c
+++ tests/sys/kern/basic_signal.c
@@ -10,6 +10,20 @@
#include <stdbool.h>
#include <stdlib.h>
+#if defined(__aarch64__)
+#include <machine/armreg.h>
+#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 <machine/psl.h>
+#define SET_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_rflags |= PSL_T
+#define CLR_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_rflags &= ~PSR_T
+#elif defined(__i386__)
+#include <machine/psl.h>
+#define SET_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_eflags |= PSL_T
+#define CLR_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_eflags &= ~PSR_T
+#endif
+
static volatile sig_atomic_t signal_fired = 0;
static void
@@ -62,6 +76,55 @@
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_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);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 9, 2:37 AM (19 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14548443
Default Alt Text
D34170.id102454.diff (8 KB)
Attached To
Mode
D34170: Stop single stepping in signal handers on arm64
Attached
Detach File
Event Timeline
Log In to Comment