kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/5] cpuidle haltpoll driver and governor (v6)
@ 2019-07-03 23:51 Marcelo Tosatti
  2019-07-03 23:51 ` [patch 1/5] add cpuidle-haltpoll driver Marcelo Tosatti
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Marcelo Tosatti @ 2019-07-03 23:51 UTC (permalink / raw)
  To: kvm-devel
  Cc: Paolo Bonzini, Radim Krcmar, Andrea Arcangeli, Rafael J. Wysocki,
	Peter Zijlstra, Wanpeng Li, Konrad Rzeszutek Wilk,
	Raslan KarimAllah, Boris Ostrovsky, Ankur Arora,
	Christian Borntraeger, linux-pm

(rebased against queue branch of kvm.git tree)

The cpuidle-haltpoll driver with haltpoll governor allows the guest
vcpus to poll for a specified amount of time before halting.
This provides the following benefits to host side polling:

         1) The POLL flag is set while polling is performed, which allows
            a remote vCPU to avoid sending an IPI (and the associated
            cost of handling the IPI) when performing a wakeup.

         2) The VM-exit cost can be avoided.

The downside of guest side polling is that polling is performed
even with other runnable tasks in the host.

Results comparing halt_poll_ns and server/client application
where a small packet is ping-ponged:

host                                        --> 31.33
halt_poll_ns=300000 / no guest busy spin    --> 33.40   (93.8%)
halt_poll_ns=0 / guest_halt_poll_ns=300000  --> 32.73   (95.7%)

For the SAP HANA benchmarks (where idle_spin is a parameter
of the previous version of the patch, results should be the
same):

hpns == halt_poll_ns

                           idle_spin=0/   idle_spin=800/    idle_spin=0/
                           hpns=200000    hpns=0            hpns=800000
DeleteC06T03 (100 thread) 1.76           1.71 (-3%)        1.78   (+1%)
InsertC16T02 (100 thread) 2.14           2.07 (-3%)        2.18   (+1.8%)
DeleteC00T01 (1 thread)   1.34           1.28 (-4.5%)	   1.29   (-3.7%)
UpdateC00T03 (1 thread)   4.72           4.18 (-12%)	   4.53   (-5%)

V2:

- Move from x86 to generic code (Paolo/Christian)
- Add auto-tuning logic (Paolo)
- Add MSR to disable host side polling (Paolo)

V3:

- Do not be specific about HLT VM-exit in the documentation (Ankur Arora)
- Mark tuning parameters static and __read_mostly (Andrea Arcangeli)
- Add WARN_ON if host does not support poll control (Joao Martins)
- Use sched_clock and cleanup haltpoll_enter_idle (Peter Zijlstra)
- Mark certain functions in kvm.c as static (kernel test robot)
- Remove tracepoints as they use RCU from extended quiescent state (kernel
test robot)

V4:
- Use a haltpoll governor, use poll_state.c poll code (Rafael J. Wysocki)

V5:
- Take latency requirement into consideration (Rafael J. Wysocki)
- Set target_residency/exit_latency to 1 (Rafael J. Wysocki)
- Do not load cpuidle driver if not virtualized (Rafael J. Wysocki)

V6:
- Switch from callback to poll_limit_ns variable in cpuidle device structure
(Rafael J. Wysocki)
- Move last_used_idx to cpuidle device structure (Rafael J. Wysocki)
- Drop per-cpu device structure in haltpoll governor (Rafael J. Wysocki)



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch 1/5] add cpuidle-haltpoll driver
  2019-07-03 23:51 [patch 0/5] cpuidle haltpoll driver and governor (v6) Marcelo Tosatti
@ 2019-07-03 23:51 ` Marcelo Tosatti
  2019-07-04  9:16   ` Joao Martins
  2019-07-03 23:51 ` [patch 2/5] cpuidle: add poll_limit_ns to cpuidle_device structure Marcelo Tosatti
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Marcelo Tosatti @ 2019-07-03 23:51 UTC (permalink / raw)
  To: kvm-devel
  Cc: Paolo Bonzini, Radim Krcmar, Andrea Arcangeli, Rafael J. Wysocki,
	Peter Zijlstra, Wanpeng Li, Konrad Rzeszutek Wilk,
	Raslan KarimAllah, Boris Ostrovsky, Ankur Arora,
	Christian Borntraeger, linux-pm, Marcelo Tosatti

