@@ -168,11 +168,11 @@ struct pt_regs {
};
u64 orig_x0;
#ifdef __AARCH64EB__
- u32 unused2;
+ u32 ss_enable; /* Kernel single-step for a task */
s32 syscallno;
#else
s32 syscallno;
- u32 unused2;
+ u32 ss_enable;
#endif
u64 orig_addr_limit;
@@ -62,6 +62,7 @@ int main(void)
DEFINE(S_PSTATE, offsetof(struct pt_regs, pstate));
DEFINE(S_PC, offsetof(struct pt_regs, pc));
DEFINE(S_SYSCALLNO, offsetof(struct pt_regs, syscallno));
+ DEFINE(S_SS_ENABLE, offsetof(struct pt_regs, ss_enable));
DEFINE(S_ORIG_ADDR_LIMIT, offsetof(struct pt_regs, orig_addr_limit));
DEFINE(S_PMR_SAVE, offsetof(struct pt_regs, pmr_save));
DEFINE(S_STACKFRAME, offsetof(struct pt_regs, stackframe));
@@ -409,7 +409,7 @@ void kernel_enable_single_step(struct pt_regs *regs)
{
WARN_ON(!irqs_disabled());
set_regs_spsr_ss(regs);
- mdscr_write(mdscr_read() | DBG_MDSCR_SS);
+ regs->ss_enable = DBG_MDSCR_SS;
enable_debug_monitors(DBG_ACTIVE_EL1);
}
NOKPROBE_SYMBOL(kernel_enable_single_step);
@@ -417,7 +417,8 @@ NOKPROBE_SYMBOL(kernel_enable_single_step);
void kernel_disable_single_step(struct pt_regs *regs)
{
WARN_ON(!irqs_disabled());
- mdscr_write(mdscr_read() & ~DBG_MDSCR_SS);
+ regs->ss_enable = 0;
+ clear_regs_spsr_ss(regs);
disable_debug_monitors(DBG_ACTIVE_EL1);
}
NOKPROBE_SYMBOL(kernel_disable_single_step);
@@ -425,7 +426,7 @@ NOKPROBE_SYMBOL(kernel_disable_single_step);
int kernel_active_single_step(struct pt_regs *regs)
{
WARN_ON(!irqs_disabled());
- return mdscr_read() & DBG_MDSCR_SS;
+ return regs->ss_enable;
}
NOKPROBE_SYMBOL(kernel_active_single_step);
@@ -174,6 +174,17 @@ alternative_cb_end
apply_ssbd 1, x22, x23
.else
+ /*
+ * If single-step was enabled, save it off and disable it,
+ * or it will trap on clearing the D bit in PSTATE.
+ * The restore code will re-enable it if necessary.
+ */
+ mrs x20, mdscr_el1
+ bic x21, x20, #1
+ msr mdscr_el1, x21
+ and x20, x20, #1
+ str w20, [sp, #S_SS_ENABLE]
+
add x21, sp, #S_FRAME_SIZE
get_current_task tsk
/* Save the task's original addr_limit and set USER_DS */
@@ -349,6 +360,16 @@ alternative_else_nop_endif
msr elr_el1, x21 // set up the return data
msr spsr_el1, x22
+
+ .if \el != 0
+ /* Restore the single-step bit. */
+ ldr w21, [sp, #S_SS_ENABLE]
+ mrs x20, mdscr_el1
+ orr x20, x20, x21
+ msr mdscr_el1, x20
+ /* PSTATE.D and PSTATE.SS will be restored from SPSR_EL1. */
+ .endif
+
ldp x0, x1, [sp, #16 * 0]
ldp x2, x3, [sp, #16 * 1]
ldp x4, x5, [sp, #16 * 2]
@@ -223,6 +223,9 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
*/
if (!kernel_active_single_step(linux_regs))
kernel_enable_single_step(linux_regs);
+ else
+ /* Doing a single-step clears ss, reset it. */
+ linux_regs->pstate |= DBG_SPSR_SS;
err = 0;
break;
default: