0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/cpuidle.h>
0015 #include <linux/time.h>
0016 #include <linux/ktime.h>
0017 #include <linux/hrtimer.h>
0018 #include <linux/tick.h>
0019 #include <linux/sched.h>
0020 #include <linux/module.h>
0021 #include <linux/kvm_para.h>
0022 #include <trace/events/power.h>
0023
0024 static unsigned int guest_halt_poll_ns __read_mostly = 200000;
0025 module_param(guest_halt_poll_ns, uint, 0644);
0026
0027
0028 static unsigned int guest_halt_poll_shrink __read_mostly = 2;
0029 module_param(guest_halt_poll_shrink, uint, 0644);
0030
0031
0032 static unsigned int guest_halt_poll_grow __read_mostly = 2;
0033 module_param(guest_halt_poll_grow, uint, 0644);
0034
0035
0036 static unsigned int guest_halt_poll_grow_start __read_mostly = 50000;
0037 module_param(guest_halt_poll_grow_start, uint, 0644);
0038
0039
0040 static bool guest_halt_poll_allow_shrink __read_mostly = true;
0041 module_param(guest_halt_poll_allow_shrink, bool, 0644);
0042
0043
0044
0045
0046
0047
0048
0049 static int haltpoll_select(struct cpuidle_driver *drv,
0050 struct cpuidle_device *dev,
0051 bool *stop_tick)
0052 {
0053 s64 latency_req = cpuidle_governor_latency_req(dev->cpu);
0054
0055 if (!drv->state_count || latency_req == 0) {
0056 *stop_tick = false;
0057 return 0;
0058 }
0059
0060 if (dev->poll_limit_ns == 0)
0061 return 1;
0062
0063
0064 if (dev->last_state_idx == 0) {
0065
0066 if (dev->poll_time_limit == true)
0067 return 1;
0068
0069 *stop_tick = false;
0070
0071 return 0;
0072 }
0073
0074 *stop_tick = false;
0075
0076 return 0;
0077 }
0078
0079 static void adjust_poll_limit(struct cpuidle_device *dev, u64 block_ns)
0080 {
0081 unsigned int val;
0082
0083
0084
0085
0086 if (block_ns > dev->poll_limit_ns && block_ns <= guest_halt_poll_ns) {
0087 val = dev->poll_limit_ns * guest_halt_poll_grow;
0088
0089 if (val < guest_halt_poll_grow_start)
0090 val = guest_halt_poll_grow_start;
0091 if (val > guest_halt_poll_ns)
0092 val = guest_halt_poll_ns;
0093
0094 trace_guest_halt_poll_ns_grow(val, dev->poll_limit_ns);
0095 dev->poll_limit_ns = val;
0096 } else if (block_ns > guest_halt_poll_ns &&
0097 guest_halt_poll_allow_shrink) {
0098 unsigned int shrink = guest_halt_poll_shrink;
0099
0100 val = dev->poll_limit_ns;
0101 if (shrink == 0)
0102 val = 0;
0103 else
0104 val /= shrink;
0105 trace_guest_halt_poll_ns_shrink(val, dev->poll_limit_ns);
0106 dev->poll_limit_ns = val;
0107 }
0108 }
0109
0110
0111
0112
0113
0114
0115 static void haltpoll_reflect(struct cpuidle_device *dev, int index)
0116 {
0117 dev->last_state_idx = index;
0118
0119 if (index != 0)
0120 adjust_poll_limit(dev, dev->last_residency_ns);
0121 }
0122
0123
0124
0125
0126
0127
0128 static int haltpoll_enable_device(struct cpuidle_driver *drv,
0129 struct cpuidle_device *dev)
0130 {
0131 dev->poll_limit_ns = 0;
0132
0133 return 0;
0134 }
0135
0136 static struct cpuidle_governor haltpoll_governor = {
0137 .name = "haltpoll",
0138 .rating = 9,
0139 .enable = haltpoll_enable_device,
0140 .select = haltpoll_select,
0141 .reflect = haltpoll_reflect,
0142 };
0143
0144 static int __init init_haltpoll(void)
0145 {
0146 if (kvm_para_available())
0147 return cpuidle_register_governor(&haltpoll_governor);
0148
0149 return 0;
0150 }
0151
0152 postcore_initcall(init_haltpoll);