[-- Attachment #1: 00-cpuidle-haltpoll --]
[-- Type: text/plain, Size: 4092 bytes --]

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@redhat.com>

---
 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-newcpuidle.git/arch/x86/kernel/process.c
===================================================================
--- linux-2.6-newcpuidle.git.orig/arch/x86/kernel/process.c
+++ linux-2.6-newcpuidle.git/arch/x86/kernel/process.c
@@ -580,7 +580,7 @@ void __cpuidle default_idle(void)
 	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-newcpuidle.git/drivers/cpuidle/Kconfig
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/Kconfig
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/Kconfig
@@ -51,6 +51,15 @@ depends on PPC
 source "drivers/cpuidle/Kconfig.powerpc"
 endmenu
 
+config HALTPOLL_CPUIDLE
+       tristate "Halt poll cpuidle driver"
+       depends on X86 && KVM_GUEST
+       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-newcpuidle.git/drivers/cpuidle/Makefile
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/Makefile
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/Makefile
@@ -7,6 +7,7 @@ obj-y += cpuidle.o driver.o governor.o s
 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-newcpuidle.git/drivers/cpuidle/cpuidle-haltpoll.c
===================================================================
--- /dev/null
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/cpuidle-haltpoll.c
@@ -0,0 +1,69 @@
+// 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@redhat.com>
+ */
+
+#include <linux/init.h>
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <linux/sched/idle.h>
+#include <linux/kvm_para.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		= 1,
+			.target_residency	= 1,
+			.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);
+
+	if (!kvm_para_available())
+		return 0;
+
+	return cpuidle_register(&haltpoll_driver, NULL);
+}
+
+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@redhat.com>");
+



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch 2/5] cpuidle: add poll_limit_ns to cpuidle_device structure
  2019-07-03 23:51 [patch 0/5] cpuidle haltpoll driver and governor (v6) Marcelo Tosatti
  2019-07-03 23:51 ` [patch 1/5] add cpuidle-haltpoll driver Marcelo Tosatti
@ 2019-07-03 23:51 ` Marcelo Tosatti
  2019-07-03 23:51 ` [patch 3/5] governors: unify last_state_idx Marcelo Tosatti
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Marcelo Tosatti @ 2019-07-03 23:51 UTC (permalink / raw)
  To: kvm-devel
  Cc: Paolo Bonzini, Radim Krcmar, Andrea Arcangeli, Rafael J. Wysocki,
	Peter Zijlstra, Wanpeng Li, Konrad Rzeszutek Wilk,
	Raslan KarimAllah, Boris Ostrovsky, Ankur Arora,
	Christian Borntraeger, linux-pm, Marcelo Tosatti

[-- Attachment #1: 01-poll-time --]
[-- Type: text/plain, Size: 5475 bytes --]

Add a poll_limit_ns variable to cpuidle_device structure. 

Calculate and configure it in the new cpuidle_poll_time
function, in case its zero.

Individual governors are allowed to override this value.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

---
 drivers/cpuidle/cpuidle.c    |   40 ++++++++++++++++++++++++++++++++++++++++
 drivers/cpuidle/poll_state.c |   11 ++---------
 include/linux/cpuidle.h      |    8 ++++++++
 3 files changed, 50 insertions(+), 9 deletions(-)

Index: linux-2.6-newcpuidle.git/drivers/cpuidle/cpuidle.c
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/cpuidle.c
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/cpuidle.c
@@ -362,6 +362,36 @@ void cpuidle_reflect(struct cpuidle_devi
 }
 
 /**
+ * cpuidle_poll_time - return amount of time to poll for,
+ * governors can override dev->poll_limit_ns if necessary
+ *
+ * @drv:   the cpuidle driver tied with the cpu
+ * @dev:   the cpuidle device
+ *
+ */
+u64 cpuidle_poll_time(struct cpuidle_driver *drv,
+		      struct cpuidle_device *dev)
+{
+	int i;
+	u64 limit_ns;
+
+	if (dev->poll_limit_ns)
+		return dev->poll_limit_ns;
+
+	limit_ns = TICK_NSEC;
+	for (i = 1; i < drv->state_count; i++) {
+		if (drv->states[i].disabled || dev->states_usage[i].disable)
+			continue;
+
+		limit_ns = (u64)drv->states[i].target_residency * NSEC_PER_USEC;
+	}
+
+	dev->poll_limit_ns = limit_ns;
+
+	return dev->poll_limit_ns;
+}
+
+/**
  * cpuidle_install_idle_handler - installs the cpuidle idle loop handler
  */
 void cpuidle_install_idle_handler(void)
Index: linux-2.6-newcpuidle.git/drivers/cpuidle/poll_state.c
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/poll_state.c
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/poll_state.c
@@ -20,16 +20,9 @@ static int __cpuidle poll_idle(struct cp
 	local_irq_enable();
 	if (!current_set_polling_and_test()) {
 		unsigned int loop_count = 0;
-		u64 limit = TICK_NSEC;
-		int i;
+		u64 limit;
 
-		for (i = 1; i < drv->state_count; i++) {
-			if (drv->states[i].disabled || dev->states_usage[i].disable)
-				continue;
-
-			limit = (u64)drv->states[i].target_residency * NSEC_PER_USEC;
-			break;
-		}
+		limit = cpuidle_poll_time(drv, dev);
 
 		while (!need_resched()) {
 			cpu_relax();
Index: linux-2.6-newcpuidle.git/include/linux/cpuidle.h
===================================================================
--- linux-2.6-newcpuidle.git.orig/include/linux/cpuidle.h
+++ linux-2.6-newcpuidle.git/include/linux/cpuidle.h
@@ -86,6 +86,7 @@ struct cpuidle_device {
 	ktime_t			next_hrtimer;
 
 	int			last_residency;
+	u64			poll_limit_ns;
 	struct cpuidle_state_usage	states_usage[CPUIDLE_STATE_MAX];
 	struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
 	struct cpuidle_driver_kobj *kobj_driver;
@@ -132,6 +133,8 @@ extern int cpuidle_select(struct cpuidle
 extern int cpuidle_enter(struct cpuidle_driver *drv,
 			 struct cpuidle_device *dev, int index);
 extern void cpuidle_reflect(struct cpuidle_device *dev, int index);
+extern u64 cpuidle_poll_time(struct cpuidle_driver *drv,
+			     struct cpuidle_device *dev);
 
 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
 extern struct cpuidle_driver *cpuidle_get_driver(void);
@@ -166,6 +169,9 @@ static inline int cpuidle_enter(struct c
 				struct cpuidle_device *dev, int index)
 {return -ENODEV; }
 static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { }
+extern u64 cpuidle_poll_time(struct cpuidle_driver *drv,
+			     struct cpuidle_device *dev)
+{return 0; }
 static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
 {return -ENODEV; }
 static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
Index: linux-2.6-newcpuidle.git/drivers/cpuidle/sysfs.c
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/sysfs.c
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/sysfs.c
@@ -334,6 +334,7 @@ struct cpuidle_state_kobj {
 	struct cpuidle_state_usage *state_usage;
 	struct completion kobj_unregister;
 	struct kobject kobj;
+	struct cpuidle_device *device;
 };
 
 #ifdef CONFIG_SUSPEND
@@ -391,6 +392,7 @@ static inline void cpuidle_remove_s2idle
 #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
 #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
 #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
+#define kobj_to_device(k) (kobj_to_state_obj(k)->device)
 #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
 
 static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr,
@@ -414,10 +416,14 @@ static ssize_t cpuidle_state_store(struc
 	struct cpuidle_state *state = kobj_to_state(kobj);
 	struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
 	struct cpuidle_state_attr *cattr = attr_to_stateattr(attr);
+	struct cpuidle_device *dev = kobj_to_device(kobj);
 
 	if (cattr->store)
 		ret = cattr->store(state, state_usage, buf, size);
 
+	/* reset poll time cache */
+	dev->poll_limit_ns = 0;
+
 	return ret;
 }
 
@@ -468,6 +474,7 @@ static int cpuidle_add_state_sysfs(struc
 		}
 		kobj->state = &drv->states[i];
 		kobj->state_usage = &device->states_usage[i];
+		kobj->device = device;
 		init_completion(&kobj->kobj_unregister);
 
 		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch 3/5] governors: unify last_state_idx
  2019-07-03 23:51 [patch 0/5] cpuidle haltpoll driver and governor (v6) Marcelo Tosatti
  2019-07-03 23:51 ` [patch 1/5] add cpuidle-haltpoll driver Marcelo Tosatti
  2019-07-03 23:51 ` [patch 2/5] cpuidle: add poll_limit_ns to cpuidle_device structure Marcelo Tosatti
@ 2019-07-03 23:51 ` Marcelo Tosatti
  2019-07-03 23:51 ` [patch 4/5] cpuidle: add haltpoll governor Marcelo Tosatti
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Marcelo Tosatti @ 2019-07-03 23:51 UTC (permalink / raw)
  To: kvm-devel
  Cc: Paolo Bonzini, Radim Krcmar, Andrea Arcangeli, Rafael J. Wysocki,
	Peter Zijlstra, Wanpeng Li, Konrad Rzeszutek Wilk,
	Raslan KarimAllah, Boris Ostrovsky, Ankur Arora,
	Christian Borntraeger, linux-pm, Marcelo Tosatti

[-- Attachment #1: 02-unify-last-used-idx --]
[-- Type: text/plain, Size: 6798 bytes --]

Since this field is shared by all governors, move it to 
cpuidle device structure.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

Index: linux-2.6-newcpuidle.git/drivers/cpuidle/governors/ladder.c
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/governors/ladder.c
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/governors/ladder.c
@@ -38,7 +38,6 @@ struct ladder_device_state {
 
 struct ladder_device {
 	struct ladder_device_state states[CPUIDLE_STATE_MAX];
-	int last_state_idx;
 };
 
 static DEFINE_PER_CPU(struct ladder_device, ladder_devices);
@@ -49,12 +48,13 @@ static DEFINE_PER_CPU(struct ladder_devi
  * @old_idx: the current state index
  * @new_idx: the new target state index
  */
-static inline void ladder_do_selection(struct ladder_device *ldev,
+static inline void ladder_do_selection(struct cpuidle_device *dev,
+				       struct ladder_device *ldev,
 				       int old_idx, int new_idx)
 {
 	ldev->states[old_idx].stats.promotion_count = 0;
 	ldev->states[old_idx].stats.demotion_count = 0;
-	ldev->last_state_idx = new_idx;
+	dev->last_state_idx = new_idx;
 }
 
 /**
@@ -68,13 +68,13 @@ static int ladder_select_state(struct cp
 {
 	struct ladder_device *ldev = this_cpu_ptr(&ladder_devices);
 	struct ladder_device_state *last_state;
-	int last_residency, last_idx = ldev->last_state_idx;
+	int last_residency, last_idx = dev->last_state_idx;
 	int first_idx = drv->states[0].flags & CPUIDLE_FLAG_POLLING ? 1 : 0;
 	int latency_req = cpuidle_governor_latency_req(dev->cpu);
 
 	/* Special case when user has set very strict latency requirement */
 	if (unlikely(latency_req == 0)) {
-		ladder_do_selection(ldev, last_idx, 0);
+		ladder_do_selection(dev, ldev, last_idx, 0);
 		return 0;
 	}
 
@@ -91,7 +91,7 @@ static int ladder_select_state(struct cp
 		last_state->stats.promotion_count++;
 		last_state->stats.demotion_count = 0;
 		if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
-			ladder_do_selection(ldev, last_idx, last_idx + 1);
+			ladder_do_selection(dev, ldev, last_idx, last_idx + 1);
 			return last_idx + 1;
 		}
 	}
@@ -107,7 +107,7 @@ static int ladder_select_state(struct cp
 			if (drv->states[i].exit_latency <= latency_req)
 				break;
 		}
-		ladder_do_selection(ldev, last_idx, i);
+		ladder_do_selection(dev, ldev, last_idx, i);
 		return i;
 	}
 
@@ -116,7 +116,7 @@ static int ladder_select_state(struct cp
 		last_state->stats.demotion_count++;
 		last_state->stats.promotion_count = 0;
 		if (last_state->stats.demotion_count >= last_state->threshold.demotion_count) {
-			ladder_do_selection(ldev, last_idx, last_idx - 1);
+			ladder_do_selection(dev, ldev, last_idx, last_idx - 1);
 			return last_idx - 1;
 		}
 	}
@@ -139,7 +139,7 @@ static int ladder_enable_device(struct c
 	struct ladder_device_state *lstate;
 	struct cpuidle_state *state;
 
-	ldev->last_state_idx = first_idx;
+	dev->last_state_idx = first_idx;
 
 	for (i = first_idx; i < drv->state_count; i++) {
 		state = &drv->states[i];
@@ -167,9 +167,8 @@ static int ladder_enable_device(struct c
  */
 static void ladder_reflect(struct cpuidle_device *dev, int index)
 {
-	struct ladder_device *ldev = this_cpu_ptr(&ladder_devices);
 	if (index > 0)
-		ldev->last_state_idx = index;
+		dev->last_state_idx = index;
 }
 
 static struct cpuidle_governor ladder_governor = {
Index: linux-2.6-newcpuidle.git/drivers/cpuidle/governors/menu.c
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/governors/menu.c
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/governors/menu.c
@@ -117,7 +117,6 @@
  */
 
 struct menu_device {
-	int		last_state_idx;
 	int             needs_update;
 	int             tick_wakeup;
 
@@ -455,7 +454,7 @@ static void menu_reflect(struct cpuidle_
 {
 	struct menu_device *data = this_cpu_ptr(&menu_devices);
 
-	data->last_state_idx = index;
+	dev->last_state_idx = index;
 	data->needs_update = 1;
 	data->tick_wakeup = tick_nohz_idle_got_tick();
 }
@@ -468,7 +467,7 @@ static void menu_reflect(struct cpuidle_
 static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
 {
 	struct menu_device *data = this_cpu_ptr(&menu_devices);
-	int last_idx = data->last_state_idx;
+	int last_idx = dev->last_state_idx;
 	struct cpuidle_state *target = &drv->states[last_idx];
 	unsigned int measured_us;
 	unsigned int new_factor;
Index: linux-2.6-newcpuidle.git/drivers/cpuidle/governors/teo.c
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/governors/teo.c
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/governors/teo.c
@@ -96,7 +96,6 @@ struct teo_idle_state {
  * @time_span_ns: Time between idle state selection and post-wakeup update.
  * @sleep_length_ns: Time till the closest timer event (at the selection time).
  * @states: Idle states data corresponding to this CPU.
- * @last_state: Idle state entered by the CPU last time.
  * @interval_idx: Index of the most recent saved idle interval.
  * @intervals: Saved idle duration values.
  */
@@ -104,7 +103,6 @@ struct teo_cpu {
 	u64 time_span_ns;
 	u64 sleep_length_ns;
 	struct teo_idle_state states[CPUIDLE_STATE_MAX];
-	int last_state;
 	int interval_idx;
 	unsigned int intervals[INTERVALS];
 };
@@ -130,7 +128,9 @@ static void teo_update(struct cpuidle_dr
 		 */
 		measured_us = sleep_length_us;
 	} else {
-		unsigned int lat = drv->states[cpu_data->last_state].exit_latency;
+		unsigned int lat;
+
+		lat = drv->states[dev->last_state_idx].exit_latency;
 
 		measured_us = ktime_to_us(cpu_data->time_span_ns);
 		/*
@@ -245,9 +245,9 @@ static int teo_select(struct cpuidle_dri
 	int max_early_idx, idx, i;
 	ktime_t delta_tick;
 
-	if (cpu_data->last_state >= 0) {
+	if (dev->last_state_idx >= 0) {
 		teo_update(drv, dev);
-		cpu_data->last_state = -1;
+		dev->last_state_idx = -1;
 	}
 
 	cpu_data->time_span_ns = local_clock();
@@ -394,7 +394,7 @@ static void teo_reflect(struct cpuidle_d
 {
 	struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
 
-	cpu_data->last_state = state;
+	dev->last_state_idx = state;
 	/*
 	 * If the wakeup was not "natural", but triggered by one of the safety
 	 * nets, assume that the CPU might have been idle for the entire sleep
Index: linux-2.6-newcpuidle.git/include/linux/cpuidle.h
===================================================================
--- linux-2.6-newcpuidle.git.orig/include/linux/cpuidle.h
+++ linux-2.6-newcpuidle.git/include/linux/cpuidle.h
@@ -85,6 +85,7 @@ struct cpuidle_device {
 	unsigned int		cpu;
 	ktime_t			next_hrtimer;
 
+	int			last_state_idx;
 	int			last_residency;
 	u64			poll_limit_ns;
 	struct cpuidle_state_usage	states_usage[CPUIDLE_STATE_MAX];



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch 4/5] cpuidle: add haltpoll governor
  2019-07-03 23:51 [patch 0/5] cpuidle haltpoll driver and governor (v6) Marcelo Tosatti
                   ` (2 preceding siblings ...)
  2019-07-03 23:51 ` [patch 3/5] governors: unify last_state_idx Marcelo Tosatti
@ 2019-07-03 23:51 ` Marcelo Tosatti
  2019-07-03 23:51 ` [patch 5/5] cpuidle-haltpoll: disable host side polling when kvm virtualized Marcelo Tosatti
  2019-07-04  8:32 ` [patch 0/5] cpuidle haltpoll driver and governor (v6) Rafael J. Wysocki
  5 siblings, 0 replies; 12+ messages in thread
