1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * intel_idle.c - native hardware idle loop for modern Intel processors
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2013 - 2020, Intel Corporation.
6*4882a593Smuzhiyun * Len Brown <len.brown@intel.com>
7*4882a593Smuzhiyun * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun /*
11*4882a593Smuzhiyun * intel_idle is a cpuidle driver that loads on all Intel CPUs with MWAIT
12*4882a593Smuzhiyun * in lieu of the legacy ACPI processor_idle driver. The intent is to
13*4882a593Smuzhiyun * make Linux more efficient on these processors, as intel_idle knows
14*4882a593Smuzhiyun * more than ACPI, as well as make Linux more immune to ACPI BIOS bugs.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun /*
18*4882a593Smuzhiyun * Design Assumptions
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun * All CPUs have same idle states as boot CPU
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * Chipset BM_STS (bus master status) bit is a NOP
23*4882a593Smuzhiyun * for preventing entry into deep C-states
24*4882a593Smuzhiyun *
25*4882a593Smuzhiyun * CPU will flush caches as needed when entering a C-state via MWAIT
26*4882a593Smuzhiyun * (in contrast to entering ACPI C3, in which case the WBINVD
27*4882a593Smuzhiyun * instruction needs to be executed to flush the caches)
28*4882a593Smuzhiyun */
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun /*
31*4882a593Smuzhiyun * Known limitations
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * ACPI has a .suspend hack to turn off deep c-statees during suspend
34*4882a593Smuzhiyun * to avoid complications with the lapic timer workaround.
35*4882a593Smuzhiyun * Have not seen issues with suspend, but may need same workaround here.
36*4882a593Smuzhiyun *
37*4882a593Smuzhiyun */
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /* un-comment DEBUG to enable pr_debug() statements */
40*4882a593Smuzhiyun #define DEBUG
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #include <linux/acpi.h>
45*4882a593Smuzhiyun #include <linux/kernel.h>
46*4882a593Smuzhiyun #include <linux/cpuidle.h>
47*4882a593Smuzhiyun #include <linux/tick.h>
48*4882a593Smuzhiyun #include <trace/events/power.h>
49*4882a593Smuzhiyun #include <linux/sched.h>
50*4882a593Smuzhiyun #include <linux/sched/smt.h>
51*4882a593Smuzhiyun #include <linux/notifier.h>
52*4882a593Smuzhiyun #include <linux/cpu.h>
53*4882a593Smuzhiyun #include <linux/moduleparam.h>
54*4882a593Smuzhiyun #include <asm/cpu_device_id.h>
55*4882a593Smuzhiyun #include <asm/intel-family.h>
56*4882a593Smuzhiyun #include <asm/nospec-branch.h>
57*4882a593Smuzhiyun #include <asm/mwait.h>
58*4882a593Smuzhiyun #include <asm/msr.h>
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun #define INTEL_IDLE_VERSION "0.5.1"
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun static struct cpuidle_driver intel_idle_driver = {
63*4882a593Smuzhiyun .name = "intel_idle",
64*4882a593Smuzhiyun .owner = THIS_MODULE,
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun /* intel_idle.max_cstate=0 disables driver */
67*4882a593Smuzhiyun static int max_cstate = CPUIDLE_STATE_MAX - 1;
68*4882a593Smuzhiyun static unsigned int disabled_states_mask;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun static unsigned long auto_demotion_disable_flags;
73*4882a593Smuzhiyun static bool disable_promotion_to_c1e;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun struct idle_cpu {
76*4882a593Smuzhiyun struct cpuidle_state *state_table;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /*
79*4882a593Smuzhiyun * Hardware C-state auto-demotion may not always be optimal.
80*4882a593Smuzhiyun * Indicate which enable bits to clear here.
81*4882a593Smuzhiyun */
82*4882a593Smuzhiyun unsigned long auto_demotion_disable_flags;
83*4882a593Smuzhiyun bool byt_auto_demotion_disable_flag;
84*4882a593Smuzhiyun bool disable_promotion_to_c1e;
85*4882a593Smuzhiyun bool use_acpi;
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun static const struct idle_cpu *icpu __initdata;
89*4882a593Smuzhiyun static struct cpuidle_state *cpuidle_state_table __initdata;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun static unsigned int mwait_substates __initdata;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun /*
94*4882a593Smuzhiyun * Enable this state by default even if the ACPI _CST does not list it.
95*4882a593Smuzhiyun */
96*4882a593Smuzhiyun #define CPUIDLE_FLAG_ALWAYS_ENABLE BIT(15)
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /*
99*4882a593Smuzhiyun * Disable IBRS across idle (when KERNEL_IBRS), is exclusive vs IRQ_ENABLE
100*4882a593Smuzhiyun * above.
101*4882a593Smuzhiyun */
102*4882a593Smuzhiyun #define CPUIDLE_FLAG_IBRS BIT(16)
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /*
105*4882a593Smuzhiyun * MWAIT takes an 8-bit "hint" in EAX "suggesting"
106*4882a593Smuzhiyun * the C-state (top nibble) and sub-state (bottom nibble)
107*4882a593Smuzhiyun * 0x00 means "MWAIT(C1)", 0x10 means "MWAIT(C2)" etc.
108*4882a593Smuzhiyun *
109*4882a593Smuzhiyun * We store the hint at the top of our "flags" for each state.
110*4882a593Smuzhiyun */
111*4882a593Smuzhiyun #define flg2MWAIT(flags) (((flags) >> 24) & 0xFF)
112*4882a593Smuzhiyun #define MWAIT2flg(eax) ((eax & 0xFF) << 24)
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /**
115*4882a593Smuzhiyun * intel_idle - Ask the processor to enter the given idle state.
116*4882a593Smuzhiyun * @dev: cpuidle device of the target CPU.
117*4882a593Smuzhiyun * @drv: cpuidle driver (assumed to point to intel_idle_driver).
118*4882a593Smuzhiyun * @index: Target idle state index.
119*4882a593Smuzhiyun *
120*4882a593Smuzhiyun * Use the MWAIT instruction to notify the processor that the CPU represented by
121*4882a593Smuzhiyun * @dev is idle and it can try to enter the idle state corresponding to @index.
122*4882a593Smuzhiyun *
123*4882a593Smuzhiyun * If the local APIC timer is not known to be reliable in the target idle state,
124*4882a593Smuzhiyun * enable one-shot tick broadcasting for the target CPU before executing MWAIT.
125*4882a593Smuzhiyun *
126*4882a593Smuzhiyun * Optionally call leave_mm() for the target CPU upfront to avoid wakeups due to
127*4882a593Smuzhiyun * flushing user TLBs.
128*4882a593Smuzhiyun *
129*4882a593Smuzhiyun * Must be called under local_irq_disable().
130*4882a593Smuzhiyun */
intel_idle(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)131*4882a593Smuzhiyun static __cpuidle int intel_idle(struct cpuidle_device *dev,
132*4882a593Smuzhiyun struct cpuidle_driver *drv, int index)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun struct cpuidle_state *state = &drv->states[index];
135*4882a593Smuzhiyun unsigned long eax = flg2MWAIT(state->flags);
136*4882a593Smuzhiyun unsigned long ecx = 1; /* break on interrupt flag */
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun mwait_idle_with_hints(eax, ecx);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun return index;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
intel_idle_ibrs(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)143*4882a593Smuzhiyun static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
144*4882a593Smuzhiyun struct cpuidle_driver *drv, int index)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun bool smt_active = sched_smt_active();
147*4882a593Smuzhiyun u64 spec_ctrl = spec_ctrl_current();
148*4882a593Smuzhiyun int ret;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun if (smt_active)
151*4882a593Smuzhiyun wrmsrl(MSR_IA32_SPEC_CTRL, 0);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun ret = intel_idle(dev, drv, index);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun if (smt_active)
156*4882a593Smuzhiyun wrmsrl(MSR_IA32_SPEC_CTRL, spec_ctrl);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun return ret;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /**
162*4882a593Smuzhiyun * intel_idle_s2idle - Ask the processor to enter the given idle state.
163*4882a593Smuzhiyun * @dev: cpuidle device of the target CPU.
164*4882a593Smuzhiyun * @drv: cpuidle driver (assumed to point to intel_idle_driver).
165*4882a593Smuzhiyun * @index: Target idle state index.
166*4882a593Smuzhiyun *
167*4882a593Smuzhiyun * Use the MWAIT instruction to notify the processor that the CPU represented by
168*4882a593Smuzhiyun * @dev is idle and it can try to enter the idle state corresponding to @index.
169*4882a593Smuzhiyun *
170*4882a593Smuzhiyun * Invoked as a suspend-to-idle callback routine with frozen user space, frozen
171*4882a593Smuzhiyun * scheduler tick and suspended scheduler clock on the target CPU.
172*4882a593Smuzhiyun */
intel_idle_s2idle(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)173*4882a593Smuzhiyun static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev,
174*4882a593Smuzhiyun struct cpuidle_driver *drv, int index)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun unsigned long eax = flg2MWAIT(drv->states[index].flags);
177*4882a593Smuzhiyun unsigned long ecx = 1; /* break on interrupt flag */
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun mwait_idle_with_hints(eax, ecx);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun return 0;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /*
185*4882a593Smuzhiyun * States are indexed by the cstate number,
186*4882a593Smuzhiyun * which is also the index into the MWAIT hint array.
187*4882a593Smuzhiyun * Thus C0 is a dummy.
188*4882a593Smuzhiyun */
189*4882a593Smuzhiyun static struct cpuidle_state nehalem_cstates[] __initdata = {
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun .name = "C1",
192*4882a593Smuzhiyun .desc = "MWAIT 0x00",
193*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
194*4882a593Smuzhiyun .exit_latency = 3,
195*4882a593Smuzhiyun .target_residency = 6,
196*4882a593Smuzhiyun .enter = &intel_idle,
197*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun .name = "C1E",
200*4882a593Smuzhiyun .desc = "MWAIT 0x01",
201*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
202*4882a593Smuzhiyun .exit_latency = 10,
203*4882a593Smuzhiyun .target_residency = 20,
204*4882a593Smuzhiyun .enter = &intel_idle,
205*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun .name = "C3",
208*4882a593Smuzhiyun .desc = "MWAIT 0x10",
209*4882a593Smuzhiyun .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
210*4882a593Smuzhiyun .exit_latency = 20,
211*4882a593Smuzhiyun .target_residency = 80,
212*4882a593Smuzhiyun .enter = &intel_idle,
213*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun .name = "C6",
216*4882a593Smuzhiyun .desc = "MWAIT 0x20",
217*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
218*4882a593Smuzhiyun .exit_latency = 200,
219*4882a593Smuzhiyun .target_residency = 800,
220*4882a593Smuzhiyun .enter = &intel_idle,
221*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun .enter = NULL }
224*4882a593Smuzhiyun };
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun static struct cpuidle_state snb_cstates[] __initdata = {
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun .name = "C1",
229*4882a593Smuzhiyun .desc = "MWAIT 0x00",
230*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
231*4882a593Smuzhiyun .exit_latency = 2,
232*4882a593Smuzhiyun .target_residency = 2,
233*4882a593Smuzhiyun .enter = &intel_idle,
234*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun .name = "C1E",
237*4882a593Smuzhiyun .desc = "MWAIT 0x01",
238*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
239*4882a593Smuzhiyun .exit_latency = 10,
240*4882a593Smuzhiyun .target_residency = 20,
241*4882a593Smuzhiyun .enter = &intel_idle,
242*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun .name = "C3",
245*4882a593Smuzhiyun .desc = "MWAIT 0x10",
246*4882a593Smuzhiyun .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
247*4882a593Smuzhiyun .exit_latency = 80,
248*4882a593Smuzhiyun .target_residency = 211,
249*4882a593Smuzhiyun .enter = &intel_idle,
250*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun .name = "C6",
253*4882a593Smuzhiyun .desc = "MWAIT 0x20",
254*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
255*4882a593Smuzhiyun .exit_latency = 104,
256*4882a593Smuzhiyun .target_residency = 345,
257*4882a593Smuzhiyun .enter = &intel_idle,
258*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun .name = "C7",
261*4882a593Smuzhiyun .desc = "MWAIT 0x30",
262*4882a593Smuzhiyun .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
263*4882a593Smuzhiyun .exit_latency = 109,
264*4882a593Smuzhiyun .target_residency = 345,
265*4882a593Smuzhiyun .enter = &intel_idle,
266*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun .enter = NULL }
269*4882a593Smuzhiyun };
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun static struct cpuidle_state byt_cstates[] __initdata = {
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun .name = "C1",
274*4882a593Smuzhiyun .desc = "MWAIT 0x00",
275*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
276*4882a593Smuzhiyun .exit_latency = 1,
277*4882a593Smuzhiyun .target_residency = 1,
278*4882a593Smuzhiyun .enter = &intel_idle,
279*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun .name = "C6N",
282*4882a593Smuzhiyun .desc = "MWAIT 0x58",
283*4882a593Smuzhiyun .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
284*4882a593Smuzhiyun .exit_latency = 300,
285*4882a593Smuzhiyun .target_residency = 275,
286*4882a593Smuzhiyun .enter = &intel_idle,
287*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun .name = "C6S",
290*4882a593Smuzhiyun .desc = "MWAIT 0x52",
291*4882a593Smuzhiyun .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
292*4882a593Smuzhiyun .exit_latency = 500,
293*4882a593Smuzhiyun .target_residency = 560,
294*4882a593Smuzhiyun .enter = &intel_idle,
295*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun .name = "C7",
298*4882a593Smuzhiyun .desc = "MWAIT 0x60",
299*4882a593Smuzhiyun .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
300*4882a593Smuzhiyun .exit_latency = 1200,
301*4882a593Smuzhiyun .target_residency = 4000,
302*4882a593Smuzhiyun .enter = &intel_idle,
303*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun .name = "C7S",
306*4882a593Smuzhiyun .desc = "MWAIT 0x64",
307*4882a593Smuzhiyun .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
308*4882a593Smuzhiyun .exit_latency = 10000,
309*4882a593Smuzhiyun .target_residency = 20000,
310*4882a593Smuzhiyun .enter = &intel_idle,
311*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun .enter = NULL }
314*4882a593Smuzhiyun };
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun static struct cpuidle_state cht_cstates[] __initdata = {
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun .name = "C1",
319*4882a593Smuzhiyun .desc = "MWAIT 0x00",
320*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
321*4882a593Smuzhiyun .exit_latency = 1,
322*4882a593Smuzhiyun .target_residency = 1,
323*4882a593Smuzhiyun .enter = &intel_idle,
324*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun .name = "C6N",
327*4882a593Smuzhiyun .desc = "MWAIT 0x58",
328*4882a593Smuzhiyun .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
329*4882a593Smuzhiyun .exit_latency = 80,
330*4882a593Smuzhiyun .target_residency = 275,
331*4882a593Smuzhiyun .enter = &intel_idle,
332*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun .name = "C6S",
335*4882a593Smuzhiyun .desc = "MWAIT 0x52",
336*4882a593Smuzhiyun .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
337*4882a593Smuzhiyun .exit_latency = 200,
338*4882a593Smuzhiyun .target_residency = 560,
339*4882a593Smuzhiyun .enter = &intel_idle,
340*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun .name = "C7",
343*4882a593Smuzhiyun .desc = "MWAIT 0x60",
344*4882a593Smuzhiyun .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
345*4882a593Smuzhiyun .exit_latency = 1200,
346*4882a593Smuzhiyun .target_residency = 4000,
347*4882a593Smuzhiyun .enter = &intel_idle,
348*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun .name = "C7S",
351*4882a593Smuzhiyun .desc = "MWAIT 0x64",
352*4882a593Smuzhiyun .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
353*4882a593Smuzhiyun .exit_latency = 10000,
354*4882a593Smuzhiyun .target_residency = 20000,
355*4882a593Smuzhiyun .enter = &intel_idle,
356*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun .enter = NULL }
359*4882a593Smuzhiyun };
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun static struct cpuidle_state ivb_cstates[] __initdata = {
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun .name = "C1",
364*4882a593Smuzhiyun .desc = "MWAIT 0x00",
365*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
366*4882a593Smuzhiyun .exit_latency = 1,
367*4882a593Smuzhiyun .target_residency = 1,
368*4882a593Smuzhiyun .enter = &intel_idle,
369*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun .name = "C1E",
372*4882a593Smuzhiyun .desc = "MWAIT 0x01",
373*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
374*4882a593Smuzhiyun .exit_latency = 10,
375*4882a593Smuzhiyun .target_residency = 20,
376*4882a593Smuzhiyun .enter = &intel_idle,
377*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun .name = "C3",
380*4882a593Smuzhiyun .desc = "MWAIT 0x10",
381*4882a593Smuzhiyun .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
382*4882a593Smuzhiyun .exit_latency = 59,
383*4882a593Smuzhiyun .target_residency = 156,
384*4882a593Smuzhiyun .enter = &intel_idle,
385*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun .name = "C6",
388*4882a593Smuzhiyun .desc = "MWAIT 0x20",
389*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
390*4882a593Smuzhiyun .exit_latency = 80,
391*4882a593Smuzhiyun .target_residency = 300,
392*4882a593Smuzhiyun .enter = &intel_idle,
393*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun .name = "C7",
396*4882a593Smuzhiyun .desc = "MWAIT 0x30",
397*4882a593Smuzhiyun .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
398*4882a593Smuzhiyun .exit_latency = 87,
399*4882a593Smuzhiyun .target_residency = 300,
400*4882a593Smuzhiyun .enter = &intel_idle,
401*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun .enter = NULL }
404*4882a593Smuzhiyun };
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun static struct cpuidle_state ivt_cstates[] __initdata = {
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun .name = "C1",
409*4882a593Smuzhiyun .desc = "MWAIT 0x00",
410*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
411*4882a593Smuzhiyun .exit_latency = 1,
412*4882a593Smuzhiyun .target_residency = 1,
413*4882a593Smuzhiyun .enter = &intel_idle,
414*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun .name = "C1E",
417*4882a593Smuzhiyun .desc = "MWAIT 0x01",
418*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
419*4882a593Smuzhiyun .exit_latency = 10,
420*4882a593Smuzhiyun .target_residency = 80,
421*4882a593Smuzhiyun .enter = &intel_idle,
422*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun .name = "C3",
425*4882a593Smuzhiyun .desc = "MWAIT 0x10",
426*4882a593Smuzhiyun .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
427*4882a593Smuzhiyun .exit_latency = 59,
428*4882a593Smuzhiyun .target_residency = 156,
429*4882a593Smuzhiyun .enter = &intel_idle,
430*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun .name = "C6",
433*4882a593Smuzhiyun .desc = "MWAIT 0x20",
434*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
435*4882a593Smuzhiyun .exit_latency = 82,
436*4882a593Smuzhiyun .target_residency = 300,
437*4882a593Smuzhiyun .enter = &intel_idle,
438*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun .enter = NULL }
441*4882a593Smuzhiyun };
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun static struct cpuidle_state ivt_cstates_4s[] __initdata = {
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun .name = "C1",
446*4882a593Smuzhiyun .desc = "MWAIT 0x00",
447*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
448*4882a593Smuzhiyun .exit_latency = 1,
449*4882a593Smuzhiyun .target_residency = 1,
450*4882a593Smuzhiyun .enter = &intel_idle,
451*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun .name = "C1E",
454*4882a593Smuzhiyun .desc = "MWAIT 0x01",
455*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
456*4882a593Smuzhiyun .exit_latency = 10,
457*4882a593Smuzhiyun .target_residency = 250,
458*4882a593Smuzhiyun .enter = &intel_idle,
459*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun .name = "C3",
462*4882a593Smuzhiyun .desc = "MWAIT 0x10",
463*4882a593Smuzhiyun .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
464*4882a593Smuzhiyun .exit_latency = 59,
465*4882a593Smuzhiyun .target_residency = 300,
466*4882a593Smuzhiyun .enter = &intel_idle,
467*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun .name = "C6",
470*4882a593Smuzhiyun .desc = "MWAIT 0x20",
471*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
472*4882a593Smuzhiyun .exit_latency = 84,
473*4882a593Smuzhiyun .target_residency = 400,
474*4882a593Smuzhiyun .enter = &intel_idle,
475*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun .enter = NULL }
478*4882a593Smuzhiyun };
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun static struct cpuidle_state ivt_cstates_8s[] __initdata = {
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun .name = "C1",
483*4882a593Smuzhiyun .desc = "MWAIT 0x00",
484*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
485*4882a593Smuzhiyun .exit_latency = 1,
486*4882a593Smuzhiyun .target_residency = 1,
487*4882a593Smuzhiyun .enter = &intel_idle,
488*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun .name = "C1E",
491*4882a593Smuzhiyun .desc = "MWAIT 0x01",
492*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
493*4882a593Smuzhiyun .exit_latency = 10,
494*4882a593Smuzhiyun .target_residency = 500,
495*4882a593Smuzhiyun .enter = &intel_idle,
496*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun .name = "C3",
499*4882a593Smuzhiyun .desc = "MWAIT 0x10",
500*4882a593Smuzhiyun .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
501*4882a593Smuzhiyun .exit_latency = 59,
502*4882a593Smuzhiyun .target_residency = 600,
503*4882a593Smuzhiyun .enter = &intel_idle,
504*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun .name = "C6",
507*4882a593Smuzhiyun .desc = "MWAIT 0x20",
508*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
509*4882a593Smuzhiyun .exit_latency = 88,
510*4882a593Smuzhiyun .target_residency = 700,
511*4882a593Smuzhiyun .enter = &intel_idle,
512*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun .enter = NULL }
515*4882a593Smuzhiyun };
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun static struct cpuidle_state hsw_cstates[] __initdata = {
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun .name = "C1",
520*4882a593Smuzhiyun .desc = "MWAIT 0x00",
521*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
522*4882a593Smuzhiyun .exit_latency = 2,
523*4882a593Smuzhiyun .target_residency = 2,
524*4882a593Smuzhiyun .enter = &intel_idle,
525*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun .name = "C1E",
528*4882a593Smuzhiyun .desc = "MWAIT 0x01",
529*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
530*4882a593Smuzhiyun .exit_latency = 10,
531*4882a593Smuzhiyun .target_residency = 20,
532*4882a593Smuzhiyun .enter = &intel_idle,
533*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun .name = "C3",
536*4882a593Smuzhiyun .desc = "MWAIT 0x10",
537*4882a593Smuzhiyun .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
538*4882a593Smuzhiyun .exit_latency = 33,
539*4882a593Smuzhiyun .target_residency = 100,
540*4882a593Smuzhiyun .enter = &intel_idle,
541*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun .name = "C6",
544*4882a593Smuzhiyun .desc = "MWAIT 0x20",
545*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
546*4882a593Smuzhiyun .exit_latency = 133,
547*4882a593Smuzhiyun .target_residency = 400,
548*4882a593Smuzhiyun .enter = &intel_idle,
549*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun .name = "C7s",
552*4882a593Smuzhiyun .desc = "MWAIT 0x32",
553*4882a593Smuzhiyun .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
554*4882a593Smuzhiyun .exit_latency = 166,
555*4882a593Smuzhiyun .target_residency = 500,
556*4882a593Smuzhiyun .enter = &intel_idle,
557*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun .name = "C8",
560*4882a593Smuzhiyun .desc = "MWAIT 0x40",
561*4882a593Smuzhiyun .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
562*4882a593Smuzhiyun .exit_latency = 300,
563*4882a593Smuzhiyun .target_residency = 900,
564*4882a593Smuzhiyun .enter = &intel_idle,
565*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun .name = "C9",
568*4882a593Smuzhiyun .desc = "MWAIT 0x50",
569*4882a593Smuzhiyun .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
570*4882a593Smuzhiyun .exit_latency = 600,
571*4882a593Smuzhiyun .target_residency = 1800,
572*4882a593Smuzhiyun .enter = &intel_idle,
573*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun .name = "C10",
576*4882a593Smuzhiyun .desc = "MWAIT 0x60",
577*4882a593Smuzhiyun .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
578*4882a593Smuzhiyun .exit_latency = 2600,
579*4882a593Smuzhiyun .target_residency = 7700,
580*4882a593Smuzhiyun .enter = &intel_idle,
581*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
582*4882a593Smuzhiyun {
583*4882a593Smuzhiyun .enter = NULL }
584*4882a593Smuzhiyun };
585*4882a593Smuzhiyun static struct cpuidle_state bdw_cstates[] __initdata = {
586*4882a593Smuzhiyun {
587*4882a593Smuzhiyun .name = "C1",
588*4882a593Smuzhiyun .desc = "MWAIT 0x00",
589*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
590*4882a593Smuzhiyun .exit_latency = 2,
591*4882a593Smuzhiyun .target_residency = 2,
592*4882a593Smuzhiyun .enter = &intel_idle,
593*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun .name = "C1E",
596*4882a593Smuzhiyun .desc = "MWAIT 0x01",
597*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
598*4882a593Smuzhiyun .exit_latency = 10,
599*4882a593Smuzhiyun .target_residency = 20,
600*4882a593Smuzhiyun .enter = &intel_idle,
601*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun .name = "C3",
604*4882a593Smuzhiyun .desc = "MWAIT 0x10",
605*4882a593Smuzhiyun .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
606*4882a593Smuzhiyun .exit_latency = 40,
607*4882a593Smuzhiyun .target_residency = 100,
608*4882a593Smuzhiyun .enter = &intel_idle,
609*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
610*4882a593Smuzhiyun {
611*4882a593Smuzhiyun .name = "C6",
612*4882a593Smuzhiyun .desc = "MWAIT 0x20",
613*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
614*4882a593Smuzhiyun .exit_latency = 133,
615*4882a593Smuzhiyun .target_residency = 400,
616*4882a593Smuzhiyun .enter = &intel_idle,
617*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun .name = "C7s",
620*4882a593Smuzhiyun .desc = "MWAIT 0x32",
621*4882a593Smuzhiyun .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
622*4882a593Smuzhiyun .exit_latency = 166,
623*4882a593Smuzhiyun .target_residency = 500,
624*4882a593Smuzhiyun .enter = &intel_idle,
625*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun .name = "C8",
628*4882a593Smuzhiyun .desc = "MWAIT 0x40",
629*4882a593Smuzhiyun .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
630*4882a593Smuzhiyun .exit_latency = 300,
631*4882a593Smuzhiyun .target_residency = 900,
632*4882a593Smuzhiyun .enter = &intel_idle,
633*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun .name = "C9",
636*4882a593Smuzhiyun .desc = "MWAIT 0x50",
637*4882a593Smuzhiyun .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
638*4882a593Smuzhiyun .exit_latency = 600,
639*4882a593Smuzhiyun .target_residency = 1800,
640*4882a593Smuzhiyun .enter = &intel_idle,
641*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
642*4882a593Smuzhiyun {
643*4882a593Smuzhiyun .name = "C10",
644*4882a593Smuzhiyun .desc = "MWAIT 0x60",
645*4882a593Smuzhiyun .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
646*4882a593Smuzhiyun .exit_latency = 2600,
647*4882a593Smuzhiyun .target_residency = 7700,
648*4882a593Smuzhiyun .enter = &intel_idle,
649*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
650*4882a593Smuzhiyun {
651*4882a593Smuzhiyun .enter = NULL }
652*4882a593Smuzhiyun };
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun static struct cpuidle_state skl_cstates[] __initdata = {
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun .name = "C1",
657*4882a593Smuzhiyun .desc = "MWAIT 0x00",
658*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
659*4882a593Smuzhiyun .exit_latency = 2,
660*4882a593Smuzhiyun .target_residency = 2,
661*4882a593Smuzhiyun .enter = &intel_idle,
662*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun .name = "C1E",
665*4882a593Smuzhiyun .desc = "MWAIT 0x01",
666*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
667*4882a593Smuzhiyun .exit_latency = 10,
668*4882a593Smuzhiyun .target_residency = 20,
669*4882a593Smuzhiyun .enter = &intel_idle,
670*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
671*4882a593Smuzhiyun {
672*4882a593Smuzhiyun .name = "C3",
673*4882a593Smuzhiyun .desc = "MWAIT 0x10",
674*4882a593Smuzhiyun .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
675*4882a593Smuzhiyun .exit_latency = 70,
676*4882a593Smuzhiyun .target_residency = 100,
677*4882a593Smuzhiyun .enter = &intel_idle,
678*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun .name = "C6",
681*4882a593Smuzhiyun .desc = "MWAIT 0x20",
682*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
683*4882a593Smuzhiyun .exit_latency = 85,
684*4882a593Smuzhiyun .target_residency = 200,
685*4882a593Smuzhiyun .enter = &intel_idle,
686*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun .name = "C7s",
689*4882a593Smuzhiyun .desc = "MWAIT 0x33",
690*4882a593Smuzhiyun .flags = MWAIT2flg(0x33) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
691*4882a593Smuzhiyun .exit_latency = 124,
692*4882a593Smuzhiyun .target_residency = 800,
693*4882a593Smuzhiyun .enter = &intel_idle,
694*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
695*4882a593Smuzhiyun {
696*4882a593Smuzhiyun .name = "C8",
697*4882a593Smuzhiyun .desc = "MWAIT 0x40",
698*4882a593Smuzhiyun .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
699*4882a593Smuzhiyun .exit_latency = 200,
700*4882a593Smuzhiyun .target_residency = 800,
701*4882a593Smuzhiyun .enter = &intel_idle,
702*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
703*4882a593Smuzhiyun {
704*4882a593Smuzhiyun .name = "C9",
705*4882a593Smuzhiyun .desc = "MWAIT 0x50",
706*4882a593Smuzhiyun .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
707*4882a593Smuzhiyun .exit_latency = 480,
708*4882a593Smuzhiyun .target_residency = 5000,
709*4882a593Smuzhiyun .enter = &intel_idle,
710*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
711*4882a593Smuzhiyun {
712*4882a593Smuzhiyun .name = "C10",
713*4882a593Smuzhiyun .desc = "MWAIT 0x60",
714*4882a593Smuzhiyun .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
715*4882a593Smuzhiyun .exit_latency = 890,
716*4882a593Smuzhiyun .target_residency = 5000,
717*4882a593Smuzhiyun .enter = &intel_idle,
718*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun .enter = NULL }
721*4882a593Smuzhiyun };
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun static struct cpuidle_state skx_cstates[] __initdata = {
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun .name = "C1",
726*4882a593Smuzhiyun .desc = "MWAIT 0x00",
727*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
728*4882a593Smuzhiyun .exit_latency = 2,
729*4882a593Smuzhiyun .target_residency = 2,
730*4882a593Smuzhiyun .enter = &intel_idle,
731*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun .name = "C1E",
734*4882a593Smuzhiyun .desc = "MWAIT 0x01",
735*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
736*4882a593Smuzhiyun .exit_latency = 10,
737*4882a593Smuzhiyun .target_residency = 20,
738*4882a593Smuzhiyun .enter = &intel_idle,
739*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
740*4882a593Smuzhiyun {
741*4882a593Smuzhiyun .name = "C6",
742*4882a593Smuzhiyun .desc = "MWAIT 0x20",
743*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
744*4882a593Smuzhiyun .exit_latency = 133,
745*4882a593Smuzhiyun .target_residency = 600,
746*4882a593Smuzhiyun .enter = &intel_idle,
747*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
748*4882a593Smuzhiyun {
749*4882a593Smuzhiyun .enter = NULL }
750*4882a593Smuzhiyun };
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun static struct cpuidle_state icx_cstates[] __initdata = {
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun .name = "C1",
755*4882a593Smuzhiyun .desc = "MWAIT 0x00",
756*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
757*4882a593Smuzhiyun .exit_latency = 1,
758*4882a593Smuzhiyun .target_residency = 1,
759*4882a593Smuzhiyun .enter = &intel_idle,
760*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
761*4882a593Smuzhiyun {
762*4882a593Smuzhiyun .name = "C1E",
763*4882a593Smuzhiyun .desc = "MWAIT 0x01",
764*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
765*4882a593Smuzhiyun .exit_latency = 4,
766*4882a593Smuzhiyun .target_residency = 4,
767*4882a593Smuzhiyun .enter = &intel_idle,
768*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun .name = "C6",
771*4882a593Smuzhiyun .desc = "MWAIT 0x20",
772*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
773*4882a593Smuzhiyun .exit_latency = 128,
774*4882a593Smuzhiyun .target_residency = 384,
775*4882a593Smuzhiyun .enter = &intel_idle,
776*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
777*4882a593Smuzhiyun {
778*4882a593Smuzhiyun .enter = NULL }
779*4882a593Smuzhiyun };
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun static struct cpuidle_state atom_cstates[] __initdata = {
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun .name = "C1E",
784*4882a593Smuzhiyun .desc = "MWAIT 0x00",
785*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
786*4882a593Smuzhiyun .exit_latency = 10,
787*4882a593Smuzhiyun .target_residency = 20,
788*4882a593Smuzhiyun .enter = &intel_idle,
789*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
790*4882a593Smuzhiyun {
791*4882a593Smuzhiyun .name = "C2",
792*4882a593Smuzhiyun .desc = "MWAIT 0x10",
793*4882a593Smuzhiyun .flags = MWAIT2flg(0x10),
794*4882a593Smuzhiyun .exit_latency = 20,
795*4882a593Smuzhiyun .target_residency = 80,
796*4882a593Smuzhiyun .enter = &intel_idle,
797*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
798*4882a593Smuzhiyun {
799*4882a593Smuzhiyun .name = "C4",
800*4882a593Smuzhiyun .desc = "MWAIT 0x30",
801*4882a593Smuzhiyun .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
802*4882a593Smuzhiyun .exit_latency = 100,
803*4882a593Smuzhiyun .target_residency = 400,
804*4882a593Smuzhiyun .enter = &intel_idle,
805*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
806*4882a593Smuzhiyun {
807*4882a593Smuzhiyun .name = "C6",
808*4882a593Smuzhiyun .desc = "MWAIT 0x52",
809*4882a593Smuzhiyun .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
810*4882a593Smuzhiyun .exit_latency = 140,
811*4882a593Smuzhiyun .target_residency = 560,
812*4882a593Smuzhiyun .enter = &intel_idle,
813*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
814*4882a593Smuzhiyun {
815*4882a593Smuzhiyun .enter = NULL }
816*4882a593Smuzhiyun };
817*4882a593Smuzhiyun static struct cpuidle_state tangier_cstates[] __initdata = {
818*4882a593Smuzhiyun {
819*4882a593Smuzhiyun .name = "C1",
820*4882a593Smuzhiyun .desc = "MWAIT 0x00",
821*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
822*4882a593Smuzhiyun .exit_latency = 1,
823*4882a593Smuzhiyun .target_residency = 4,
824*4882a593Smuzhiyun .enter = &intel_idle,
825*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
826*4882a593Smuzhiyun {
827*4882a593Smuzhiyun .name = "C4",
828*4882a593Smuzhiyun .desc = "MWAIT 0x30",
829*4882a593Smuzhiyun .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
830*4882a593Smuzhiyun .exit_latency = 100,
831*4882a593Smuzhiyun .target_residency = 400,
832*4882a593Smuzhiyun .enter = &intel_idle,
833*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
834*4882a593Smuzhiyun {
835*4882a593Smuzhiyun .name = "C6",
836*4882a593Smuzhiyun .desc = "MWAIT 0x52",
837*4882a593Smuzhiyun .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
838*4882a593Smuzhiyun .exit_latency = 140,
839*4882a593Smuzhiyun .target_residency = 560,
840*4882a593Smuzhiyun .enter = &intel_idle,
841*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
842*4882a593Smuzhiyun {
843*4882a593Smuzhiyun .name = "C7",
844*4882a593Smuzhiyun .desc = "MWAIT 0x60",
845*4882a593Smuzhiyun .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
846*4882a593Smuzhiyun .exit_latency = 1200,
847*4882a593Smuzhiyun .target_residency = 4000,
848*4882a593Smuzhiyun .enter = &intel_idle,
849*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
850*4882a593Smuzhiyun {
851*4882a593Smuzhiyun .name = "C9",
852*4882a593Smuzhiyun .desc = "MWAIT 0x64",
853*4882a593Smuzhiyun .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
854*4882a593Smuzhiyun .exit_latency = 10000,
855*4882a593Smuzhiyun .target_residency = 20000,
856*4882a593Smuzhiyun .enter = &intel_idle,
857*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
858*4882a593Smuzhiyun {
859*4882a593Smuzhiyun .enter = NULL }
860*4882a593Smuzhiyun };
861*4882a593Smuzhiyun static struct cpuidle_state avn_cstates[] __initdata = {
862*4882a593Smuzhiyun {
863*4882a593Smuzhiyun .name = "C1",
864*4882a593Smuzhiyun .desc = "MWAIT 0x00",
865*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
866*4882a593Smuzhiyun .exit_latency = 2,
867*4882a593Smuzhiyun .target_residency = 2,
868*4882a593Smuzhiyun .enter = &intel_idle,
869*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
870*4882a593Smuzhiyun {
871*4882a593Smuzhiyun .name = "C6",
872*4882a593Smuzhiyun .desc = "MWAIT 0x51",
873*4882a593Smuzhiyun .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED,
874*4882a593Smuzhiyun .exit_latency = 15,
875*4882a593Smuzhiyun .target_residency = 45,
876*4882a593Smuzhiyun .enter = &intel_idle,
877*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
878*4882a593Smuzhiyun {
879*4882a593Smuzhiyun .enter = NULL }
880*4882a593Smuzhiyun };
881*4882a593Smuzhiyun static struct cpuidle_state knl_cstates[] __initdata = {
882*4882a593Smuzhiyun {
883*4882a593Smuzhiyun .name = "C1",
884*4882a593Smuzhiyun .desc = "MWAIT 0x00",
885*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
886*4882a593Smuzhiyun .exit_latency = 1,
887*4882a593Smuzhiyun .target_residency = 2,
888*4882a593Smuzhiyun .enter = &intel_idle,
889*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle },
890*4882a593Smuzhiyun {
891*4882a593Smuzhiyun .name = "C6",
892*4882a593Smuzhiyun .desc = "MWAIT 0x10",
893*4882a593Smuzhiyun .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
894*4882a593Smuzhiyun .exit_latency = 120,
895*4882a593Smuzhiyun .target_residency = 500,
896*4882a593Smuzhiyun .enter = &intel_idle,
897*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle },
898*4882a593Smuzhiyun {
899*4882a593Smuzhiyun .enter = NULL }
900*4882a593Smuzhiyun };
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun static struct cpuidle_state bxt_cstates[] __initdata = {
903*4882a593Smuzhiyun {
904*4882a593Smuzhiyun .name = "C1",
905*4882a593Smuzhiyun .desc = "MWAIT 0x00",
906*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
907*4882a593Smuzhiyun .exit_latency = 2,
908*4882a593Smuzhiyun .target_residency = 2,
909*4882a593Smuzhiyun .enter = &intel_idle,
910*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
911*4882a593Smuzhiyun {
912*4882a593Smuzhiyun .name = "C1E",
913*4882a593Smuzhiyun .desc = "MWAIT 0x01",
914*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
915*4882a593Smuzhiyun .exit_latency = 10,
916*4882a593Smuzhiyun .target_residency = 20,
917*4882a593Smuzhiyun .enter = &intel_idle,
918*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
919*4882a593Smuzhiyun {
920*4882a593Smuzhiyun .name = "C6",
921*4882a593Smuzhiyun .desc = "MWAIT 0x20",
922*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
923*4882a593Smuzhiyun .exit_latency = 133,
924*4882a593Smuzhiyun .target_residency = 133,
925*4882a593Smuzhiyun .enter = &intel_idle,
926*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
927*4882a593Smuzhiyun {
928*4882a593Smuzhiyun .name = "C7s",
929*4882a593Smuzhiyun .desc = "MWAIT 0x31",
930*4882a593Smuzhiyun .flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
931*4882a593Smuzhiyun .exit_latency = 155,
932*4882a593Smuzhiyun .target_residency = 155,
933*4882a593Smuzhiyun .enter = &intel_idle,
934*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
935*4882a593Smuzhiyun {
936*4882a593Smuzhiyun .name = "C8",
937*4882a593Smuzhiyun .desc = "MWAIT 0x40",
938*4882a593Smuzhiyun .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
939*4882a593Smuzhiyun .exit_latency = 1000,
940*4882a593Smuzhiyun .target_residency = 1000,
941*4882a593Smuzhiyun .enter = &intel_idle,
942*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
943*4882a593Smuzhiyun {
944*4882a593Smuzhiyun .name = "C9",
945*4882a593Smuzhiyun .desc = "MWAIT 0x50",
946*4882a593Smuzhiyun .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
947*4882a593Smuzhiyun .exit_latency = 2000,
948*4882a593Smuzhiyun .target_residency = 2000,
949*4882a593Smuzhiyun .enter = &intel_idle,
950*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
951*4882a593Smuzhiyun {
952*4882a593Smuzhiyun .name = "C10",
953*4882a593Smuzhiyun .desc = "MWAIT 0x60",
954*4882a593Smuzhiyun .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
955*4882a593Smuzhiyun .exit_latency = 10000,
956*4882a593Smuzhiyun .target_residency = 10000,
957*4882a593Smuzhiyun .enter = &intel_idle,
958*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
959*4882a593Smuzhiyun {
960*4882a593Smuzhiyun .enter = NULL }
961*4882a593Smuzhiyun };
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun static struct cpuidle_state dnv_cstates[] __initdata = {
964*4882a593Smuzhiyun {
965*4882a593Smuzhiyun .name = "C1",
966*4882a593Smuzhiyun .desc = "MWAIT 0x00",
967*4882a593Smuzhiyun .flags = MWAIT2flg(0x00),
968*4882a593Smuzhiyun .exit_latency = 2,
969*4882a593Smuzhiyun .target_residency = 2,
970*4882a593Smuzhiyun .enter = &intel_idle,
971*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
972*4882a593Smuzhiyun {
973*4882a593Smuzhiyun .name = "C1E",
974*4882a593Smuzhiyun .desc = "MWAIT 0x01",
975*4882a593Smuzhiyun .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
976*4882a593Smuzhiyun .exit_latency = 10,
977*4882a593Smuzhiyun .target_residency = 20,
978*4882a593Smuzhiyun .enter = &intel_idle,
979*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
980*4882a593Smuzhiyun {
981*4882a593Smuzhiyun .name = "C6",
982*4882a593Smuzhiyun .desc = "MWAIT 0x20",
983*4882a593Smuzhiyun .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
984*4882a593Smuzhiyun .exit_latency = 50,
985*4882a593Smuzhiyun .target_residency = 500,
986*4882a593Smuzhiyun .enter = &intel_idle,
987*4882a593Smuzhiyun .enter_s2idle = intel_idle_s2idle, },
988*4882a593Smuzhiyun {
989*4882a593Smuzhiyun .enter = NULL }
990*4882a593Smuzhiyun };
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_nehalem __initconst = {
993*4882a593Smuzhiyun .state_table = nehalem_cstates,
994*4882a593Smuzhiyun .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
995*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
996*4882a593Smuzhiyun };
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_nhx __initconst = {
999*4882a593Smuzhiyun .state_table = nehalem_cstates,
1000*4882a593Smuzhiyun .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
1001*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1002*4882a593Smuzhiyun .use_acpi = true,
1003*4882a593Smuzhiyun };
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_atom __initconst = {
1006*4882a593Smuzhiyun .state_table = atom_cstates,
1007*4882a593Smuzhiyun };
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_tangier __initconst = {
1010*4882a593Smuzhiyun .state_table = tangier_cstates,
1011*4882a593Smuzhiyun };
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_lincroft __initconst = {
1014*4882a593Smuzhiyun .state_table = atom_cstates,
1015*4882a593Smuzhiyun .auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
1016*4882a593Smuzhiyun };
1017*4882a593Smuzhiyun
1018*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_snb __initconst = {
1019*4882a593Smuzhiyun .state_table = snb_cstates,
1020*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1021*4882a593Smuzhiyun };
1022*4882a593Smuzhiyun
1023*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_snx __initconst = {
1024*4882a593Smuzhiyun .state_table = snb_cstates,
1025*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1026*4882a593Smuzhiyun .use_acpi = true,
1027*4882a593Smuzhiyun };
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_byt __initconst = {
1030*4882a593Smuzhiyun .state_table = byt_cstates,
1031*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1032*4882a593Smuzhiyun .byt_auto_demotion_disable_flag = true,
1033*4882a593Smuzhiyun };
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_cht __initconst = {
1036*4882a593Smuzhiyun .state_table = cht_cstates,
1037*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1038*4882a593Smuzhiyun .byt_auto_demotion_disable_flag = true,
1039*4882a593Smuzhiyun };
1040*4882a593Smuzhiyun
1041*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_ivb __initconst = {
1042*4882a593Smuzhiyun .state_table = ivb_cstates,
1043*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1044*4882a593Smuzhiyun };
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_ivt __initconst = {
1047*4882a593Smuzhiyun .state_table = ivt_cstates,
1048*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1049*4882a593Smuzhiyun .use_acpi = true,
1050*4882a593Smuzhiyun };
1051*4882a593Smuzhiyun
1052*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_hsw __initconst = {
1053*4882a593Smuzhiyun .state_table = hsw_cstates,
1054*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1055*4882a593Smuzhiyun };
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_hsx __initconst = {
1058*4882a593Smuzhiyun .state_table = hsw_cstates,
1059*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1060*4882a593Smuzhiyun .use_acpi = true,
1061*4882a593Smuzhiyun };
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_bdw __initconst = {
1064*4882a593Smuzhiyun .state_table = bdw_cstates,
1065*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1066*4882a593Smuzhiyun };
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_bdx __initconst = {
1069*4882a593Smuzhiyun .state_table = bdw_cstates,
1070*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1071*4882a593Smuzhiyun .use_acpi = true,
1072*4882a593Smuzhiyun };
1073*4882a593Smuzhiyun
1074*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_skl __initconst = {
1075*4882a593Smuzhiyun .state_table = skl_cstates,
1076*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1077*4882a593Smuzhiyun };
1078*4882a593Smuzhiyun
1079*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_skx __initconst = {
1080*4882a593Smuzhiyun .state_table = skx_cstates,
1081*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1082*4882a593Smuzhiyun .use_acpi = true,
1083*4882a593Smuzhiyun };
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_icx __initconst = {
1086*4882a593Smuzhiyun .state_table = icx_cstates,
1087*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1088*4882a593Smuzhiyun .use_acpi = true,
1089*4882a593Smuzhiyun };
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_avn __initconst = {
1092*4882a593Smuzhiyun .state_table = avn_cstates,
1093*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1094*4882a593Smuzhiyun .use_acpi = true,
1095*4882a593Smuzhiyun };
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_knl __initconst = {
1098*4882a593Smuzhiyun .state_table = knl_cstates,
1099*4882a593Smuzhiyun .use_acpi = true,
1100*4882a593Smuzhiyun };
1101*4882a593Smuzhiyun
1102*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_bxt __initconst = {
1103*4882a593Smuzhiyun .state_table = bxt_cstates,
1104*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1105*4882a593Smuzhiyun };
1106*4882a593Smuzhiyun
1107*4882a593Smuzhiyun static const struct idle_cpu idle_cpu_dnv __initconst = {
1108*4882a593Smuzhiyun .state_table = dnv_cstates,
1109*4882a593Smuzhiyun .disable_promotion_to_c1e = true,
1110*4882a593Smuzhiyun .use_acpi = true,
1111*4882a593Smuzhiyun };
1112*4882a593Smuzhiyun
1113*4882a593Smuzhiyun static const struct x86_cpu_id intel_idle_ids[] __initconst = {
1114*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EP, &idle_cpu_nhx),
1115*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(NEHALEM, &idle_cpu_nehalem),
1116*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_G, &idle_cpu_nehalem),
1117*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(WESTMERE, &idle_cpu_nehalem),
1118*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EP, &idle_cpu_nhx),
1119*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EX, &idle_cpu_nhx),
1120*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL, &idle_cpu_atom),
1121*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL_MID, &idle_cpu_lincroft),
1122*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EX, &idle_cpu_nhx),
1123*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE, &idle_cpu_snb),
1124*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, &idle_cpu_snx),
1125*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_SALTWELL, &idle_cpu_atom),
1126*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, &idle_cpu_byt),
1127*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, &idle_cpu_tangier),
1128*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, &idle_cpu_cht),
1129*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE, &idle_cpu_ivb),
1130*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X, &idle_cpu_ivt),
1131*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(HASWELL, &idle_cpu_hsw),
1132*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X, &idle_cpu_hsx),
1133*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L, &idle_cpu_hsw),
1134*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G, &idle_cpu_hsw),
1135*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D, &idle_cpu_avn),
1136*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(BROADWELL, &idle_cpu_bdw),
1137*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G, &idle_cpu_bdw),
1138*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X, &idle_cpu_bdx),
1139*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D, &idle_cpu_bdx),
1140*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, &idle_cpu_skl),
1141*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, &idle_cpu_skl),
1142*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, &idle_cpu_skl),
1143*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, &idle_cpu_skl),
1144*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X, &idle_cpu_skx),
1145*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, &idle_cpu_icx),
1146*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &idle_cpu_knl),
1147*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &idle_cpu_knl),
1148*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &idle_cpu_bxt),
1149*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS, &idle_cpu_bxt),
1150*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D, &idle_cpu_dnv),
1151*4882a593Smuzhiyun X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D, &idle_cpu_dnv),
1152*4882a593Smuzhiyun {}
1153*4882a593Smuzhiyun };
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun static const struct x86_cpu_id intel_mwait_ids[] __initconst = {
1156*4882a593Smuzhiyun X86_MATCH_VENDOR_FAM_FEATURE(INTEL, 6, X86_FEATURE_MWAIT, NULL),
1157*4882a593Smuzhiyun {}
1158*4882a593Smuzhiyun };
1159*4882a593Smuzhiyun
intel_idle_max_cstate_reached(int cstate)1160*4882a593Smuzhiyun static bool __init intel_idle_max_cstate_reached(int cstate)
1161*4882a593Smuzhiyun {
1162*4882a593Smuzhiyun if (cstate + 1 > max_cstate) {
1163*4882a593Smuzhiyun pr_info("max_cstate %d reached\n", max_cstate);
1164*4882a593Smuzhiyun return true;
1165*4882a593Smuzhiyun }
1166*4882a593Smuzhiyun return false;
1167*4882a593Smuzhiyun }
1168*4882a593Smuzhiyun
intel_idle_state_needs_timer_stop(struct cpuidle_state * state)1169*4882a593Smuzhiyun static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state)
1170*4882a593Smuzhiyun {
1171*4882a593Smuzhiyun unsigned long eax = flg2MWAIT(state->flags);
1172*4882a593Smuzhiyun
1173*4882a593Smuzhiyun if (boot_cpu_has(X86_FEATURE_ARAT))
1174*4882a593Smuzhiyun return false;
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun /*
1177*4882a593Smuzhiyun * Switch over to one-shot tick broadcast if the target C-state
1178*4882a593Smuzhiyun * is deeper than C1.
1179*4882a593Smuzhiyun */
1180*4882a593Smuzhiyun return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK);
1181*4882a593Smuzhiyun }
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun #ifdef CONFIG_ACPI_PROCESSOR_CSTATE
1184*4882a593Smuzhiyun #include <acpi/processor.h>
1185*4882a593Smuzhiyun
1186*4882a593Smuzhiyun static bool no_acpi __read_mostly;
1187*4882a593Smuzhiyun module_param(no_acpi, bool, 0444);
1188*4882a593Smuzhiyun MODULE_PARM_DESC(no_acpi, "Do not use ACPI _CST for building the idle states list");
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun static bool force_use_acpi __read_mostly; /* No effect if no_acpi is set. */
1191*4882a593Smuzhiyun module_param_named(use_acpi, force_use_acpi, bool, 0444);
1192*4882a593Smuzhiyun MODULE_PARM_DESC(use_acpi, "Use ACPI _CST for building the idle states list");
1193*4882a593Smuzhiyun
1194*4882a593Smuzhiyun static struct acpi_processor_power acpi_state_table __initdata;
1195*4882a593Smuzhiyun
1196*4882a593Smuzhiyun /**
1197*4882a593Smuzhiyun * intel_idle_cst_usable - Check if the _CST information can be used.
1198*4882a593Smuzhiyun *
1199*4882a593Smuzhiyun * Check if all of the C-states listed by _CST in the max_cstate range are
1200*4882a593Smuzhiyun * ACPI_CSTATE_FFH, which means that they should be entered via MWAIT.
1201*4882a593Smuzhiyun */
intel_idle_cst_usable(void)1202*4882a593Smuzhiyun static bool __init intel_idle_cst_usable(void)
1203*4882a593Smuzhiyun {
1204*4882a593Smuzhiyun int cstate, limit;
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun limit = min_t(int, min_t(int, CPUIDLE_STATE_MAX, max_cstate + 1),
1207*4882a593Smuzhiyun acpi_state_table.count);
1208*4882a593Smuzhiyun
1209*4882a593Smuzhiyun for (cstate = 1; cstate < limit; cstate++) {
1210*4882a593Smuzhiyun struct acpi_processor_cx *cx = &acpi_state_table.states[cstate];
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun if (cx->entry_method != ACPI_CSTATE_FFH)
1213*4882a593Smuzhiyun return false;
1214*4882a593Smuzhiyun }
1215*4882a593Smuzhiyun
1216*4882a593Smuzhiyun return true;
1217*4882a593Smuzhiyun }
1218*4882a593Smuzhiyun
intel_idle_acpi_cst_extract(void)1219*4882a593Smuzhiyun static bool __init intel_idle_acpi_cst_extract(void)
1220*4882a593Smuzhiyun {
1221*4882a593Smuzhiyun unsigned int cpu;
1222*4882a593Smuzhiyun
1223*4882a593Smuzhiyun if (no_acpi) {
1224*4882a593Smuzhiyun pr_debug("Not allowed to use ACPI _CST\n");
1225*4882a593Smuzhiyun return false;
1226*4882a593Smuzhiyun }
1227*4882a593Smuzhiyun
1228*4882a593Smuzhiyun for_each_possible_cpu(cpu) {
1229*4882a593Smuzhiyun struct acpi_processor *pr = per_cpu(processors, cpu);
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun if (!pr)
1232*4882a593Smuzhiyun continue;
1233*4882a593Smuzhiyun
1234*4882a593Smuzhiyun if (acpi_processor_evaluate_cst(pr->handle, cpu, &acpi_state_table))
1235*4882a593Smuzhiyun continue;
1236*4882a593Smuzhiyun
1237*4882a593Smuzhiyun acpi_state_table.count++;
1238*4882a593Smuzhiyun
1239*4882a593Smuzhiyun if (!intel_idle_cst_usable())
1240*4882a593Smuzhiyun continue;
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun if (!acpi_processor_claim_cst_control())
1243*4882a593Smuzhiyun break;
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun return true;
1246*4882a593Smuzhiyun }
1247*4882a593Smuzhiyun
1248*4882a593Smuzhiyun acpi_state_table.count = 0;
1249*4882a593Smuzhiyun pr_debug("ACPI _CST not found or not usable\n");
1250*4882a593Smuzhiyun return false;
1251*4882a593Smuzhiyun }
1252*4882a593Smuzhiyun
intel_idle_init_cstates_acpi(struct cpuidle_driver * drv)1253*4882a593Smuzhiyun static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun int cstate, limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
1256*4882a593Smuzhiyun
1257*4882a593Smuzhiyun /*
1258*4882a593Smuzhiyun * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of
1259*4882a593Smuzhiyun * the interesting states are ACPI_CSTATE_FFH.
1260*4882a593Smuzhiyun */
1261*4882a593Smuzhiyun for (cstate = 1; cstate < limit; cstate++) {
1262*4882a593Smuzhiyun struct acpi_processor_cx *cx;
1263*4882a593Smuzhiyun struct cpuidle_state *state;
1264*4882a593Smuzhiyun
1265*4882a593Smuzhiyun if (intel_idle_max_cstate_reached(cstate - 1))
1266*4882a593Smuzhiyun break;
1267*4882a593Smuzhiyun
1268*4882a593Smuzhiyun cx = &acpi_state_table.states[cstate];
1269*4882a593Smuzhiyun
1270*4882a593Smuzhiyun state = &drv->states[drv->state_count++];
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun snprintf(state->name, CPUIDLE_NAME_LEN, "C%d_ACPI", cstate);
1273*4882a593Smuzhiyun strlcpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
1274*4882a593Smuzhiyun state->exit_latency = cx->latency;
1275*4882a593Smuzhiyun /*
1276*4882a593Smuzhiyun * For C1-type C-states use the same number for both the exit
1277*4882a593Smuzhiyun * latency and target residency, because that is the case for
1278*4882a593Smuzhiyun * C1 in the majority of the static C-states tables above.
1279*4882a593Smuzhiyun * For the other types of C-states, however, set the target
1280*4882a593Smuzhiyun * residency to 3 times the exit latency which should lead to
1281*4882a593Smuzhiyun * a reasonable balance between energy-efficiency and
1282*4882a593Smuzhiyun * performance in the majority of interesting cases.
1283*4882a593Smuzhiyun */
1284*4882a593Smuzhiyun state->target_residency = cx->latency;
1285*4882a593Smuzhiyun if (cx->type > ACPI_STATE_C1)
1286*4882a593Smuzhiyun state->target_residency *= 3;
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun state->flags = MWAIT2flg(cx->address);
1289*4882a593Smuzhiyun if (cx->type > ACPI_STATE_C2)
1290*4882a593Smuzhiyun state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
1291*4882a593Smuzhiyun
1292*4882a593Smuzhiyun if (disabled_states_mask & BIT(cstate))
1293*4882a593Smuzhiyun state->flags |= CPUIDLE_FLAG_OFF;
1294*4882a593Smuzhiyun
1295*4882a593Smuzhiyun if (intel_idle_state_needs_timer_stop(state))
1296*4882a593Smuzhiyun state->flags |= CPUIDLE_FLAG_TIMER_STOP;
1297*4882a593Smuzhiyun
1298*4882a593Smuzhiyun state->enter = intel_idle;
1299*4882a593Smuzhiyun state->enter_s2idle = intel_idle_s2idle;
1300*4882a593Smuzhiyun }
1301*4882a593Smuzhiyun }
1302*4882a593Smuzhiyun
intel_idle_off_by_default(u32 mwait_hint)1303*4882a593Smuzhiyun static bool __init intel_idle_off_by_default(u32 mwait_hint)
1304*4882a593Smuzhiyun {
1305*4882a593Smuzhiyun int cstate, limit;
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun /*
1308*4882a593Smuzhiyun * If there are no _CST C-states, do not disable any C-states by
1309*4882a593Smuzhiyun * default.
1310*4882a593Smuzhiyun */
1311*4882a593Smuzhiyun if (!acpi_state_table.count)
1312*4882a593Smuzhiyun return false;
1313*4882a593Smuzhiyun
1314*4882a593Smuzhiyun limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
1315*4882a593Smuzhiyun /*
1316*4882a593Smuzhiyun * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of
1317*4882a593Smuzhiyun * the interesting states are ACPI_CSTATE_FFH.
1318*4882a593Smuzhiyun */
1319*4882a593Smuzhiyun for (cstate = 1; cstate < limit; cstate++) {
1320*4882a593Smuzhiyun if (acpi_state_table.states[cstate].address == mwait_hint)
1321*4882a593Smuzhiyun return false;
1322*4882a593Smuzhiyun }
1323*4882a593Smuzhiyun return true;
1324*4882a593Smuzhiyun }
1325*4882a593Smuzhiyun #else /* !CONFIG_ACPI_PROCESSOR_CSTATE */
1326*4882a593Smuzhiyun #define force_use_acpi (false)
1327*4882a593Smuzhiyun
intel_idle_acpi_cst_extract(void)1328*4882a593Smuzhiyun static inline bool intel_idle_acpi_cst_extract(void) { return false; }
intel_idle_init_cstates_acpi(struct cpuidle_driver * drv)1329*4882a593Smuzhiyun static inline void intel_idle_init_cstates_acpi(struct cpuidle_driver *drv) { }
intel_idle_off_by_default(u32 mwait_hint)1330*4882a593Smuzhiyun static inline bool intel_idle_off_by_default(u32 mwait_hint) { return false; }
1331*4882a593Smuzhiyun #endif /* !CONFIG_ACPI_PROCESSOR_CSTATE */
1332*4882a593Smuzhiyun
1333*4882a593Smuzhiyun /**
1334*4882a593Smuzhiyun * ivt_idle_state_table_update - Tune the idle states table for Ivy Town.
1335*4882a593Smuzhiyun *
1336*4882a593Smuzhiyun * Tune IVT multi-socket targets.
1337*4882a593Smuzhiyun * Assumption: num_sockets == (max_package_num + 1).
1338*4882a593Smuzhiyun */
ivt_idle_state_table_update(void)1339*4882a593Smuzhiyun static void __init ivt_idle_state_table_update(void)
1340*4882a593Smuzhiyun {
1341*4882a593Smuzhiyun /* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
1342*4882a593Smuzhiyun int cpu, package_num, num_sockets = 1;
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun for_each_online_cpu(cpu) {
1345*4882a593Smuzhiyun package_num = topology_physical_package_id(cpu);
1346*4882a593Smuzhiyun if (package_num + 1 > num_sockets) {
1347*4882a593Smuzhiyun num_sockets = package_num + 1;
1348*4882a593Smuzhiyun
1349*4882a593Smuzhiyun if (num_sockets > 4) {
1350*4882a593Smuzhiyun cpuidle_state_table = ivt_cstates_8s;
1351*4882a593Smuzhiyun return;
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun }
1354*4882a593Smuzhiyun }
1355*4882a593Smuzhiyun
1356*4882a593Smuzhiyun if (num_sockets > 2)
1357*4882a593Smuzhiyun cpuidle_state_table = ivt_cstates_4s;
1358*4882a593Smuzhiyun
1359*4882a593Smuzhiyun /* else, 1 and 2 socket systems use default ivt_cstates */
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun
1362*4882a593Smuzhiyun /**
1363*4882a593Smuzhiyun * irtl_2_usec - IRTL to microseconds conversion.
1364*4882a593Smuzhiyun * @irtl: IRTL MSR value.
1365*4882a593Smuzhiyun *
1366*4882a593Smuzhiyun * Translate the IRTL (Interrupt Response Time Limit) MSR value to microseconds.
1367*4882a593Smuzhiyun */
irtl_2_usec(unsigned long long irtl)1368*4882a593Smuzhiyun static unsigned long long __init irtl_2_usec(unsigned long long irtl)
1369*4882a593Smuzhiyun {
1370*4882a593Smuzhiyun static const unsigned int irtl_ns_units[] __initconst = {
1371*4882a593Smuzhiyun 1, 32, 1024, 32768, 1048576, 33554432, 0, 0
1372*4882a593Smuzhiyun };
1373*4882a593Smuzhiyun unsigned long long ns;
1374*4882a593Smuzhiyun
1375*4882a593Smuzhiyun if (!irtl)
1376*4882a593Smuzhiyun return 0;
1377*4882a593Smuzhiyun
1378*4882a593Smuzhiyun ns = irtl_ns_units[(irtl >> 10) & 0x7];
1379*4882a593Smuzhiyun
1380*4882a593Smuzhiyun return div_u64((irtl & 0x3FF) * ns, NSEC_PER_USEC);
1381*4882a593Smuzhiyun }
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun /**
1384*4882a593Smuzhiyun * bxt_idle_state_table_update - Fix up the Broxton idle states table.
1385*4882a593Smuzhiyun *
1386*4882a593Smuzhiyun * On BXT, trust the IRTL (Interrupt Response Time Limit) MSR to show the
1387*4882a593Smuzhiyun * definitive maximum latency and use the same value for target_residency.
1388*4882a593Smuzhiyun */
bxt_idle_state_table_update(void)1389*4882a593Smuzhiyun static void __init bxt_idle_state_table_update(void)
1390*4882a593Smuzhiyun {
1391*4882a593Smuzhiyun unsigned long long msr;
1392*4882a593Smuzhiyun unsigned int usec;
1393*4882a593Smuzhiyun
1394*4882a593Smuzhiyun rdmsrl(MSR_PKGC6_IRTL, msr);
1395*4882a593Smuzhiyun usec = irtl_2_usec(msr);
1396*4882a593Smuzhiyun if (usec) {
1397*4882a593Smuzhiyun bxt_cstates[2].exit_latency = usec;
1398*4882a593Smuzhiyun bxt_cstates[2].target_residency = usec;
1399*4882a593Smuzhiyun }
1400*4882a593Smuzhiyun
1401*4882a593Smuzhiyun rdmsrl(MSR_PKGC7_IRTL, msr);
1402*4882a593Smuzhiyun usec = irtl_2_usec(msr);
1403*4882a593Smuzhiyun if (usec) {
1404*4882a593Smuzhiyun bxt_cstates[3].exit_latency = usec;
1405*4882a593Smuzhiyun bxt_cstates[3].target_residency = usec;
1406*4882a593Smuzhiyun }
1407*4882a593Smuzhiyun
1408*4882a593Smuzhiyun rdmsrl(MSR_PKGC8_IRTL, msr);
1409*4882a593Smuzhiyun usec = irtl_2_usec(msr);
1410*4882a593Smuzhiyun if (usec) {
1411*4882a593Smuzhiyun bxt_cstates[4].exit_latency = usec;
1412*4882a593Smuzhiyun bxt_cstates[4].target_residency = usec;
1413*4882a593Smuzhiyun }
1414*4882a593Smuzhiyun
1415*4882a593Smuzhiyun rdmsrl(MSR_PKGC9_IRTL, msr);
1416*4882a593Smuzhiyun usec = irtl_2_usec(msr);
1417*4882a593Smuzhiyun if (usec) {
1418*4882a593Smuzhiyun bxt_cstates[5].exit_latency = usec;
1419*4882a593Smuzhiyun bxt_cstates[5].target_residency = usec;
1420*4882a593Smuzhiyun }
1421*4882a593Smuzhiyun
1422*4882a593Smuzhiyun rdmsrl(MSR_PKGC10_IRTL, msr);
1423*4882a593Smuzhiyun usec = irtl_2_usec(msr);
1424*4882a593Smuzhiyun if (usec) {
1425*4882a593Smuzhiyun bxt_cstates[6].exit_latency = usec;
1426*4882a593Smuzhiyun bxt_cstates[6].target_residency = usec;
1427*4882a593Smuzhiyun }
1428*4882a593Smuzhiyun
1429*4882a593Smuzhiyun }
1430*4882a593Smuzhiyun
1431*4882a593Smuzhiyun /**
1432*4882a593Smuzhiyun * sklh_idle_state_table_update - Fix up the Sky Lake idle states table.
1433*4882a593Smuzhiyun *
1434*4882a593Smuzhiyun * On SKL-H (model 0x5e) skip C8 and C9 if C10 is enabled and SGX disabled.
1435*4882a593Smuzhiyun */
sklh_idle_state_table_update(void)1436*4882a593Smuzhiyun static void __init sklh_idle_state_table_update(void)
1437*4882a593Smuzhiyun {
1438*4882a593Smuzhiyun unsigned long long msr;
1439*4882a593Smuzhiyun unsigned int eax, ebx, ecx, edx;
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun
1442*4882a593Smuzhiyun /* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */
1443*4882a593Smuzhiyun if (max_cstate <= 7)
1444*4882a593Smuzhiyun return;
1445*4882a593Smuzhiyun
1446*4882a593Smuzhiyun /* if PC10 not present in CPUID.MWAIT.EDX */
1447*4882a593Smuzhiyun if ((mwait_substates & (0xF << 28)) == 0)
1448*4882a593Smuzhiyun return;
1449*4882a593Smuzhiyun
1450*4882a593Smuzhiyun rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
1451*4882a593Smuzhiyun
1452*4882a593Smuzhiyun /* PC10 is not enabled in PKG C-state limit */
1453*4882a593Smuzhiyun if ((msr & 0xF) != 8)
1454*4882a593Smuzhiyun return;
1455*4882a593Smuzhiyun
1456*4882a593Smuzhiyun ecx = 0;
1457*4882a593Smuzhiyun cpuid(7, &eax, &ebx, &ecx, &edx);
1458*4882a593Smuzhiyun
1459*4882a593Smuzhiyun /* if SGX is present */
1460*4882a593Smuzhiyun if (ebx & (1 << 2)) {
1461*4882a593Smuzhiyun
1462*4882a593Smuzhiyun rdmsrl(MSR_IA32_FEAT_CTL, msr);
1463*4882a593Smuzhiyun
1464*4882a593Smuzhiyun /* if SGX is enabled */
1465*4882a593Smuzhiyun if (msr & (1 << 18))
1466*4882a593Smuzhiyun return;
1467*4882a593Smuzhiyun }
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun skl_cstates[5].flags |= CPUIDLE_FLAG_UNUSABLE; /* C8-SKL */
1470*4882a593Smuzhiyun skl_cstates[6].flags |= CPUIDLE_FLAG_UNUSABLE; /* C9-SKL */
1471*4882a593Smuzhiyun }
1472*4882a593Smuzhiyun
intel_idle_verify_cstate(unsigned int mwait_hint)1473*4882a593Smuzhiyun static bool __init intel_idle_verify_cstate(unsigned int mwait_hint)
1474*4882a593Smuzhiyun {
1475*4882a593Smuzhiyun unsigned int mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint) + 1;
1476*4882a593Smuzhiyun unsigned int num_substates = (mwait_substates >> mwait_cstate * 4) &
1477*4882a593Smuzhiyun MWAIT_SUBSTATE_MASK;
1478*4882a593Smuzhiyun
1479*4882a593Smuzhiyun /* Ignore the C-state if there are NO sub-states in CPUID for it. */
1480*4882a593Smuzhiyun if (num_substates == 0)
1481*4882a593Smuzhiyun return false;
1482*4882a593Smuzhiyun
1483*4882a593Smuzhiyun if (mwait_cstate > 2 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
1484*4882a593Smuzhiyun mark_tsc_unstable("TSC halts in idle states deeper than C2");
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun return true;
1487*4882a593Smuzhiyun }
1488*4882a593Smuzhiyun
intel_idle_init_cstates_icpu(struct cpuidle_driver * drv)1489*4882a593Smuzhiyun static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
1490*4882a593Smuzhiyun {
1491*4882a593Smuzhiyun int cstate;
1492*4882a593Smuzhiyun
1493*4882a593Smuzhiyun switch (boot_cpu_data.x86_model) {
1494*4882a593Smuzhiyun case INTEL_FAM6_IVYBRIDGE_X:
1495*4882a593Smuzhiyun ivt_idle_state_table_update();
1496*4882a593Smuzhiyun break;
1497*4882a593Smuzhiyun case INTEL_FAM6_ATOM_GOLDMONT:
1498*4882a593Smuzhiyun case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
1499*4882a593Smuzhiyun bxt_idle_state_table_update();
1500*4882a593Smuzhiyun break;
1501*4882a593Smuzhiyun case INTEL_FAM6_SKYLAKE:
1502*4882a593Smuzhiyun sklh_idle_state_table_update();
1503*4882a593Smuzhiyun break;
1504*4882a593Smuzhiyun }
1505*4882a593Smuzhiyun
1506*4882a593Smuzhiyun for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
1507*4882a593Smuzhiyun unsigned int mwait_hint;
1508*4882a593Smuzhiyun
1509*4882a593Smuzhiyun if (intel_idle_max_cstate_reached(cstate))
1510*4882a593Smuzhiyun break;
1511*4882a593Smuzhiyun
1512*4882a593Smuzhiyun if (!cpuidle_state_table[cstate].enter &&
1513*4882a593Smuzhiyun !cpuidle_state_table[cstate].enter_s2idle)
1514*4882a593Smuzhiyun break;
1515*4882a593Smuzhiyun
1516*4882a593Smuzhiyun /* If marked as unusable, skip this state. */
1517*4882a593Smuzhiyun if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_UNUSABLE) {
1518*4882a593Smuzhiyun pr_debug("state %s is disabled\n",
1519*4882a593Smuzhiyun cpuidle_state_table[cstate].name);
1520*4882a593Smuzhiyun continue;
1521*4882a593Smuzhiyun }
1522*4882a593Smuzhiyun
1523*4882a593Smuzhiyun mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
1524*4882a593Smuzhiyun if (!intel_idle_verify_cstate(mwait_hint))
1525*4882a593Smuzhiyun continue;
1526*4882a593Smuzhiyun
1527*4882a593Smuzhiyun /* Structure copy. */
1528*4882a593Smuzhiyun drv->states[drv->state_count] = cpuidle_state_table[cstate];
1529*4882a593Smuzhiyun
1530*4882a593Smuzhiyun if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) &&
1531*4882a593Smuzhiyun cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IBRS) {
1532*4882a593Smuzhiyun drv->states[drv->state_count].enter = intel_idle_ibrs;
1533*4882a593Smuzhiyun }
1534*4882a593Smuzhiyun
1535*4882a593Smuzhiyun if ((disabled_states_mask & BIT(drv->state_count)) ||
1536*4882a593Smuzhiyun ((icpu->use_acpi || force_use_acpi) &&
1537*4882a593Smuzhiyun intel_idle_off_by_default(mwait_hint) &&
1538*4882a593Smuzhiyun !(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
1539*4882a593Smuzhiyun drv->states[drv->state_count].flags |= CPUIDLE_FLAG_OFF;
1540*4882a593Smuzhiyun
1541*4882a593Smuzhiyun if (intel_idle_state_needs_timer_stop(&drv->states[drv->state_count]))
1542*4882a593Smuzhiyun drv->states[drv->state_count].flags |= CPUIDLE_FLAG_TIMER_STOP;
1543*4882a593Smuzhiyun
1544*4882a593Smuzhiyun drv->state_count++;
1545*4882a593Smuzhiyun }
1546*4882a593Smuzhiyun
1547*4882a593Smuzhiyun if (icpu->byt_auto_demotion_disable_flag) {
1548*4882a593Smuzhiyun wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0);
1549*4882a593Smuzhiyun wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0);
1550*4882a593Smuzhiyun }
1551*4882a593Smuzhiyun }
1552*4882a593Smuzhiyun
1553*4882a593Smuzhiyun /**
1554*4882a593Smuzhiyun * intel_idle_cpuidle_driver_init - Create the list of available idle states.
1555*4882a593Smuzhiyun * @drv: cpuidle driver structure to initialize.
1556*4882a593Smuzhiyun */
intel_idle_cpuidle_driver_init(struct cpuidle_driver * drv)1557*4882a593Smuzhiyun static void __init intel_idle_cpuidle_driver_init(struct cpuidle_driver *drv)
1558*4882a593Smuzhiyun {
1559*4882a593Smuzhiyun cpuidle_poll_state_init(drv);
1560*4882a593Smuzhiyun
1561*4882a593Smuzhiyun if (disabled_states_mask & BIT(0))
1562*4882a593Smuzhiyun drv->states[0].flags |= CPUIDLE_FLAG_OFF;
1563*4882a593Smuzhiyun
1564*4882a593Smuzhiyun drv->state_count = 1;
1565*4882a593Smuzhiyun
1566*4882a593Smuzhiyun if (icpu)
1567*4882a593Smuzhiyun intel_idle_init_cstates_icpu(drv);
1568*4882a593Smuzhiyun else
1569*4882a593Smuzhiyun intel_idle_init_cstates_acpi(drv);
1570*4882a593Smuzhiyun }
1571*4882a593Smuzhiyun
auto_demotion_disable(void)1572*4882a593Smuzhiyun static void auto_demotion_disable(void)
1573*4882a593Smuzhiyun {
1574*4882a593Smuzhiyun unsigned long long msr_bits;
1575*4882a593Smuzhiyun
1576*4882a593Smuzhiyun rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
1577*4882a593Smuzhiyun msr_bits &= ~auto_demotion_disable_flags;
1578*4882a593Smuzhiyun wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
1579*4882a593Smuzhiyun }
1580*4882a593Smuzhiyun
c1e_promotion_disable(void)1581*4882a593Smuzhiyun static void c1e_promotion_disable(void)
1582*4882a593Smuzhiyun {
1583*4882a593Smuzhiyun unsigned long long msr_bits;
1584*4882a593Smuzhiyun
1585*4882a593Smuzhiyun rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
1586*4882a593Smuzhiyun msr_bits &= ~0x2;
1587*4882a593Smuzhiyun wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
1588*4882a593Smuzhiyun }
1589*4882a593Smuzhiyun
1590*4882a593Smuzhiyun /**
1591*4882a593Smuzhiyun * intel_idle_cpu_init - Register the target CPU with the cpuidle core.
1592*4882a593Smuzhiyun * @cpu: CPU to initialize.
1593*4882a593Smuzhiyun *
1594*4882a593Smuzhiyun * Register a cpuidle device object for @cpu and update its MSRs in accordance
1595*4882a593Smuzhiyun * with the processor model flags.
1596*4882a593Smuzhiyun */
intel_idle_cpu_init(unsigned int cpu)1597*4882a593Smuzhiyun static int intel_idle_cpu_init(unsigned int cpu)
1598*4882a593Smuzhiyun {
1599*4882a593Smuzhiyun struct cpuidle_device *dev;
1600*4882a593Smuzhiyun
1601*4882a593Smuzhiyun dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
1602*4882a593Smuzhiyun dev->cpu = cpu;
1603*4882a593Smuzhiyun
1604*4882a593Smuzhiyun if (cpuidle_register_device(dev)) {
1605*4882a593Smuzhiyun pr_debug("cpuidle_register_device %d failed!\n", cpu);
1606*4882a593Smuzhiyun return -EIO;
1607*4882a593Smuzhiyun }
1608*4882a593Smuzhiyun
1609*4882a593Smuzhiyun if (auto_demotion_disable_flags)
1610*4882a593Smuzhiyun auto_demotion_disable();
1611*4882a593Smuzhiyun
1612*4882a593Smuzhiyun if (disable_promotion_to_c1e)
1613*4882a593Smuzhiyun c1e_promotion_disable();
1614*4882a593Smuzhiyun
1615*4882a593Smuzhiyun return 0;
1616*4882a593Smuzhiyun }
1617*4882a593Smuzhiyun
intel_idle_cpu_online(unsigned int cpu)1618*4882a593Smuzhiyun static int intel_idle_cpu_online(unsigned int cpu)
1619*4882a593Smuzhiyun {
1620*4882a593Smuzhiyun struct cpuidle_device *dev;
1621*4882a593Smuzhiyun
1622*4882a593Smuzhiyun if (!boot_cpu_has(X86_FEATURE_ARAT))
1623*4882a593Smuzhiyun tick_broadcast_enable();
1624*4882a593Smuzhiyun
1625*4882a593Smuzhiyun /*
1626*4882a593Smuzhiyun * Some systems can hotplug a cpu at runtime after
1627*4882a593Smuzhiyun * the kernel has booted, we have to initialize the
1628*4882a593Smuzhiyun * driver in this case
1629*4882a593Smuzhiyun */
1630*4882a593Smuzhiyun dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
1631*4882a593Smuzhiyun if (!dev->registered)
1632*4882a593Smuzhiyun return intel_idle_cpu_init(cpu);
1633*4882a593Smuzhiyun
1634*4882a593Smuzhiyun return 0;
1635*4882a593Smuzhiyun }
1636*4882a593Smuzhiyun
1637*4882a593Smuzhiyun /**
1638*4882a593Smuzhiyun * intel_idle_cpuidle_devices_uninit - Unregister all cpuidle devices.
1639*4882a593Smuzhiyun */
intel_idle_cpuidle_devices_uninit(void)1640*4882a593Smuzhiyun static void __init intel_idle_cpuidle_devices_uninit(void)
1641*4882a593Smuzhiyun {
1642*4882a593Smuzhiyun int i;
1643*4882a593Smuzhiyun
1644*4882a593Smuzhiyun for_each_online_cpu(i)
1645*4882a593Smuzhiyun cpuidle_unregister_device(per_cpu_ptr(intel_idle_cpuidle_devices, i));
1646*4882a593Smuzhiyun }
1647*4882a593Smuzhiyun
intel_idle_init(void)1648*4882a593Smuzhiyun static int __init intel_idle_init(void)
1649*4882a593Smuzhiyun {
1650*4882a593Smuzhiyun const struct x86_cpu_id *id;
1651*4882a593Smuzhiyun unsigned int eax, ebx, ecx;
1652*4882a593Smuzhiyun int retval;
1653*4882a593Smuzhiyun
1654*4882a593Smuzhiyun /* Do not load intel_idle at all for now if idle= is passed */
1655*4882a593Smuzhiyun if (boot_option_idle_override != IDLE_NO_OVERRIDE)
1656*4882a593Smuzhiyun return -ENODEV;
1657*4882a593Smuzhiyun
1658*4882a593Smuzhiyun if (max_cstate == 0) {
1659*4882a593Smuzhiyun pr_debug("disabled\n");
1660*4882a593Smuzhiyun return -EPERM;
1661*4882a593Smuzhiyun }
1662*4882a593Smuzhiyun
1663*4882a593Smuzhiyun id = x86_match_cpu(intel_idle_ids);
1664*4882a593Smuzhiyun if (id) {
1665*4882a593Smuzhiyun if (!boot_cpu_has(X86_FEATURE_MWAIT)) {
1666*4882a593Smuzhiyun pr_debug("Please enable MWAIT in BIOS SETUP\n");
1667*4882a593Smuzhiyun return -ENODEV;
1668*4882a593Smuzhiyun }
1669*4882a593Smuzhiyun } else {
1670*4882a593Smuzhiyun id = x86_match_cpu(intel_mwait_ids);
1671*4882a593Smuzhiyun if (!id)
1672*4882a593Smuzhiyun return -ENODEV;
1673*4882a593Smuzhiyun }
1674*4882a593Smuzhiyun
1675*4882a593Smuzhiyun if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
1676*4882a593Smuzhiyun return -ENODEV;
1677*4882a593Smuzhiyun
1678*4882a593Smuzhiyun cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
1679*4882a593Smuzhiyun
1680*4882a593Smuzhiyun if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
1681*4882a593Smuzhiyun !(ecx & CPUID5_ECX_INTERRUPT_BREAK) ||
1682*4882a593Smuzhiyun !mwait_substates)
1683*4882a593Smuzhiyun return -ENODEV;
1684*4882a593Smuzhiyun
1685*4882a593Smuzhiyun pr_debug("MWAIT substates: 0x%x\n", mwait_substates);
1686*4882a593Smuzhiyun
1687*4882a593Smuzhiyun icpu = (const struct idle_cpu *)id->driver_data;
1688*4882a593Smuzhiyun if (icpu) {
1689*4882a593Smuzhiyun cpuidle_state_table = icpu->state_table;
1690*4882a593Smuzhiyun auto_demotion_disable_flags = icpu->auto_demotion_disable_flags;
1691*4882a593Smuzhiyun disable_promotion_to_c1e = icpu->disable_promotion_to_c1e;
1692*4882a593Smuzhiyun if (icpu->use_acpi || force_use_acpi)
1693*4882a593Smuzhiyun intel_idle_acpi_cst_extract();
1694*4882a593Smuzhiyun } else if (!intel_idle_acpi_cst_extract()) {
1695*4882a593Smuzhiyun return -ENODEV;
1696*4882a593Smuzhiyun }
1697*4882a593Smuzhiyun
1698*4882a593Smuzhiyun pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n",
1699*4882a593Smuzhiyun boot_cpu_data.x86_model);
1700*4882a593Smuzhiyun
1701*4882a593Smuzhiyun intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
1702*4882a593Smuzhiyun if (!intel_idle_cpuidle_devices)
1703*4882a593Smuzhiyun return -ENOMEM;
1704*4882a593Smuzhiyun
1705*4882a593Smuzhiyun intel_idle_cpuidle_driver_init(&intel_idle_driver);
1706*4882a593Smuzhiyun
1707*4882a593Smuzhiyun retval = cpuidle_register_driver(&intel_idle_driver);
1708*4882a593Smuzhiyun if (retval) {
1709*4882a593Smuzhiyun struct cpuidle_driver *drv = cpuidle_get_driver();
1710*4882a593Smuzhiyun printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"),
1711*4882a593Smuzhiyun drv ? drv->name : "none");
1712*4882a593Smuzhiyun goto init_driver_fail;
1713*4882a593Smuzhiyun }
1714*4882a593Smuzhiyun
1715*4882a593Smuzhiyun retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
1716*4882a593Smuzhiyun intel_idle_cpu_online, NULL);
1717*4882a593Smuzhiyun if (retval < 0)
1718*4882a593Smuzhiyun goto hp_setup_fail;
1719*4882a593Smuzhiyun
1720*4882a593Smuzhiyun pr_debug("Local APIC timer is reliable in %s\n",
1721*4882a593Smuzhiyun boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1");
1722*4882a593Smuzhiyun
1723*4882a593Smuzhiyun return 0;
1724*4882a593Smuzhiyun
1725*4882a593Smuzhiyun hp_setup_fail:
1726*4882a593Smuzhiyun intel_idle_cpuidle_devices_uninit();
1727*4882a593Smuzhiyun cpuidle_unregister_driver(&intel_idle_driver);
1728*4882a593Smuzhiyun init_driver_fail:
1729*4882a593Smuzhiyun free_percpu(intel_idle_cpuidle_devices);
1730*4882a593Smuzhiyun return retval;
1731*4882a593Smuzhiyun
1732*4882a593Smuzhiyun }
1733*4882a593Smuzhiyun device_initcall(intel_idle_init);
1734*4882a593Smuzhiyun
1735*4882a593Smuzhiyun /*
1736*4882a593Smuzhiyun * We are not really modular, but we used to support that. Meaning we also
1737*4882a593Smuzhiyun * support "intel_idle.max_cstate=..." at boot and also a read-only export of
1738*4882a593Smuzhiyun * it at /sys/module/intel_idle/parameters/max_cstate -- so using module_param
1739*4882a593Smuzhiyun * is the easiest way (currently) to continue doing that.
1740*4882a593Smuzhiyun */
1741*4882a593Smuzhiyun module_param(max_cstate, int, 0444);
1742*4882a593Smuzhiyun /*
1743*4882a593Smuzhiyun * The positions of the bits that are set in this number are the indices of the
1744*4882a593Smuzhiyun * idle states to be disabled by default (as reflected by the names of the
1745*4882a593Smuzhiyun * corresponding idle state directories in sysfs, "state0", "state1" ...
1746*4882a593Smuzhiyun * "state<i>" ..., where <i> is the index of the given state).
1747*4882a593Smuzhiyun */
1748*4882a593Smuzhiyun module_param_named(states_off, disabled_states_mask, uint, 0444);
1749*4882a593Smuzhiyun MODULE_PARM_DESC(states_off, "Mask of disabled idle states");
1750