kdb,debug_core: adjust master cpu switch logic against new debug_core locking
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>
This commit is contained in:
@@ -460,19 +460,6 @@ static int kgdb_reenter_check(struct kgdb_state *ks)
|
|||||||
return 1;
|
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)
|
static void dbg_touch_watchdogs(void)
|
||||||
{
|
{
|
||||||
touch_softlockup_watchdog_sync();
|
touch_softlockup_watchdog_sync();
|
||||||
@@ -638,7 +625,8 @@ cpu_master_loop:
|
|||||||
if (error == DBG_PASS_EVENT) {
|
if (error == DBG_PASS_EVENT) {
|
||||||
dbg_kdb_mode = !dbg_kdb_mode;
|
dbg_kdb_mode = !dbg_kdb_mode;
|
||||||
} else if (error == DBG_SWITCH_CPU_EVENT) {
|
} 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;
|
goto cpu_loop;
|
||||||
} else {
|
} else {
|
||||||
kgdb_info[cpu].ret_state = error;
|
kgdb_info[cpu].ret_state = error;
|
||||||
|
@@ -86,7 +86,7 @@ int kdb_stub(struct kgdb_state *ks)
|
|||||||
}
|
}
|
||||||
/* Set initial kdb state variables */
|
/* Set initial kdb state variables */
|
||||||
KDB_STATE_CLEAR(KGDB_TRANS);
|
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_task = kgdb_info[ks->cpu].task;
|
||||||
kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
|
kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
|
||||||
/* Remove any breakpoints as needed by kdb and clear single step */
|
/* 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;
|
ks->pass_exception = 1;
|
||||||
KDB_FLAG_SET(CATASTROPHIC);
|
KDB_FLAG_SET(CATASTROPHIC);
|
||||||
}
|
}
|
||||||
kdb_initial_cpu = ks->cpu;
|
|
||||||
if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) {
|
if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) {
|
||||||
KDB_STATE_CLEAR(SSBPT);
|
KDB_STATE_CLEAR(SSBPT);
|
||||||
KDB_STATE_CLEAR(DOING_SS);
|
KDB_STATE_CLEAR(DOING_SS);
|
||||||
|
@@ -1749,13 +1749,13 @@ static int kdb_go(int argc, const char **argv)
|
|||||||
int nextarg;
|
int nextarg;
|
||||||
long offset;
|
long offset;
|
||||||
|
|
||||||
if (argc == 1) {
|
|
||||||
if (raw_smp_processor_id() != kdb_initial_cpu) {
|
if (raw_smp_processor_id() != kdb_initial_cpu) {
|
||||||
kdb_printf("go <address> must be issued from the "
|
kdb_printf("go must execute on the entry cpu, "
|
||||||
"initial cpu, do cpu %d first\n",
|
"please use \"cpu %d\" and then execute go\n",
|
||||||
kdb_initial_cpu);
|
kdb_initial_cpu);
|
||||||
return KDB_ARGCOUNT;
|
return KDB_BADCPUNUM;
|
||||||
}
|
}
|
||||||
|
if (argc == 1) {
|
||||||
nextarg = 1;
|
nextarg = 1;
|
||||||
diag = kdbgetaddrarg(argc, argv, &nextarg,
|
diag = kdbgetaddrarg(argc, argv, &nextarg,
|
||||||
&addr, &offset, NULL);
|
&addr, &offset, NULL);
|
||||||
|
Reference in New Issue
Block a user