aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kgdb.c
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2009-12-11 09:43:17 -0500
committerJason Wessel <jason.wessel@windriver.com>2009-12-11 09:43:17 -0500
commit028e7b175970be8fca58bfd7d61cc375babe40b7 (patch)
treec94d3acdc460836a9ef2d06f3e80f83d5f33f157 /kernel/kgdb.c
parentcf6f196d112a6f6757b1ca3cce0b576f7abee479 (diff)
kgdb: allow for cpu switch when single stepping
The kgdb core should not assume that a single step operation of a kernel thread will complete on the same CPU. The single step flag is set at the "thread" level and it is possible in a multi cpu system that a kernel thread can get scheduled on another cpu the next time it is run. As a further safety net in case a slave cpu is hung, the debug master cpu will try 100 times before giving up and assuming control of the slave cpus is no longer possible. It is more useful to be able to get some information out of kgdb instead of spinning forever. Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Diffstat (limited to 'kernel/kgdb.c')
-rw-r--r--kernel/kgdb.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/kernel/kgdb.c b/kernel/kgdb.c
index 29357a9ccfb2..ca21fe98e8de 100644
--- a/kernel/kgdb.c
+++ b/kernel/kgdb.c
@@ -129,6 +129,7 @@ struct task_struct *kgdb_usethread;
129struct task_struct *kgdb_contthread; 129struct task_struct *kgdb_contthread;
130 130
131int kgdb_single_step; 131int kgdb_single_step;
132pid_t kgdb_sstep_pid;
132 133
133/* Our I/O buffers. */ 134/* Our I/O buffers. */
134static char remcom_in_buffer[BUFMAX]; 135static char remcom_in_buffer[BUFMAX];
@@ -1400,6 +1401,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
1400 struct kgdb_state kgdb_var; 1401 struct kgdb_state kgdb_var;
1401 struct kgdb_state *ks = &kgdb_var; 1402 struct kgdb_state *ks = &kgdb_var;
1402 unsigned long flags; 1403 unsigned long flags;
1404 int sstep_tries = 100;
1403 int error = 0; 1405 int error = 0;
1404 int i, cpu; 1406 int i, cpu;
1405 1407
@@ -1430,13 +1432,14 @@ acquirelock:
1430 cpu_relax(); 1432 cpu_relax();
1431 1433
1432 /* 1434 /*
1433 * Do not start the debugger connection on this CPU if the last 1435 * For single stepping, try to only enter on the processor
1434 * instance of the exception handler wanted to come into the 1436 * that was single stepping. To gaurd against a deadlock, the
1435 * debugger on a different CPU via a single step 1437 * kernel will only try for the value of sstep_tries before
1438 * giving up and continuing on.
1436 */ 1439 */
1437 if (atomic_read(&kgdb_cpu_doing_single_step) != -1 && 1440 if (atomic_read(&kgdb_cpu_doing_single_step) != -1 &&
1438 atomic_read(&kgdb_cpu_doing_single_step) != cpu) { 1441 (kgdb_info[cpu].task &&
1439 1442 kgdb_info[cpu].task->pid != kgdb_sstep_pid) && --sstep_tries) {
1440 atomic_set(&kgdb_active, -1); 1443 atomic_set(&kgdb_active, -1);
1441 touch_softlockup_watchdog(); 1444 touch_softlockup_watchdog();
1442 clocksource_touch_watchdog(); 1445 clocksource_touch_watchdog();
@@ -1529,6 +1532,13 @@ acquirelock:
1529 } 1532 }
1530 1533
1531kgdb_restore: 1534kgdb_restore:
1535 if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
1536 int sstep_cpu = atomic_read(&kgdb_cpu_doing_single_step);
1537 if (kgdb_info[sstep_cpu].task)
1538 kgdb_sstep_pid = kgdb_info[sstep_cpu].task->pid;
1539 else
1540 kgdb_sstep_pid = 0;
1541 }
1532 /* Free kgdb_active */ 1542 /* Free kgdb_active */
1533 atomic_set(&kgdb_active, -1); 1543 atomic_set(&kgdb_active, -1);
1534 touch_softlockup_watchdog(); 1544 touch_softlockup_watchdog();