From: Marcelo Tosatti @ 2019-07-03 23:51 UTC (permalink / raw)
  To: kvm-devel
  Cc: Paolo Bonzini, Radim Krcmar, Andrea Arcangeli, Rafael J. Wysocki,
	Peter Zijlstra, Wanpeng Li, Konrad Rzeszutek Wilk,
	Raslan KarimAllah, Boris Ostrovsky, Ankur Arora,
	Christian Borntraeger, linux-pm, Marcelo Tosatti

[-- Attachment #1: 03-cpuidle-haltpoll-governor --]
[-- Type: text/plain, Size: 9929 bytes --]

The cpuidle_haltpoll governor, in conjunction with the haltpoll cpuidle
driver, allows guest vcpus to poll for a specified amount of time before
halting.
This provides the following benefits to host side polling:

        1) The POLL flag is set while polling is performed, which allows
           a remote vCPU to avoid sending an IPI (and the associated
           cost of handling the IPI) when performing a wakeup.

        2) The VM-exit cost can be avoided.

The downside of guest side polling is that polling is performed
even with other runnable tasks in the host.

Results comparing halt_poll_ns and server/client application
where a small packet is ping-ponged:

host                                        --> 31.33
halt_poll_ns=300000 / no guest busy spin    --> 33.40   (93.8%)
halt_poll_ns=0 / guest_halt_poll_ns=300000  --> 32.73   (95.7%)

