Commit d7161a65 authored by Jason Wessel's avatar Jason Wessel

kgdb, x86, arm, mips, powerpc: ignore user space single stepping

On the x86 arch, user space single step exceptions should be ignored
if they occur in the kernel space, such as ptrace stepping through a
system call.

First check if it is kgdb that is executing a single step, then ensure
it is not an accidental traversal into the user space, while in kgdb,
any other time the TIF_SINGLESTEP is set, kgdb should ignore the
exception.

On x86, arm, mips and powerpc, the kgdb_contthread usage was
inconsistent with the way single stepping is implemented in the kgdb
core.  The arch specific stub should always set the
kgdb_cpu_doing_single_step correctly if it is single stepping.  This
allows kgdb to correctly process an instruction steps if ptrace
happens to be requesting an instruction step over a system call.
Signed-off-by: default avatarJason Wessel <jason.wessel@windriver.com>
parent 18d6522b
...@@ -111,8 +111,6 @@ int kgdb_arch_handle_exception(int exception_vector, int signo, ...@@ -111,8 +111,6 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
case 'D': case 'D':
case 'k': case 'k':
case 'c': case 'c':
kgdb_contthread = NULL;
/* /*
* Try to read optional parameter, pc unchanged if no parm. * Try to read optional parameter, pc unchanged if no parm.
* If this was a compiled breakpoint, we need to move * If this was a compiled breakpoint, we need to move
......
...@@ -236,8 +236,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, ...@@ -236,8 +236,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
atomic_set(&kgdb_cpu_doing_single_step, -1); atomic_set(&kgdb_cpu_doing_single_step, -1);
if (remcom_in_buffer[0] == 's') if (remcom_in_buffer[0] == 's')
if (kgdb_contthread) atomic_set(&kgdb_cpu_doing_single_step, cpu);
atomic_set(&kgdb_cpu_doing_single_step, cpu);
return 0; return 0;
} }
......
...@@ -347,9 +347,8 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, ...@@ -347,9 +347,8 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
linux_regs->msr |= MSR_SE; linux_regs->msr |= MSR_SE;
#endif #endif
kgdb_single_step = 1; kgdb_single_step = 1;
if (kgdb_contthread) atomic_set(&kgdb_cpu_doing_single_step,
atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id());
raw_smp_processor_id());
} }
return 0; return 0;
} }
......
...@@ -378,10 +378,8 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, ...@@ -378,10 +378,8 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
if (remcomInBuffer[0] == 's') { if (remcomInBuffer[0] == 's') {
linux_regs->flags |= X86_EFLAGS_TF; linux_regs->flags |= X86_EFLAGS_TF;
kgdb_single_step = 1; kgdb_single_step = 1;
if (kgdb_contthread) { atomic_set(&kgdb_cpu_doing_single_step,
atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id());
raw_smp_processor_id());
}
} }
get_debugreg(dr6, 6); get_debugreg(dr6, 6);
...@@ -466,9 +464,15 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd) ...@@ -466,9 +464,15 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
case DIE_DEBUG: case DIE_DEBUG:
if (atomic_read(&kgdb_cpu_doing_single_step) == if (atomic_read(&kgdb_cpu_doing_single_step) ==
raw_smp_processor_id() && raw_smp_processor_id()) {
user_mode(regs)) if (user_mode(regs))
return single_step_cont(regs, args); return single_step_cont(regs, args);
break;
} else if (test_thread_flag(TIF_SINGLESTEP))
/* This means a user thread is single stepping
* a system call which should be ignored
*/
return NOTIFY_DONE;
/* fall through */ /* fall through */
default: default:
if (user_mode(regs)) if (user_mode(regs))
......
...@@ -1462,7 +1462,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) ...@@ -1462,7 +1462,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
* Get the passive CPU lock which will hold all the non-primary * Get the passive CPU lock which will hold all the non-primary
* CPU in a spin state while the debugger is active * CPU in a spin state while the debugger is active
*/ */
if (!kgdb_single_step || !kgdb_contthread) { if (!kgdb_single_step) {
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
atomic_set(&passive_cpu_wait[i], 1); atomic_set(&passive_cpu_wait[i], 1);
} }
...@@ -1475,7 +1475,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) ...@@ -1475,7 +1475,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Signal the other CPUs to enter kgdb_wait() */ /* Signal the other CPUs to enter kgdb_wait() */
if ((!kgdb_single_step || !kgdb_contthread) && kgdb_do_roundup) if ((!kgdb_single_step) && kgdb_do_roundup)
kgdb_roundup_cpus(flags); kgdb_roundup_cpus(flags);
#endif #endif
...@@ -1494,7 +1494,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) ...@@ -1494,7 +1494,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code); kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code);
kgdb_deactivate_sw_breakpoints(); kgdb_deactivate_sw_breakpoints();
kgdb_single_step = 0; kgdb_single_step = 0;
kgdb_contthread = NULL; kgdb_contthread = current;
exception_level = 0; exception_level = 0;
/* Talk to debugger with gdbserial protocol */ /* Talk to debugger with gdbserial protocol */
...@@ -1508,7 +1508,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) ...@@ -1508,7 +1508,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
kgdb_info[ks->cpu].task = NULL; kgdb_info[ks->cpu].task = NULL;
atomic_set(&cpu_in_kgdb[ks->cpu], 0); atomic_set(&cpu_in_kgdb[ks->cpu], 0);
if (!kgdb_single_step || !kgdb_contthread) { if (!kgdb_single_step) {
for (i = NR_CPUS-1; i >= 0; i--) for (i = NR_CPUS-1; i >= 0; i--)
atomic_set(&passive_cpu_wait[i], 0); atomic_set(&passive_cpu_wait[i], 0);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment