If the cpu implements monitor/mwait, use it for the trigger API.
TODO: work out if any mwait hints are going to be useful here.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
---
arch/x86/kernel/paravirt-spinlocks.c | 22 ++++++++++++
arch/x86/kernel/trigger.c | 59 ++++++++++++++++++++++++++++++++++
include/asm-x86/trigger.h | 27 +++++++++++++--
3 files changed, 104 insertions(+), 4 deletions(-)
===================================================================
--- a/arch/x86/kernel/paravirt-spinlocks.c
+++ b/arch/x86/kernel/paravirt-spinlocks.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <asm/paravirt.h>
+#include <asm/cpufeature.h>
static void default_spin_lock_flags(struct raw_spinlock *lock, unsigned long flags)
{
@@ -41,3 +42,24 @@
pv_lock_ops.spin_unlock = __byte_spin_unlock;
#endif
}
+
+static int __init use_mwait_trigger(void)
+{
+ /*
+ * If we're using normal native trigger operations and the cpu
+ * supports mwait, then switch to using it.
+ */
+ if (pv_lock_ops.trigger_wait == native_trigger_wait &&
+ pv_lock_ops.trigger_reset == native_trigger_reset &&
+ pv_lock_ops.trigger_kick == native_trigger_kick &&
+ pv_lock_ops.trigger_finish == paravirt_nop &&
+ boot_cpu_has(X86_FEATURE_MWAIT)) {
+ pv_lock_ops.trigger_reset = mwait_trigger_reset;
+ pv_lock_ops.trigger_wait = mwait_trigger_wait;
+ pv_lock_ops.trigger_kick = mwait_trigger_kick;
+ pv_lock_ops.trigger_finish = mwait_trigger_finish;
+ }
+
+ return 0;
+}
+early_initcall(use_mwait_trigger);
===================================================================
--- a/arch/x86/kernel/trigger.c
+++ b/arch/x86/kernel/trigger.c
@@ -1,5 +1,9 @@
#include <linux/trigger.h>
#include <linux/smp.h>
+#include <linux/percpu.h>
+#include ...