kdb,debug_core: adjust master cpu switch logic against new debug_core locking
authorJason Wessel <jason.wessel@windriver.com>
Fri, 21 May 2010 13:46:00 +0000 (08:46 -0500)
committerJason Wessel <jason.wessel@windriver.com>
Fri, 22 Oct 2010 20:34:13 +0000 (15:34 -0500)
The kdb shell needs to enforce switching back to the original CPU that
took the exception before restoring normal kernel execution.  Resuming
from a different CPU than what took the original exception will cause
problems with spin locks that are freed from the a different processor
than had taken the lock.

The special logic in dbg_cpu_switch() can go away entirely with
because the state of what cpus want to be masters or slaves will
remain unchanged between entry and exit of the debug_core exception
context.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
kernel/debug/debug_core.c
kernel/debug/kdb/kdb_debugger.c
kernel/debug/kdb/kdb_main.c

index 26dbdc37d2195b0d0bb4925060e950fd9da3e060..fec596da9bd0c19b2e6959098e7cb50ed0564d79 100644 (file)
@@ -460,19 +460,6 @@ static int kgdb_reenter_check(struct kgdb_state *ks)
        return 1;
 }
 
-static void dbg_cpu_switch(int cpu, int next_cpu)
-{
-       /* Mark the cpu we are switching away from as a slave when it
-        * holds the kgdb_active token.  This must be done so that the
-        * that all the cpus wait in for the debug core will not enter
-        * again as the master. */
-       if (cpu == atomic_read(&kgdb_active)) {
-               kgdb_info[cpu].exception_state |= DCPU_IS_SLAVE;
-               kgdb_info[cpu].exception_state &= ~DCPU_WANT_MASTER;
-       }
-       kgdb_info[next_cpu].exception_state |= DCPU_NEXT_MASTER;
-}
-
 static void dbg_touch_watchdogs(void)
 {
        touch_softlockup_watchdog_sync();
@@ -638,7 +625,8 @@ cpu_master_loop:
                if (error == DBG_PASS_EVENT) {
                        dbg_kdb_mode = !dbg_kdb_mode;
                } else if (error == DBG_SWITCH_CPU_EVENT) {
-                       dbg_cpu_switch(cpu, dbg_switch_cpu);
+                       kgdb_info[dbg_switch_cpu].exception_state |=
+                               DCPU_NEXT_MASTER;
                        goto cpu_loop;
                } else {
                        kgdb_info[cpu].ret_state = error;
index bf6e8270e95781469d07c08652cab9edd7c45d71..dd0b1b7dd02c9bb5d8d32b84c39f0a62a4db9c56 100644 (file)
@@ -86,7 +86,7 @@ int kdb_stub(struct kgdb_state *ks)
        }
        /* Set initial kdb state variables */
        KDB_STATE_CLEAR(KGDB_TRANS);
-       kdb_initial_cpu = ks->cpu;
+       kdb_initial_cpu = atomic_read(&kgdb_active);
        kdb_current_task = kgdb_info[ks->cpu].task;
        kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
        /* Remove any breakpoints as needed by kdb and clear single step */
@@ -105,7 +105,6 @@ int kdb_stub(struct kgdb_state *ks)
                ks->pass_exception = 1;
                KDB_FLAG_SET(CATASTROPHIC);
        }
-       kdb_initial_cpu = ks->cpu;
        if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) {
                KDB_STATE_CLEAR(SSBPT);
                KDB_STATE_CLEAR(DOING_SS);
index 4226f32517d178f2330e97b0acb92f78f97013ce..d7bda21a106b572ee95c22fd1e59524914944ed4 100644 (file)
@@ -1749,13 +1749,13 @@ static int kdb_go(int argc, const char **argv)
        int nextarg;
        long offset;
 
+       if (raw_smp_processor_id() != kdb_initial_cpu) {
+               kdb_printf("go must execute on the entry cpu, "
+                          "please use \"cpu %d\" and then execute go\n",
+                          kdb_initial_cpu);
+               return KDB_BADCPUNUM;
+       }
        if (argc == 1) {
-               if (raw_smp_processor_id() != kdb_initial_cpu) {
-                       kdb_printf("go <address> must be issued from the "
-                                  "initial cpu, do cpu %d first\n",
-                                  kdb_initial_cpu);
-                       return KDB_ARGCOUNT;
-               }
                nextarg = 1;
                diag = kdbgetaddrarg(argc, argv, &nextarg,
                                     &addr, &offset, NULL);