For the SAP HANA benchmarks (where idle_spin is a parameter
of the previous version of the patch, results should be the
same):

hpns == halt_poll_ns

                          idle_spin=0/   idle_spin=800/    idle_spin=0/
                          hpns=200000    hpns=0            hpns=800000
DeleteC06T03 (100 thread) 1.76           1.71 (-3%)        1.78   (+1%)
InsertC16T02 (100 thread) 2.14           2.07 (-3%)        2.18   (+1.8%)
DeleteC00T01 (1 thread)   1.34           1.28 (-4.5%)      1.29   (-3.7%)
UpdateC00T03 (1 thread)   4.72           4.18 (-12%)       4.53   (-5%)

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>


---
 Documentation/virtual/guest-halt-polling.txt |   79 ++++++++++++
 drivers/cpuidle/Kconfig                      |   11 +
 drivers/cpuidle/governors/Makefile           |    1 
 drivers/cpuidle/governors/haltpoll.c         |  175 +++++++++++++++++++++++++++
 4 files changed, 266 insertions(+)

Index: linux-2.6-newcpuidle.git/drivers/cpuidle/Kconfig
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/Kconfig
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/Kconfig
@@ -33,6 +33,17 @@ config CPU_IDLE_GOV_TEO
 	  Some workloads benefit from using it and it generally should be safe
 	  to use.  Say Y here if you are not happy with the alternatives.
 
+config CPU_IDLE_GOV_HALTPOLL
+	bool "Haltpoll governor (for virtualized systems)"
+	depends on KVM_GUEST
+	help
+	  This governor implements haltpoll idle state selection, to be
+	  used in conjunction with the haltpoll cpuidle driver, allowing
+	  for polling for a certain amount of time before entering idle
+	  state.
+
+	  Some virtualized workloads benefit from using it.
+
 config DT_IDLE_STATES
 	bool
 
Index: linux-2.6-newcpuidle.git/drivers/cpuidle/governors/Makefile
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/governors/Makefile
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/governors/Makefile
@@ -6,3 +6,4 @@
 obj-$(CONFIG_CPU_IDLE_GOV_LADDER) += ladder.o
 obj-$(CONFIG_CPU_IDLE_GOV_MENU) += menu.o
 obj-$(CONFIG_CPU_IDLE_GOV_TEO) += teo.o
+obj-$(CONFIG_CPU_IDLE_GOV_HALTPOLL) += haltpoll.o
Index: linux-2.6-newcpuidle.git/drivers/cpuidle/governors/haltpoll.c
===================================================================
--- /dev/null
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/governors/haltpoll.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * haltpoll.c - haltpoll idle 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@redhat.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/cpuidle.h>
+#include <linux/time.h>
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kvm_para.h>
+
+static unsigned int guest_halt_poll_ns __read_mostly = 200000;
+module_param(guest_halt_poll_ns, uint, 0644);
+
+/* division factor to shrink halt_poll_ns */
+static unsigned int guest_halt_poll_shrink __read_mostly = 2;
+module_param(guest_halt_poll_shrink, uint, 0644);
+
+/* multiplication factor to grow per-cpu poll_limit_ns */
+static unsigned int guest_halt_poll_grow __read_mostly = 2;
+module_param(guest_halt_poll_grow, uint, 0644);
+
+/* value in us to start growing per-cpu halt_poll_ns */
+static unsigned int guest_halt_poll_grow_start __read_mostly = 50000;
+module_param(guest_halt_poll_grow_start, uint, 0644);
+
+/* allow shrinking guest halt poll */
+static bool guest_halt_poll_allow_shrink __read_mostly = true;
+module_param(guest_halt_poll_allow_shrink, bool, 0644);
+
+/**
+ * haltpoll_select - selects the next idle state to enter
+ * @drv: cpuidle driver containing state data
+ * @dev: the CPU
+ * @stop_tick: indication on whether or not to stop the tick
+ */
+static int haltpoll_select(struct cpuidle_driver *drv,
+			   struct cpuidle_device *dev,
+			   bool *stop_tick)
+{
+	int latency_req = cpuidle_governor_latency_req(dev->cpu);
+
+	if (!drv->state_count || latency_req == 0) {
+		*stop_tick = false;
+		return 0;
+	}
+
+	if (dev->poll_limit_ns == 0)
+		return 1;
+
+	/* Last state was poll? */
+	if (dev->last_state_idx == 0) {
+		/* Halt if no event occurred on poll window */
+		if (dev->poll_time_limit == true)
+			return 1;
+
+		*stop_tick = false;
+		/* Otherwise, poll again */
+		return 0;
+	}
+
+	*stop_tick = false;
+	/* Last state was halt: poll */
+	return 0;
+}
+
+static void adjust_poll_limit(struct cpuidle_device *dev, unsigned int block_us)
+{
+	unsigned int val;
+	u64 block_ns = block_us*NSEC_PER_USEC;
+
+	/* Grow cpu_halt_poll_us if
+	 * cpu_halt_poll_us < block_ns < guest_halt_poll_us
+	 */
+	if (block_ns > dev->poll_limit_ns && block_ns <= guest_halt_poll_ns) {
+		val = dev->poll_limit_ns * guest_halt_poll_grow;
+
+		if (val < guest_halt_poll_grow_start)
+			val = guest_halt_poll_grow_start;
+		if (val > guest_halt_poll_ns)
+			val = guest_halt_poll_ns;
+
+		dev->poll_limit_ns = val;
+	} else if (block_ns > guest_halt_poll_ns &&
+		   guest_halt_poll_allow_shrink) {
+		unsigned int shrink = guest_halt_poll_shrink;
+
+		val = dev->poll_limit_ns;
+		if (shrink == 0)
+			val = 0;
+		else
+			val /= shrink;
+		dev->poll_limit_ns = val;
+	}
+}
+
+/**
+ * haltpoll_reflect - update variables and update poll time
+ * @dev: the CPU
+ * @index: the index of actual entered state
+ */
+static void haltpoll_reflect(struct cpuidle_device *dev, int index)
+{
+	dev->last_state_idx = index;
+
+	if (index != 0)
+		adjust_poll_limit(dev, dev->last_residency);
+}
+
+/**
+ * haltpoll_enable_device - scans a CPU's states and does setup
+ * @drv: cpuidle driver
+ * @dev: the CPU
+ */
+static int haltpoll_enable_device(struct cpuidle_driver *drv,
+				  struct cpuidle_device *dev)
+{
+	dev->poll_limit_ns = 0;
+
+	return 0;
+}
+
+static struct cpuidle_governor haltpoll_governor = {
+	.name =			"haltpoll",
+	.rating =		21,
+	.enable =		haltpoll_enable_device,
+	.select =		haltpoll_select,
+	.reflect =		haltpoll_reflect,
+};
+
+static int __init init_haltpoll(void)
+{
+	if (kvm_para_available())
+		return cpuidle_register_governor(&haltpoll_governor);
+
+	return 0;
+}
+
+postcore_initcall(init_haltpoll);
Index: linux-2.6-newcpuidle.git/Documentation/virtual/guest-halt-polling.txt
===================================================================
--- /dev/null
+++ linux-2.6-newcpuidle.git/Documentation/virtual/guest-halt-polling.txt
@@ -0,0 +1,79 @@
+Guest halt polling
+==================
+
+The cpuidle_haltpoll driver, with the haltpoll governor, allows
+the guest vcpus to poll for a specified amount of time before
+halting.
+This provides the following benefits to host side polling:
+
+	1) The POLL flag is set while polling is performed, which allows
+	   a remote vCPU to avoid sending an IPI (and the associated
+ 	   cost of handling the IPI) when performing a wakeup.
+
+	2) The VM-exit cost can be avoided.
+
+The downside of guest side polling is that polling is performed
+even with other runnable tasks in the host.
+
+The basic logic as follows: A global value, guest_halt_poll_ns,
+is configured by the user, indicating the maximum amount of
+time polling is allowed. This value is fixed.
+
+Each vcpu has an adjustable guest_halt_poll_ns
+("per-cpu guest_halt_poll_ns"), which is adjusted by the algorithm
+in response to events (explained below).
+
+Module Parameters
+=================
+
+The haltpoll governor has 5 tunable module parameters:
+
+1) guest_halt_poll_ns:
+Maximum amount of time, in nanoseconds, that polling is
+performed before halting.
+
+Default: 200000
+
+2) guest_halt_poll_shrink:
+Division factor used to shrink per-cpu guest_halt_poll_ns when
+wakeup event occurs after the global guest_halt_poll_ns.
+
+Default: 2
+
+3) guest_halt_poll_grow:
+Multiplication factor used to grow per-cpu guest_halt_poll_ns
+when event occurs after per-cpu guest_halt_poll_ns
+but before global guest_halt_poll_ns.
+
+Default: 2
+
+4) guest_halt_poll_grow_start:
+The per-cpu guest_halt_poll_ns eventually reaches zero
+in case of an idle system. This value sets the initial
+per-cpu guest_halt_poll_ns when growing. This can
+be increased from 10000, to avoid misses during the initial
+growth stage:
+
+10k, 20k, 40k, ... (example assumes guest_halt_poll_grow=2).
+
+Default: 50000
+
+5) guest_halt_poll_allow_shrink:
+
+Bool parameter which allows shrinking. Set to N
+to avoid it (per-cpu guest_halt_poll_ns will remain
+high once achieves global guest_halt_poll_ns value).
+
+Default: Y
+
+The module parameters can be set from the debugfs files in:
+
+	/sys/module/haltpoll/parameters/
+
+Further Notes
+=============
+
+- Care should be taken when setting the guest_halt_poll_ns parameter as a
+large value has the potential to drive the cpu usage to 100% on a machine which
+would be almost entirely idle otherwise.
+



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch 5/5] cpuidle-haltpoll: disable host side polling when kvm virtualized
  2019-07-03 23:51 [patch 0/5] cpuidle haltpoll driver and governor (v6) Marcelo Tosatti
                   ` (3 preceding siblings ...)
  2019-07-03 23:51 ` [patch 4/5] cpuidle: add haltpoll governor Marcelo Tosatti
@ 2019-07-03 23:51 ` Marcelo Tosatti
  2019-07-04  8:32 ` [patch 0/5] cpuidle haltpoll driver and governor (v6) Rafael J. Wysocki
  5 siblings, 0 replies; 12+ messages in thread
From: Marcelo Tosatti @ 2019-07-03 23:51 UTC (permalink / raw)
  To: kvm-devel
  Cc: Paolo Bonzini, Radim Krcmar, Andrea Arcangeli, Rafael J. Wysocki,
	Peter Zijlstra, Wanpeng Li, Konrad Rzeszutek Wilk,
	Raslan KarimAllah, Boris Ostrovsky, Ankur Arora,
	Christian Borntraeger, linux-pm, Marcelo Tosatti

[-- Attachment #1: 04-pollcontrol-guest.patch --]
[-- Type: text/plain, Size: 4631 bytes --]

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: Marcelo Tosatti <mtosatti@redhat.com>

---
 arch/x86/Kconfig                        |    7 +++++
 arch/x86/include/asm/cpuidle_haltpoll.h |    8 ++++++
 arch/x86/kernel/kvm.c                   |   42 ++++++++++++++++++++++++++++++++
 drivers/cpuidle/cpuidle-haltpoll.c      |   10 ++++++-
 include/linux/cpuidle_haltpoll.h        |   16 ++++++++++++
 5 files changed, 82 insertions(+), 1 deletion(-)

Index: kvm/arch/x86/include/asm/cpuidle_haltpoll.h
===================================================================
--- /dev/null
+++ kvm/arch/x86/include/asm/cpuidle_haltpoll.h
@@ -0,0 +1,8 @@
+/* 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
Index: kvm/drivers/cpuidle/cpuidle-haltpoll.c
===================================================================
--- kvm.orig/drivers/cpuidle/cpuidle-haltpoll.c
+++ kvm/drivers/cpuidle/cpuidle-haltpoll.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/sched/idle.h>
 #include <linux/kvm_para.h>
+#include <linux/cpuidle_haltpoll.h>
 
 static int default_enter_idle(struct cpuidle_device *dev,
 			      struct cpuidle_driver *drv, int index)
@@ -47,6 +48,7 @@ static struct cpuidle_driver haltpoll_dr
 
 static int __init haltpoll_init(void)
 {
+	int ret;
 	struct cpuidle_driver *drv = &haltpoll_driver;
 
 	cpuidle_poll_state_init(drv);
@@ -54,11 +56,16 @@ static int __init haltpoll_init(void)
 	if (!kvm_para_available())
 		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)
 {
+	arch_haltpoll_disable();
 	cpuidle_unregister(&haltpoll_driver);
 }
 
Index: kvm/include/linux/cpuidle_haltpoll.h
===================================================================
--- /dev/null
+++ kvm/include/linux/cpuidle_haltpoll.h
@@ -0,0 +1,16 @@
+/* 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
Index: kvm/arch/x86/Kconfig
===================================================================
--- kvm.orig/arch/x86/Kconfig
+++ kvm/arch/x86/Kconfig
@@ -787,6 +787,7 @@ config KVM_GUEST
 	bool "KVM Guest support (including kvmclock)"
 	depends on PARAVIRT
 	select PARAVIRT_CLOCK
+	select ARCH_CPUIDLE_HALTPOLL
 	default y
 	---help---
 	  This option enables various optimizations for running under the KVM
@@ -795,6 +796,12 @@ config KVM_GUEST
 	  underlying device model, the host provides the guest with
 	  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
 	bool "Support for running PVH guests"
 	---help---
Index: kvm/arch/x86/kernel/kvm.c
===================================================================
--- kvm.orig/arch/x86/kernel/kvm.c
+++ kvm/arch/x86/kernel/kvm.c
@@ -874,3 +874,45 @@ 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(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



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 0/5] cpuidle haltpoll driver and governor (v6)
  2019-07-03 23:51 [patch 0/5] cpuidle haltpoll driver and governor (v6) Marcelo Tosatti
                   ` (4 preceding siblings ...)
  2019-07-03 23:51 ` [patch 5/5] cpuidle-haltpoll: disable host side polling when kvm virtualized Marcelo Tosatti
@ 2019-07-04  8:32 ` Rafael J. Wysocki
  2019-07-22 15:25   ` Paolo Bonzini
  5 siblings, 1 reply; 12+ messages in thread
From: Rafael J. Wysocki @ 2019-07-04  8:32 UTC (permalink / raw)
  To: Marcelo Tosatti
  Cc: kvm-devel, Paolo Bonzini, Radim Krcmar, Andrea Arcangeli,
	Rafael J. Wysocki, Peter Zijlstra, Wanpeng Li,
	Konrad Rzeszutek Wilk, Raslan KarimAllah, Boris Ostrovsky,
	Ankur Arora, Christian Borntraeger, Linux PM

On Thu, Jul 4, 2019 at 1:59 AM Marcelo Tosatti <mtosatti@redhat.com> wrote:
>
> (rebased against queue branch of kvm.git tree)
>
> The cpuidle-haltpoll driver with haltpoll governor allows the guest
> vcpus to poll for a specified amount of time before halting.
> This provides the following benefits to host side polling:
>
>          1) The POLL flag is set while polling is performed, which allows
>             a remote vCPU to avoid sending an IPI (and the associated
>             cost of handling the IPI) when performing a wakeup.
>
>          2) The VM-exit cost can be avoided.
>
> The downside of guest side polling is that polling is performed
> even with other runnable tasks in the host.
>
> Results comparing halt_poll_ns and server/client application
> where a small packet is ping-ponged:
>
> host                                        --> 31.33
> halt_poll_ns=300000 / no guest busy spin    --> 33.40   (93.8%)
> halt_poll_ns=0 / guest_halt_poll_ns=300000  --> 32.73   (95.7%)
>
> For the SAP HANA benchmarks (where idle_spin is a parameter
> of the previous version of the patch, results should be the
> same):
>
> hpns == halt_poll_ns
>
>                            idle_spin=0/   idle_spin=800/    idle_spin=0/
>                            hpns=200000    hpns=0            hpns=800000
> DeleteC06T03 (100 thread) 1.76           1.71 (-3%)        1.78   (+1%)
> InsertC16T02 (100 thread) 2.14           2.07 (-3%)        2.18   (+1.8%)
> DeleteC00T01 (1 thread)   1.34           1.28 (-4.5%)      1.29   (-3.7%)
> UpdateC00T03 (1 thread)   4.72           4.18 (-12%)       4.53   (-5%)
>
> V2:
>
> - Move from x86 to generic code (Paolo/Christian)
> - Add auto-tuning logic (Paolo)
> - Add MSR to disable host side polling (Paolo)
>
> V3:
>
> - Do not be specific about HLT VM-exit in the documentation (Ankur Arora)
> - Mark tuning parameters static and __read_mostly (Andrea Arcangeli)
> - Add WARN_ON if host does not support poll control (Joao Martins)
> - Use sched_clock and cleanup haltpoll_enter_idle (Peter Zijlstra)
> - Mark certain functions in kvm.c as static (kernel test robot)
> - Remove tracepoints as they use RCU from extended quiescent state (kernel
> test robot)
>
> V4:
> - Use a haltpoll governor, use poll_state.c poll code (Rafael J. Wysocki)
>
> V5:
> - Take latency requirement into consideration (Rafael J. Wysocki)
> - Set target_residency/exit_latency to 1 (Rafael J. Wysocki)
> - Do not load cpuidle driver if not virtualized (Rafael J. Wysocki)
>
> V6:
> - Switch from callback to poll_limit_ns variable in cpuidle device structure
> (Rafael J. Wysocki)
> - Move last_used_idx to cpuidle device structure (Rafael J. Wysocki)
> - Drop per-cpu device structure in haltpoll governor (Rafael J. Wysocki)

It looks good to me now, but I have some cpuidle changes in the work
that will clash in some changes in this series if not rebased on top
of it, so IMO it would make sense for me to get patches [1-4/5] at
least into my queue.  I can expose an immutable branch with them for
the KVM tree to consume.  I can take the last patch in the series as
well if I get an ACK for it.

Would that work for everybody?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 1/5] add cpuidle-haltpoll driver
  2019-07-03 23:51 ` [patch 1/5] add cpuidle-haltpoll driver Marcelo Tosatti
@ 2019-07-04  9:16   ` Joao Martins
  2019-07-04 11:13     ` Marcelo Tosatti
  0 siblings, 1 reply; 12+ messages in thread
From: Joao Martins @ 2019-07-04  9:16 UTC (permalink / raw)
  To: Marcelo Tosatti
  Cc: kvm-devel, Paolo Bonzini, Radim Krcmar, Andrea Arcangeli,
	Rafael J. Wysocki, Peter Zijlstra, Wanpeng Li,
	Konrad Rzeszutek Wilk, Raslan KarimAllah, Boris Ostrovsky,
	Ankur Arora, Christian Borntraeger, linux-pm

On 7/4/19 12:51 AM, Marcelo Tosatti wrote:
> +++ linux-2.6-newcpuidle.git/drivers/cpuidle/cpuidle-haltpoll.c
> @@ -0,0 +1,69 @@
> +// 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@redhat.com>
> + */
> +
> +#include <linux/init.h>
> +#include <linux/cpuidle.h>
> +#include <linux/module.h>
> +#include <linux/sched/idle.h>
> +#include <linux/kvm_para.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		= 1,
> +			.target_residency	= 1,
> +			.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);
> +
> +	if (!kvm_para_available())
> +		return 0;
> +

Isn't this meant to return -ENODEV value if the module is meant to not load?

Also this check should probably be placed before initializing the poll state,
provided poll state isn't used anyways if you're not a kvm guest.

	Joao

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 1/5] add cpuidle-haltpoll driver
  2019-07-04  9:16   ` Joao Martins
@ 2019-07-04 11:13     ` Marcelo Tosatti
  0 siblings, 0 replies; 12+ messages in thread
From: Marcelo Tosatti @ 2019-07-04 11:13 UTC (permalink / raw)
  To: Joao Martins
  Cc: kvm-devel, Paolo Bonzini, Radim Krcmar, Andrea Arcangeli,
	Rafael J. Wysocki, Peter Zijlstra, Wanpeng Li,
	Konrad Rzeszutek Wilk, Raslan KarimAllah, Boris Ostrovsky,
	Ankur Arora, Christian Borntraeger, linux-pm

On Thu, Jul 04, 2019 at 10:16:47AM +0100, Joao Martins wrote:
> On 7/4/19 12:51 AM, Marcelo Tosatti wrote:
> > +++ linux-2.6-newcpuidle.git/drivers/cpuidle/cpuidle-haltpoll.c
> > @@ -0,0 +1,69 @@
> > +// 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@redhat.com>
> > + */
> > +
> > +#include <linux/init.h>
> > +#include <linux/cpuidle.h>
> > +#include <linux/module.h>
> > +#include <linux/sched/idle.h>
> > +#include <linux/kvm_para.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		= 1,
> > +			.target_residency	= 1,
> > +			.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);
> > +
> > +	if (!kvm_para_available())
> > +		return 0;
> > +
> 
> Isn't this meant to return -ENODEV value if the module is meant to not load?

Well, the cpuidle drivers return an error only if registration fails.

> Also this check should probably be placed before initializing the poll state,
> provided poll state isn't used anyways if you're not a kvm guest.

Poll state init is only local variable initialization, it does not
have any external effect.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 0/5] cpuidle haltpoll driver and governor (v6)
  2019-07-04  8:32 ` [patch 0/5] cpuidle haltpoll driver and governor (v6) Rafael J. Wysocki
@ 2019-07-22 15:25   ` Paolo Bonzini
  0 siblings, 0 replies; 12+ messages in thread
From: Paolo Bonzini @ 2019-07-22 15:25 UTC (permalink / raw)
  To: Rafael J. Wysocki, Marcelo Tosatti
  Cc: kvm-devel, Radim Krcmar, Andrea Arcangeli, Rafael J. Wysocki,
	Peter Zijlstra, Wanpeng Li, Konrad Rzeszutek Wilk,
	Raslan KarimAllah, Boris Ostrovsky, Ankur Arora,
	Christian Borntraeger, Linux PM

On 04/07/19 10:32, Rafael J. Wysocki wrote:
> On Thu, Jul 4, 2019 at 1:59 AM Marcelo Tosatti <mtosatti@redhat.com> wrote:
>>
>> (rebased against queue branch of kvm.git tree)
>>
>> The cpuidle-haltpoll driver with haltpoll governor allows the guest
>> vcpus to poll for a specified amount of time before halting.
>> This provides the following benefits to host side polling:
>>
>>          1) The POLL flag is set while polling is performed, which allows
>>             a remote vCPU to avoid sending an IPI (and the associated
>>             cost of handling the IPI) when performing a wakeup.
>>
>>          2) The VM-exit cost can be avoided.
>>
>> The downside of guest side polling is that polling is performed
>> even with other runnable tasks in the host.
>>
>> Results comparing halt_poll_ns and server/client application
>> where a small packet is ping-ponged:
>>
>> host                                        --> 31.33
>> halt_poll_ns=300000 / no guest busy spin    --> 33.40   (93.8%)
>> halt_poll_ns=0 / guest_halt_poll_ns=300000  --> 32.73   (95.7%)
>>
>> For the SAP HANA benchmarks (where idle_spin is a parameter
>> of the previous version of the patch, results should be the
>> same):
>>
>> hpns == halt_poll_ns
>>
>>                            idle_spin=0/   idle_spin=800/    idle_spin=0/
>>                            hpns=200000    hpns=0            hpns=800000
>> DeleteC06T03 (100 thread) 1.76           1.71 (-3%)        1.78   (+1%)
>> InsertC16T02 (100 thread) 2.14           2.07 (-3%)        2.18   (+1.8%)
>> DeleteC00T01 (1 thread)   1.34           1.28 (-4.5%)      1.29   (-3.7%)
>> UpdateC00T03 (1 thread)   4.72           4.18 (-12%)       4.53   (-5%)
>>
>> V2:
>>
>> - Move from x86 to generic code (Paolo/Christian)
>> - Add auto-tuning logic (Paolo)
>> - Add MSR to disable host side polling (Paolo)
>>
>> V3:
>>
>> - Do not be specific about HLT VM-exit in the documentation (Ankur Arora)
>> - Mark tuning parameters static and __read_mostly (Andrea Arcangeli)
>> - Add WARN_ON if host does not support poll control (Joao Martins)
>> - Use sched_clock and cleanup haltpoll_enter_idle (Peter Zijlstra)
>> - Mark certain functions in kvm.c as static (kernel test robot)
>> - Remove tracepoints as they use RCU from extended quiescent state (kernel
>> test robot)
>>
>> V4:
>> - Use a haltpoll governor, use poll_state.c poll code (Rafael J. Wysocki)
>>
>> V5:
>> - Take latency requirement into consideration (Rafael J. Wysocki)
>> - Set target_residency/exit_latency to 1 (Rafael J. Wysocki)
>> - Do not load cpuidle driver if not virtualized (Rafael J. Wysocki)
>>
>> V6:
>> - Switch from callback to poll_limit_ns variable in cpuidle device structure
>> (Rafael J. Wysocki)
>> - Move last_used_idx to cpuidle device structure (Rafael J. Wysocki)
>> - Drop per-cpu device structure in haltpoll governor (Rafael J. Wysocki)
> 
> It looks good to me now, but I have some cpuidle changes in the work
> that will clash in some changes in this series if not rebased on top
> of it, so IMO it would make sense for me to get patches [1-4/5] at
> least into my queue.  I can expose an immutable branch with them for
> the KVM tree to consume.  I can take the last patch in the series as
> well if I get an ACK for it.
> 
> Would that work for everybody?

Rafael, please take the whole series in your tree.  Thanks!

Paolo

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch 1/5] add cpuidle-haltpoll driver
  2019-07-01 18:53 ` [patch 1/5] add cpuidle-haltpoll driver Marcelo Tosatti
@ 2019-07-03  9:54   ` Rafael J. Wysocki
  0 siblings, 0 replies; 12+ messages in thread
From: Rafael J. Wysocki @ 2019-07-03  9:54 UTC (permalink / raw)
  To: Marcelo Tosatti
  Cc: kvm-devel, Linux PM, Paolo Bonzini, Radim Krcmar,
	Andrea Arcangeli, Rafael J. Wysocki, Peter Zijlstra, Wanpeng Li,
	Konrad Rzeszutek Wilk, Raslan KarimAllah, Boris Ostrovsky,
	Ankur Arora, Christian Borntraeger

On Mon, Jul 1, 2019 at 8:57 PM Marcelo Tosatti <mtosatti@redhat.com> 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@redhat.com>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

>
> ---
>  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-newcpuidle.git/arch/x86/kernel/process.c
> ===================================================================
> --- linux-2.6-newcpuidle.git.orig/arch/x86/kernel/process.c
> +++ linux-2.6-newcpuidle.git/arch/x86/kernel/process.c
> @@ -580,7 +580,7 @@ void __cpuidle default_idle(void)
>         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-newcpuidle.git/drivers/cpuidle/Kconfig
> ===================================================================
> --- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/Kconfig
> +++ linux-2.6-newcpuidle.git/drivers/cpuidle/Kconfig
> @@ -51,6 +51,15 @@ depends on PPC
>  source "drivers/cpuidle/Kconfig.powerpc"
>  endmenu
>
> +config HALTPOLL_CPUIDLE
> +       tristate "Halt poll cpuidle driver"
> +       depends on X86 && KVM_GUEST
> +       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-newcpuidle.git/drivers/cpuidle/Makefile
> ===================================================================
> --- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/Makefile
> +++ linux-2.6-newcpuidle.git/drivers/cpuidle/Makefile
> @@ -7,6 +7,7 @@ obj-y += cpuidle.o driver.o governor.o s
>  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-newcpuidle.git/drivers/cpuidle/cpuidle-haltpoll.c
> ===================================================================
> --- /dev/null
> +++ linux-2.6-newcpuidle.git/drivers/cpuidle/cpuidle-haltpoll.c
> @@ -0,0 +1,69 @@
> +// 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@redhat.com>
> + */
> +
> +#include <linux/init.h>
> +#include <linux/cpuidle.h>
> +#include <linux/module.h>
> +#include <linux/sched/idle.h>
> +#include <linux/kvm_para.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           = 1,
> +                       .target_residency       = 1,
> +                       .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);
> +
> +       if (!kvm_para_available())
> +               return 0;
> +
> +       return cpuidle_register(&haltpoll_driver, NULL);
> +}
> +
> +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@redhat.com>");
> +
>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch 1/5] add cpuidle-haltpoll driver
  2019-07-01 18:53 [patch 0/5] cpuidle haltpoll driver and governor (v5) Marcelo Tosatti
@ 2019-07-01 18:53 ` Marcelo Tosatti
  2019-07-03  9:54   ` Rafael J. Wysocki
  0 siblings, 1 reply; 12+ messages in thread
From: Marcelo Tosatti @ 2019-07-01 18:53 UTC (permalink / raw)
  To: kvm, linux-pm
  Cc: Paolo Bonzini, Radim Krcmar, Andrea Arcangeli, Rafael J. Wysocki,
	Peter Zijlstra, Wanpeng Li, Konrad Rzeszutek Wilk,
	Raslan KarimAllah, Boris Ostrovsky, Ankur Arora,
	Christian Borntraeger, Marcelo Tosatti

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@redhat.com>

---
 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-newcpuidle.git/arch/x86/kernel/process.c
===================================================================
--- linux-2.6-newcpuidle.git.orig/arch/x86/kernel/process.c
+++ linux-2.6-newcpuidle.git/arch/x86/kernel/process.c
@@ -580,7 +580,7 @@ void __cpuidle default_idle(void)
 	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-newcpuidle.git/drivers/cpuidle/Kconfig
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/Kconfig
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/Kconfig
@@ -51,6 +51,15 @@ depends on PPC
 source "drivers/cpuidle/Kconfig.powerpc"
 endmenu
 
+config HALTPOLL_CPUIDLE
+       tristate "Halt poll cpuidle driver"
+       depends on X86 && KVM_GUEST
+       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-newcpuidle.git/drivers/cpuidle/Makefile
===================================================================
--- linux-2.6-newcpuidle.git.orig/drivers/cpuidle/Makefile
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/Makefile
@@ -7,6 +7,7 @@ obj-y += cpuidle.o driver.o governor.o s
 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-newcpuidle.git/drivers/cpuidle/cpuidle-haltpoll.c
===================================================================
--- /dev/null
+++ linux-2.6-newcpuidle.git/drivers/cpuidle/cpuidle-haltpoll.c
@@ -0,0 +1,69 @@
+// 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@redhat.com>
+ */
+
+#include <linux/init.h>
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <linux/sched/idle.h>
+#include <linux/kvm_para.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		= 1,
+			.target_residency	= 1,
+			.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);
+
+	if (!kvm_para_available())
+		return 0;
+
+	return cpuidle_register(&haltpoll_driver, NULL);
+}
+
+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@redhat.com>");
+



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2019-07-22 15:25 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-03 23:51 [patch 0/5] cpuidle haltpoll driver and governor (v6) Marcelo Tosatti
2019-07-03 23:51 ` [patch 1/5] add cpuidle-haltpoll driver Marcelo Tosatti
2019-07-04  9:16   ` Joao Martins
2019-07-04 11:13     ` Marcelo Tosatti
2019-07-03 23:51 ` [patch 2/5] cpuidle: add poll_limit_ns to cpuidle_device structure Marcelo Tosatti
2019-07-03 23:51 ` [patch 3/5] governors: unify last_state_idx Marcelo Tosatti
2019-07-03 23:51 ` [patch 4/5] cpuidle: add haltpoll governor Marcelo Tosatti
2019-07-03 23:51 ` [patch 5/5] cpuidle-haltpoll: disable host side polling when kvm virtualized Marcelo Tosatti
2019-07-04  8:32 ` [patch 0/5] cpuidle haltpoll driver and governor (v6) Rafael J. Wysocki
2019-07-22 15:25   ` Paolo Bonzini
  -- strict thread matches above, loose matches on Subject: below --
2019-07-01 18:53 [patch 0/5] cpuidle haltpoll driver and governor (v5) Marcelo Tosatti
2019-07-01 18:53 ` [patch 1/5] add cpuidle-haltpoll driver Marcelo Tosatti
2019-07-03  9:54   ` Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).