Page MenuHomeFreeBSD

D34170.id102453.diff
No OneTemporary

D34170.id102453.diff

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,10 @@
#include <stdbool.h>
#include <stdlib.h>
+#ifdef __aarch64__
+#include <machine/armreg.h>
+#endif
+
static volatile sig_atomic_t signal_fired = 0;
static void
@@ -62,6 +66,56 @@
ATF_CHECK(signal_fired == 3);
}
+/*
+ * Check setting the machine dependent single step flag works when supported.
+ */
+/* TODO: Add x86 support */
+#ifdef __aarch64__
+static volatile sig_atomic_t trap_signal_fired = 0;
+
+#include <stdio.h>
+static void
+trap_sig_handler(int signo, siginfo_t *info __unused, void *_ucp)
+{
+ ucontext_t *ucp = _ucp;
+
+ if (trap_signal_fired < 9)
+ ucp->uc_mcontext.mc_gpregs.gp_spsr |= PSR_SS;
+ else
+ ucp->uc_mcontext.mc_gpregs.gp_spsr &= ~PSR_SS;
+ 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 +204,9 @@
{
ATF_TP_ADD_TC(tp, signal_test);
+#ifdef __aarch64__
+ 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

Mime Type
text/plain
Expires
Sat, Nov 9, 4:47 AM (20 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14550564
Default Alt Text
D34170.id102453.diff (7 KB)

Event Timeline