When I spend more that 10 seconds in KDB console and then exit from KDB, Kernel 
think that current clocksource is unstable and change it. I'm using 2.6.22-rc7 
kdb on SMP i386 system. Here is log:
Before doing sync, I've set breakpoint to do_sync().
[EMAIL PROTECTED]:~#
[EMAIL PROTECTED]:~# cat 
/sys/devices/system/clocksource/clocksource0/current_clocksource
tsc
[EMAIL PROTECTED]:~# sync
Instruction(i) breakpoint #0 at 0xc017b64a (adjusted)
0xc017b64a do_sync:         int3

Entering kdb (current=0xc16f3a50, pid 2983) on processor 0 due to Breakpoint @ 
0xc017b64a
[0]kdb> go
Clocksource tsc unstable (delta = 14060902198 ns)
[EMAIL PROTECTED]:~# Time: acpi_pm clocksource has been installed.

[EMAIL PROTECTED]:~#
[EMAIL PROTECTED]:~# cat 
/sys/devices/system/clocksource/clocksource0/current_clocksource
acpi_pm
[EMAIL PROTECTED]:~#
[EMAIL PROTECTED]:~#

Issue: tsc clocksource was replaced by acpi_pm.

The reason of issue:
Current clocksource(tsc) in kernel have a watchdog - another 
clocksource(acpi_pm). clocksource_watchdog() that updates
watchdog_last timestamp runs with help of kernel timer that is disabled when 
kernel enters kdb. So watchdog clocksource(acpi_pm) can overflow and when 
kernel exits kdb, watchdog clocksource can report wrong time delta - that's why 
kernel can think that current clocksource is unstable and change it.

How solved:
I suspend/resume timekeeping when we enter/exit kdb. Suspend/resume of 
timekeeping suspends/resumes current clocksource and watchdog clocksource.
Also patch prevents potential softlockup warnings that appear in earlier 
kernels.

Thanks.

Signed-off-by: Konstantin Baydarov <[EMAIL PROTECTED]>

 kdb/kdbmain.c             |   17 +++++++++++++++++
 kernel/time/timekeeping.c |   27 +++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

Index: linux-2.6.22-rc7/kdb/kdbmain.c
===================================================================
--- linux-2.6.22-rc7.orig/kdb/kdbmain.c
+++ linux-2.6.22-rc7/kdb/kdbmain.c
@@ -47,6 +47,9 @@
 #include <asm/system.h>
 #include <asm/kdebug.h>
 
+int kdb_timekeeping_suspend(void);
+int kdb_timekeeping_resume(void);
+
 /*
  * Kernel debugger state flags
  */
@@ -60,6 +63,7 @@ atomic_t kdb_8250;
  */
 static DEFINE_SPINLOCK(kdb_lock);
 volatile int kdb_initial_cpu = -1;             /* cpu number that owns kdb */
+volatile int kdb_initial_cpu_save = -1;                /* cpu number that owns 
kdb */
 int kdb_seqno = 2;                             /* how many times kdb has been 
entered */
 
 volatile int kdb_nextline = 1;
@@ -1998,6 +2002,11 @@ kdb(kdb_reason_t reason, int error, stru
                        smp_kdb_stop();
                        KDB_DEBUG_STATE("kdb 8", reason);
                }
+               /* Suspend clocksource, when entering kdb, to prevent
+                * false soft lockup warnings and switching to another
+                * clocksource.
+                */
+               kdb_timekeeping_suspend();
        }
 
        if (KDB_STATE(GO1)) {
@@ -2020,6 +2029,7 @@ kdb(kdb_reason_t reason, int error, stru
        if (result == KDB_CMD_GO && KDB_STATE(SSBPT))
                KDB_STATE_SET(GO1);
 
+       kdb_initial_cpu_save = kdb_initial_cpu;
        if (smp_processor_id() == kdb_initial_cpu &&
          !KDB_STATE(DOING_SS) &&
          !KDB_STATE(RECURSE)) {
@@ -2055,6 +2065,13 @@ kdb(kdb_reason_t reason, int error, stru
                }
        }
 
+       /* Only do this work if we are really leaving kdb */
+       if (!(KDB_STATE(DOING_SS) || KDB_STATE(SSBPT) || KDB_STATE(RECURSE))) {
+               if(smp_processor_id() == kdb_initial_cpu_save)
+                       /* Resume clocksource when initial cpu leaves kdb */
+                       kdb_timekeeping_resume();
+       }
+
        KDB_DEBUG_STATE("kdb 14", result);
        kdba_restoreint(&int_state);
 #ifdef  CONFIG_CPU_XSCALE
Index: linux-2.6.22-rc7/kernel/time/timekeeping.c
===================================================================
--- linux-2.6.22-rc7.orig/kernel/time/timekeeping.c
+++ linux-2.6.22-rc7/kernel/time/timekeeping.c
@@ -299,6 +299,19 @@ static int timekeeping_resume(struct sys
        return 0;
 }
 
+#if defined(CONFIG_KDB) || defined(CONFIG_KDB_MODULE)
+int kdb_timekeeping_resume(void)
+{
+       int ret;
+       struct sys_device dev;
+
+       ret = timekeeping_resume(&dev);
+
+       return ret;
+}
+EXPORT_SYMBOL(kdb_timekeeping_resume);
+#endif
+
 static int timekeeping_suspend(struct sys_device *dev, pm_message_t state)
 {
        unsigned long flags;
@@ -313,6 +326,20 @@ static int timekeeping_suspend(struct sy
        return 0;
 }
 
+#if defined(CONFIG_KDB) || defined(CONFIG_KDB_MODULE)
+int kdb_timekeeping_suspend(void)
+{
+       int ret;
+       struct sys_device dev;
+       pm_message_t state;
+
+       ret = timekeeping_suspend(&dev, state);
+
+       return ret;
+}
+EXPORT_SYMBOL(kdb_timekeeping_suspend);
+#endif
+
 /* sysfs resume/suspend bits for timekeeping */
 static struct sysdev_class timekeeping_sysclass = {
        .resume         = timekeeping_resume,
---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.

Reply via email to