|
@@ -728,6 +728,29 @@ extern unsigned long boot_option_idle_override;
|
|
|
extern unsigned long idle_halt;
|
|
|
extern unsigned long idle_nomwait;
|
|
|
|
|
|
+/*
|
|
|
+ * on systems with caches, caches must be flashed as the absolute
|
|
|
+ * last instruction before going into a suspended halt. Otherwise,
|
|
|
+ * dirty data can linger in the cache and become stale on resume,
|
|
|
+ * leading to strange errors.
|
|
|
+ *
|
|
|
+ * perform a variety of operations to guarantee that the compiler
|
|
|
+ * will not reorder instructions. wbinvd itself is serializing
|
|
|
+ * so the processor will not reorder.
|
|
|
+ *
|
|
|
+ * Systems without cache can just go into halt.
|
|
|
+ */
|
|
|
+static inline void wbinvd_halt(void)
|
|
|
+{
|
|
|
+ mb();
|
|
|
+ /* check for clflush to determine if wbinvd is legal */
|
|
|
+ if (cpu_has_clflush)
|
|
|
+ asm volatile("cli; wbinvd; 1: hlt; jmp 1b" : : : "memory");
|
|
|
+ else
|
|
|
+ while (1)
|
|
|
+ halt();
|
|
|
+}
|
|
|
+
|
|
|
extern void enable_sep_cpu(void);
|
|
|
extern int sysenter_setup(void);
|
|
|
|