Commit a1c4423b authored by Marcelo Tosatti's avatar Marcelo Tosatti Committed by Rafael J. Wysocki

cpuidle-haltpoll: disable host side polling when kvm virtualized

When performing guest side polling, it is not necessary to
also perform host side polling.

So disable host side polling, via the new MSR interface,
when loading cpuidle-haltpoll driver.
Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 2cffe9f6
...@@ -794,6 +794,7 @@ config KVM_GUEST ...@@ -794,6 +794,7 @@ config KVM_GUEST
bool "KVM Guest support (including kvmclock)" bool "KVM Guest support (including kvmclock)"
depends on PARAVIRT depends on PARAVIRT
select PARAVIRT_CLOCK select PARAVIRT_CLOCK
select ARCH_CPUIDLE_HALTPOLL
default y default y
---help--- ---help---
This option enables various optimizations for running under the KVM This option enables various optimizations for running under the KVM
...@@ -802,6 +803,12 @@ config KVM_GUEST ...@@ -802,6 +803,12 @@ config KVM_GUEST
underlying device model, the host provides the guest with underlying device model, the host provides the guest with
timing infrastructure such as time of day, and system time timing infrastructure such as time of day, and system time
config ARCH_CPUIDLE_HALTPOLL
def_bool n
prompt "Disable host haltpoll when loading haltpoll driver"
help
If virtualized under KVM, disable host haltpoll.
config PVH config PVH
bool "Support for running PVH guests" bool "Support for running PVH guests"
---help--- ---help---
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ARCH_HALTPOLL_H
#define _ARCH_HALTPOLL_H
void arch_haltpoll_enable(void);
void arch_haltpoll_disable(void);
#endif
...@@ -875,3 +875,45 @@ void __init kvm_spinlock_init(void) ...@@ -875,3 +875,45 @@ void __init kvm_spinlock_init(void)
} }
#endif /* CONFIG_PARAVIRT_SPINLOCKS */ #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(void)
{
if (!kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL)) {
printk(KERN_ERR "kvm: host does not support poll control\n");
printk(KERN_ERR "kvm: host upgrade recommended\n");
return;
}
preempt_disable();
/* Enable guest halt poll disables host halt poll */
kvm_disable_host_haltpoll(NULL);
smp_call_function(kvm_disable_host_haltpoll, NULL, 1);
preempt_enable();
}
EXPORT_SYMBOL_GPL(arch_haltpoll_enable);
void arch_haltpoll_disable(void)
{
if (!kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL))
return;
preempt_disable();
/* Enable guest halt poll disables host halt poll */
kvm_enable_host_haltpoll(NULL);
smp_call_function(kvm_enable_host_haltpoll, NULL, 1);
preempt_enable();
}
EXPORT_SYMBOL_GPL(arch_haltpoll_disable);
#endif
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/sched/idle.h> #include <linux/sched/idle.h>
#include <linux/kvm_para.h> #include <linux/kvm_para.h>
#include <linux/cpuidle_haltpoll.h>
static int default_enter_idle(struct cpuidle_device *dev, static int default_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index) struct cpuidle_driver *drv, int index)
...@@ -47,6 +48,7 @@ static struct cpuidle_driver haltpoll_driver = { ...@@ -47,6 +48,7 @@ static struct cpuidle_driver haltpoll_driver = {
static int __init haltpoll_init(void) static int __init haltpoll_init(void)
{ {
int ret;
struct cpuidle_driver *drv = &haltpoll_driver; struct cpuidle_driver *drv = &haltpoll_driver;
cpuidle_poll_state_init(drv); cpuidle_poll_state_init(drv);
...@@ -54,11 +56,16 @@ static int __init haltpoll_init(void) ...@@ -54,11 +56,16 @@ static int __init haltpoll_init(void)
if (!kvm_para_available()) if (!kvm_para_available())
return 0; return 0;
return cpuidle_register(&haltpoll_driver, NULL); ret = cpuidle_register(&haltpoll_driver, NULL);
if (ret == 0)
arch_haltpoll_enable();
return ret;
} }
static void __exit haltpoll_exit(void) static void __exit haltpoll_exit(void)
{ {
arch_haltpoll_disable();
cpuidle_unregister(&haltpoll_driver); cpuidle_unregister(&haltpoll_driver);
} }
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _CPUIDLE_HALTPOLL_H
#define _CPUIDLE_HALTPOLL_H
#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL
#include <asm/cpuidle_haltpoll.h>
#else
static inline void arch_haltpoll_enable(void)
{
}
static inline void arch_haltpoll_disable(void)
{
}
#endif
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment