On Fri, Jun 14, 2019 at 12:55 AM Marcelo Tosatti <mtosatti@xxxxxxxxxx> wrote: > > Add a cpuidle driver that calls the architecture default_idle routine. > > To be used in conjunction with the haltpoll governor. > > Signed-off-by: Marcelo Tosatti <mtosatti@xxxxxxxxxx> > > --- > arch/x86/kernel/process.c | 2 - > drivers/cpuidle/Kconfig | 9 +++++ > drivers/cpuidle/Makefile | 1 > drivers/cpuidle/cpuidle-haltpoll.c | 65 +++++++++++++++++++++++++++++++++++++ > 4 files changed, 76 insertions(+), 1 deletion(-) > > Index: linux-2.6.git/arch/x86/kernel/process.c > =================================================================== > --- linux-2.6.git.orig/arch/x86/kernel/process.c 2019-06-13 16:19:27.877064340 -0400 > +++ linux-2.6.git/arch/x86/kernel/process.c 2019-06-13 16:19:48.795544892 -0400 > @@ -580,7 +580,7 @@ > safe_halt(); > trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); > } > -#ifdef CONFIG_APM_MODULE > +#if defined(CONFIG_APM_MODULE) || defined(CONFIG_HALTPOLL_CPUIDLE_MODULE) > EXPORT_SYMBOL(default_idle); > #endif > > Index: linux-2.6.git/drivers/cpuidle/Kconfig > =================================================================== > --- linux-2.6.git.orig/drivers/cpuidle/Kconfig 2019-06-13 16:19:27.878064316 -0400 > +++ linux-2.6.git/drivers/cpuidle/Kconfig 2019-06-13 18:41:40.599912671 -0400 > @@ -51,6 +51,15 @@ > source "drivers/cpuidle/Kconfig.powerpc" > endmenu > > +config HALTPOLL_CPUIDLE > + tristate "Halt poll cpuidle driver" > + depends on X86 > + default y > + help > + This option enables halt poll cpuidle driver, which allows to poll > + before halting in the guest (more efficient than polling in the > + host via halt_poll_ns for some scenarios). > + > endif > > config ARCH_NEEDS_CPU_IDLE_COUPLED > Index: linux-2.6.git/drivers/cpuidle/Makefile > =================================================================== > --- linux-2.6.git.orig/drivers/cpuidle/Makefile 2019-06-13 16:19:27.878064316 -0400 > +++ linux-2.6.git/drivers/cpuidle/Makefile 2019-06-13 16:19:48.796544867 -0400 > @@ -7,6 +7,7 @@ > obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o > obj-$(CONFIG_DT_IDLE_STATES) += dt_idle_states.o > obj-$(CONFIG_ARCH_HAS_CPU_RELAX) += poll_state.o > +obj-$(CONFIG_HALTPOLL_CPUIDLE) += cpuidle-haltpoll.o > > ################################################################################## > # ARM SoC drivers > Index: linux-2.6.git/drivers/cpuidle/cpuidle-haltpoll.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ linux-2.6.git/drivers/cpuidle/cpuidle-haltpoll.c 2019-06-13 18:41:39.305933413 -0400 > @@ -0,0 +1,65 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * cpuidle driver for haltpoll governor. > + * > + * Copyright 2019 Red Hat, Inc. and/or its affiliates. > + * > + * This work is licensed under the terms of the GNU GPL, version 2. See > + * the COPYING file in the top-level directory. > + * > + * Authors: Marcelo Tosatti <mtosatti@xxxxxxxxxx> > + */ > + > +#include <linux/init.h> > +#include <linux/cpuidle.h> > +#include <linux/module.h> > +#include <linux/sched/idle.h> > + > +static int default_enter_idle(struct cpuidle_device *dev, > + struct cpuidle_driver *drv, int index) > +{ > + if (current_clr_polling_and_test()) { > + local_irq_enable(); > + return index; > + } > + default_idle(); > + return index; > +} > + > +static struct cpuidle_driver haltpoll_driver = { > + .name = "haltpoll", > + .owner = THIS_MODULE, > + .states = { > + { /* entry 0 is for polling */ }, > + { > + .enter = default_enter_idle, > + .exit_latency = 0, > + .target_residency = 0, > + .power_usage = -1, > + .name = "haltpoll idle", > + .desc = "default architecture idle", > + }, > + }, > + .safe_state_index = 0, > + .state_count = 2, > +}; > + > +static int __init haltpoll_init(void) > +{ > + struct cpuidle_driver *drv = &haltpoll_driver; > + > + cpuidle_poll_state_init(drv); > + > + return cpuidle_register(&haltpoll_driver, NULL); Would it be practical to prevent this driver from loading on non-virt? > +} > + > +static void __exit haltpoll_exit(void) > +{ > + cpuidle_unregister(&haltpoll_driver); > +} > + > +module_init(haltpoll_init); > +module_exit(haltpoll_exit); > +MODULE_LICENSE("GPL"); > +MODULE_AUTHOR("Marcelo Tosatti <mtosatti@xxxxxxxxxx>"); > + Apart from the above it is simple enough.