Merge branch 'pm-cpuidle'
[linux-2.6-block.git] / arch / x86 / kernel / kvm.c
index 4ab377c9fffede8af8c93b620bdb9d90803fd353..98dafc1ea33d7f0fe8101995626691fcf35099f6 100644 (file)
@@ -705,6 +705,7 @@ unsigned int kvm_arch_para_hints(void)
 {
        return cpuid_edx(kvm_cpuid_base() | KVM_CPUID_FEATURES);
 }
+EXPORT_SYMBOL_GPL(kvm_arch_para_hints);
 
 static uint32_t __init kvm_detect(void)
 {
@@ -867,3 +868,39 @@ void __init kvm_spinlock_init(void)
 }
 
 #endif /* CONFIG_PARAVIRT_SPINLOCKS */
+
+#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL
+
+static void kvm_disable_host_haltpoll(void *i)
+{
+       wrmsrl(MSR_KVM_POLL_CONTROL, 0);
+}
+
+static void kvm_enable_host_haltpoll(void *i)
+{
+       wrmsrl(MSR_KVM_POLL_CONTROL, 1);
+}
+
+void arch_haltpoll_enable(unsigned int cpu)
+{
+       if (!kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL)) {
+               pr_err_once("kvm: host does not support poll control\n");
+               pr_err_once("kvm: host upgrade recommended\n");
+               return;
+       }
+
+       /* Enable guest halt poll disables host halt poll */
+       smp_call_function_single(cpu, kvm_disable_host_haltpoll, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(arch_haltpoll_enable);
+
+void arch_haltpoll_disable(unsigned int cpu)
+{
+       if (!kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL))
+               return;
+
+       /* Enable guest halt poll disables host halt poll */
+       smp_call_function_single(cpu, kvm_enable_host_haltpoll, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(arch_haltpoll_disable);
+#endif