kernel - Try to idle cpus when in panic()
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 5 Dec 2016 17:21:19 +0000 (09:21 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 5 Dec 2016 17:21:19 +0000 (09:21 -0800)
* Try to use MONITOR/MWAIT to idle cpus while they are stopped in a panic(),
  instead of hard-looping.  This significantly reduces power consumption while
  in a paniced state and is particularly helpful on laptops.

Reported-by: tuxillo
sys/kern/lwkt_thread.c
sys/platform/pc64/x86_64/machdep.c
sys/sys/systm.h

index 2cb502a..d68adc8 100644 (file)
@@ -1712,4 +1712,5 @@ lwkt_smp_stopped(void)
     } else {
        lwkt_process_ipiq();
     }
+    cpu_smp_stopped();
 }
index 669dd37..85c6816 100644 (file)
@@ -1250,6 +1250,28 @@ cpu_idle(void)
        }
 }
 
+/*
+ * Called in a loop indirectly via Xcpustop
+ */
+void
+cpu_smp_stopped(void)
+{
+       globaldata_t gd = mycpu;
+       volatile __uint64_t *ptr;
+       __uint64_t ovalue;
+
+       ptr = CPUMASK_ADDR(started_cpus, gd->gd_cpuid);
+       ovalue = *ptr;
+       if ((ovalue & CPUMASK_SIMPLE(gd->gd_cpuid & 63)) == 0) {
+               if (cpu_mi_feature & CPU_MI_MONITOR) {
+                       cpu_mmw_pause_long(__DEVOLATILE(void *, ptr), ovalue,
+                                          cpu_mwait_hints[CPU_MWAIT_C1], 0);
+               } else {
+                       cpu_halt();     /* depend on lapic timer */
+               }
+       }
+}
+
 /*
  * This routine is called if a spinlock has been held through the
  * exponential backoff period and is seriously contested.  On a real cpu
index 2ad9de1..2fd95cf 100644 (file)
@@ -337,6 +337,7 @@ void                splz (void);
 void           splz_check (void);
 void           cpu_mmw_pause_int(int*, int, int, int);
 void           cpu_mmw_pause_long(long*, long, int, int);
+void           cpu_smp_stopped(void);
 #endif /* __x86_64__ */
 
 /*