Title: [9010] trunk/kernel/kgdb.c: Bug[#6044] Flush and invalidate cache is not safe in SMP blackfin kernel
- Revision
- 9010
- Author
- sonicz
- Date
- 2010-07-22 07:06:32 -0400 (Thu, 22 Jul 2010)
Log Message
Bug[#6044] Flush and invalidate cache is not safe in SMP blackfin kernel
IPI message queue may overflow in kgdb loop. So, only drop local cache
before exit the kgdb loop once.
Enclose cpu switch code in CONFIG_SMP as well.
Modified Paths
Diff
Modified: trunk/kernel/kgdb.c (9009 => 9010)
--- trunk/kernel/kgdb.c 2010-07-22 10:31:06 UTC (rev 9009)
+++ trunk/kernel/kgdb.c 2010-07-22 11:06:32 UTC (rev 9010)
@@ -1217,6 +1217,7 @@
memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
if (kgdb_connected) {
+#ifdef CONFIG_SMP
/* reply the thread switch request after finish swtiching cpu */
if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
!kgdb_single_step && kgdb_contthread == current) {
@@ -1225,6 +1226,7 @@
remcom_out_buffer[2] = 0;
put_packet(remcom_out_buffer);
} else {
+#endif
unsigned char thref[8];
char *ptr;
@@ -1237,7 +1239,9 @@
ptr = pack_threadid(ptr, thref);
*ptr++ = ';';
put_packet(remcom_out_buffer);
+#ifdef CONFIG_SMP
}
+#endif
}
kgdb_single_step = 0;
@@ -1479,10 +1483,12 @@
* CPU in a spin state while the debugger is active
*/
if (!kgdb_single_step) {
+#ifdef CONFIG_SMP
if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
kgdb_contthread == current)
atomic_inc(&passive_cpu_wait[cpu]);
else
+#endif
for (i = 0; i < NR_CPUS; i++)
atomic_inc(&passive_cpu_wait[i]);
}
@@ -1521,8 +1527,12 @@
atomic_dec(&cpu_in_kgdb[ks->cpu]);
+#ifdef CONFIG_SMP
if (!kgdb_single_step && !((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
kgdb_contthread)) {
+#else
+ if (!kgdb_single_step) {
+#endif
for (i = NR_CPUS-1; i >= 0; i--)
atomic_dec(&passive_cpu_wait[i]);
/*
@@ -1547,14 +1557,27 @@
tracing_on();
/* Free kgdb_active */
atomic_set(&kgdb_active, -1);
+#ifdef CONFIG_SMP
/* wake up next master cpu when do real cpu switch */
- if (!kgdb_single_step && (arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
- kgdb_contthread) {
- i = -(ks->kgdb_usethreadid + 2);
- atomic_dec(&passive_cpu_wait[i]);
- while (atomic_read(&kgdb_active) == -1)
- cpu_relax();
+ if (!kgdb_single_step) {
+ if (!CACHE_FLUSH_IS_SAFE) {
+#ifdef __ARCH_SYNC_CORE_ICACHE
+ resync_core_icache();
+#endif
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ resync_core_dcache();
+#endif
+ }
+
+ if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
+ kgdb_contthread) {
+ i = -(ks->kgdb_usethreadid + 2);
+ atomic_dec(&passive_cpu_wait[i]);
+ while (atomic_read(&kgdb_active) == -1)
+ cpu_relax();
+ }
}
+#endif
touch_softlockup_watchdog_sync();
clocksource_touch_watchdog();
local_irq_restore(flags);
@@ -1609,17 +1632,19 @@
kgdb_cpu_enter(ks, regs);
kgdb_info[cpu].exception_state &= ~DCPU_IS_SLAVE;
- /* Trap into kgdb as the active CPU if gdb asks to switch. */
- if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
- kgdb_contthread == current) {
+ if (!CACHE_FLUSH_IS_SAFE) {
#ifdef __ARCH_SYNC_CORE_ICACHE
resync_core_icache();
#endif
#ifdef __ARCH_SYNC_CORE_DCACHE
resync_core_dcache();
#endif
+ }
+ /* Trap into kgdb as the active CPU if gdb asks to switch. */
+ if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) &&
+ kgdb_contthread == current)
kgdb_breakpoint();
- }
+
return 0;
}
#endif
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits