^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * haltpoll.c - haltpoll idle governor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2019 Red Hat, Inc. and/or its affiliates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This work is licensed under the terms of the GNU GPL, version 2. See
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * the COPYING file in the top-level directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Authors: Marcelo Tosatti <mtosatti@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/cpuidle.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/hrtimer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/tick.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kvm_para.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static unsigned int guest_halt_poll_ns __read_mostly = 200000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) module_param(guest_halt_poll_ns, uint, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* division factor to shrink halt_poll_ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static unsigned int guest_halt_poll_shrink __read_mostly = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) module_param(guest_halt_poll_shrink, uint, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* multiplication factor to grow per-cpu poll_limit_ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static unsigned int guest_halt_poll_grow __read_mostly = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) module_param(guest_halt_poll_grow, uint, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* value in us to start growing per-cpu halt_poll_ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static unsigned int guest_halt_poll_grow_start __read_mostly = 50000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) module_param(guest_halt_poll_grow_start, uint, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* allow shrinking guest halt poll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static bool guest_halt_poll_allow_shrink __read_mostly = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) module_param(guest_halt_poll_allow_shrink, bool, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * haltpoll_select - selects the next idle state to enter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * @drv: cpuidle driver containing state data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * @dev: the CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * @stop_tick: indication on whether or not to stop the tick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static int haltpoll_select(struct cpuidle_driver *drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct cpuidle_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) bool *stop_tick)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) s64 latency_req = cpuidle_governor_latency_req(dev->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (!drv->state_count || latency_req == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *stop_tick = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (dev->poll_limit_ns == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* Last state was poll? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (dev->last_state_idx == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* Halt if no event occurred on poll window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (dev->poll_time_limit == true)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *stop_tick = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Otherwise, poll again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *stop_tick = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Last state was halt: poll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static void adjust_poll_limit(struct cpuidle_device *dev, u64 block_ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* Grow cpu_halt_poll_us if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * cpu_halt_poll_us < block_ns < guest_halt_poll_us
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (block_ns > dev->poll_limit_ns && block_ns <= guest_halt_poll_ns) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) val = dev->poll_limit_ns * guest_halt_poll_grow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (val < guest_halt_poll_grow_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) val = guest_halt_poll_grow_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (val > guest_halt_poll_ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) val = guest_halt_poll_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) dev->poll_limit_ns = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) } else if (block_ns > guest_halt_poll_ns &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) guest_halt_poll_allow_shrink) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned int shrink = guest_halt_poll_shrink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) val = dev->poll_limit_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (shrink == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) val /= shrink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dev->poll_limit_ns = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * haltpoll_reflect - update variables and update poll time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @dev: the CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * @index: the index of actual entered state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static void haltpoll_reflect(struct cpuidle_device *dev, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) dev->last_state_idx = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) adjust_poll_limit(dev, dev->last_residency_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * haltpoll_enable_device - scans a CPU's states and does setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * @drv: cpuidle driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * @dev: the CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int haltpoll_enable_device(struct cpuidle_driver *drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct cpuidle_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dev->poll_limit_ns = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static struct cpuidle_governor haltpoll_governor = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .name = "haltpoll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .rating = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .enable = haltpoll_enable_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .select = haltpoll_select,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .reflect = haltpoll_reflect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int __init init_haltpoll(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (kvm_para_available())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return cpuidle_register_governor(&haltpoll_governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) postcore_initcall(init_haltpoll);