xref: /openbmc/linux/drivers/idle/intel_idle.c (revision 0f9b4c3ca5fdf3e177266ef994071b1a03f07318)
1a61127c2SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
226717172SLen Brown /*
326717172SLen Brown  * intel_idle.c - native hardware idle loop for modern Intel processors
426717172SLen Brown  *
5317e5ec3SRafael J. Wysocki  * Copyright (c) 2013 - 2020, Intel Corporation.
626717172SLen Brown  * Len Brown <len.brown@intel.com>
7317e5ec3SRafael J. Wysocki  * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
826717172SLen Brown  */
926717172SLen Brown 
1026717172SLen Brown /*
118bb2e2a8SAlexander Monakov  * intel_idle is a cpuidle driver that loads on all Intel CPUs with MWAIT
1226717172SLen Brown  * in lieu of the legacy ACPI processor_idle driver.  The intent is to
1326717172SLen Brown  * make Linux more efficient on these processors, as intel_idle knows
1426717172SLen Brown  * more than ACPI, as well as make Linux more immune to ACPI BIOS bugs.
1526717172SLen Brown  */
1626717172SLen Brown 
1726717172SLen Brown /*
1826717172SLen Brown  * Design Assumptions
1926717172SLen Brown  *
2026717172SLen Brown  * All CPUs have same idle states as boot CPU
2126717172SLen Brown  *
2226717172SLen Brown  * Chipset BM_STS (bus master status) bit is a NOP
238bb2e2a8SAlexander Monakov  *	for preventing entry into deep C-states
248bb2e2a8SAlexander Monakov  *
258bb2e2a8SAlexander Monakov  * CPU will flush caches as needed when entering a C-state via MWAIT
268bb2e2a8SAlexander Monakov  *	(in contrast to entering ACPI C3, in which case the WBINVD
278bb2e2a8SAlexander Monakov  *	instruction needs to be executed to flush the caches)
2826717172SLen Brown  */
2926717172SLen Brown 
3026717172SLen Brown /*
3126717172SLen Brown  * Known limitations
3226717172SLen Brown  *
3326717172SLen Brown  * ACPI has a .suspend hack to turn off deep c-statees during suspend
3426717172SLen Brown  * to avoid complications with the lapic timer workaround.
3526717172SLen Brown  * Have not seen issues with suspend, but may need same workaround here.
3626717172SLen Brown  *
3726717172SLen Brown  */
3826717172SLen Brown 
3926717172SLen Brown /* un-comment DEBUG to enable pr_debug() statements */
40651bc581STom Rix /* #define DEBUG */
4126717172SLen Brown 
42654d08a4SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
43654d08a4SJoe Perches 
4418734958SRafael J. Wysocki #include <linux/acpi.h>
4526717172SLen Brown #include <linux/kernel.h>
4626717172SLen Brown #include <linux/cpuidle.h>
4776962caaSThomas Gleixner #include <linux/tick.h>
4826717172SLen Brown #include <trace/events/power.h>
4926717172SLen Brown #include <linux/sched.h>
50bf5835bcSPeter Zijlstra #include <linux/sched/smt.h>
512a2d31c8SShaohua Li #include <linux/notifier.h>
522a2d31c8SShaohua Li #include <linux/cpu.h>
5302c4fae9SPaul Gortmaker #include <linux/moduleparam.h>
54b66b8b9aSAndi Kleen #include <asm/cpu_device_id.h>
55db73c5a8SDave Hansen #include <asm/intel-family.h>
56bf5835bcSPeter Zijlstra #include <asm/nospec-branch.h>
57bc83ccccSH. Peter Anvin #include <asm/mwait.h>
5814796fcaSLen Brown #include <asm/msr.h>
59*3b7d2d1bSThomas Gleixner #include <asm/tsc.h>
609f011293SChang S. Bae #include <asm/fpu/api.h>
6126717172SLen Brown 
62317e5ec3SRafael J. Wysocki #define INTEL_IDLE_VERSION "0.5.1"
6326717172SLen Brown 
6426717172SLen Brown static struct cpuidle_driver intel_idle_driver = {
6526717172SLen Brown 	.name = "intel_idle",
6626717172SLen Brown 	.owner = THIS_MODULE,
6726717172SLen Brown };
6826717172SLen Brown /* intel_idle.max_cstate=0 disables driver */
69137ecc77SLen Brown static int max_cstate = CPUIDLE_STATE_MAX - 1;
70bd446829SArtem Bityutskiy static unsigned int disabled_states_mask __read_mostly;
71bd446829SArtem Bityutskiy static unsigned int preferred_states_mask __read_mostly;
724152379aSArtem Bityutskiy static bool force_irq_on __read_mostly;
7326717172SLen Brown 
746eb0443aSRafael J. Wysocki static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
757f843dd7SRafael J. Wysocki 
767f843dd7SRafael J. Wysocki static unsigned long auto_demotion_disable_flags;
7739c184a6SArtem Bityutskiy 
7839c184a6SArtem Bityutskiy static enum {
7939c184a6SArtem Bityutskiy 	C1E_PROMOTION_PRESERVE,
8039c184a6SArtem Bityutskiy 	C1E_PROMOTION_ENABLE,
8139c184a6SArtem Bityutskiy 	C1E_PROMOTION_DISABLE
8239c184a6SArtem Bityutskiy } c1e_promotion = C1E_PROMOTION_PRESERVE;
837f843dd7SRafael J. Wysocki 
84b66b8b9aSAndi Kleen struct idle_cpu {
85b66b8b9aSAndi Kleen 	struct cpuidle_state *state_table;
8626717172SLen Brown 
8726717172SLen Brown 	/*
8814796fcaSLen Brown 	 * Hardware C-state auto-demotion may not always be optimal.
8914796fcaSLen Brown 	 * Indicate which enable bits to clear here.
9014796fcaSLen Brown 	 */
91b66b8b9aSAndi Kleen 	unsigned long auto_demotion_disable_flags;
928c058d53SLen Brown 	bool byt_auto_demotion_disable_flag;
9332e95180SLen Brown 	bool disable_promotion_to_c1e;
94bff8e60aSRafael J. Wysocki 	bool use_acpi;
95b66b8b9aSAndi Kleen };
96b66b8b9aSAndi Kleen 
977f843dd7SRafael J. Wysocki static const struct idle_cpu *icpu __initdata;
987f843dd7SRafael J. Wysocki static struct cpuidle_state *cpuidle_state_table __initdata;
9914796fcaSLen Brown 
1006eb0443aSRafael J. Wysocki static unsigned int mwait_substates __initdata;
1016eb0443aSRafael J. Wysocki 
10214796fcaSLen Brown /*
103c227233aSArtem Bityutskiy  * Enable interrupts before entering the C-state. On some platforms and for
104c227233aSArtem Bityutskiy  * some C-states, this may measurably decrease interrupt latency.
105c227233aSArtem Bityutskiy  */
106c227233aSArtem Bityutskiy #define CPUIDLE_FLAG_IRQ_ENABLE		BIT(14)
107c227233aSArtem Bityutskiy 
108c227233aSArtem Bityutskiy /*
109bff8e60aSRafael J. Wysocki  * Enable this state by default even if the ACPI _CST does not list it.
110bff8e60aSRafael J. Wysocki  */
111bff8e60aSRafael J. Wysocki #define CPUIDLE_FLAG_ALWAYS_ENABLE	BIT(15)
112bff8e60aSRafael J. Wysocki 
113bff8e60aSRafael J. Wysocki /*
114bf5835bcSPeter Zijlstra  * Disable IBRS across idle (when KERNEL_IBRS), is exclusive vs IRQ_ENABLE
115bf5835bcSPeter Zijlstra  * above.
116bf5835bcSPeter Zijlstra  */
117bf5835bcSPeter Zijlstra #define CPUIDLE_FLAG_IBRS		BIT(16)
118bf5835bcSPeter Zijlstra 
119bf5835bcSPeter Zijlstra /*
1209f011293SChang S. Bae  * Initialize large xstate for the C6-state entrance.
1219f011293SChang S. Bae  */
1229f011293SChang S. Bae #define CPUIDLE_FLAG_INIT_XSTATE	BIT(17)
1239f011293SChang S. Bae 
1249f011293SChang S. Bae /*
125b1beab48SLen Brown  * MWAIT takes an 8-bit "hint" in EAX "suggesting"
126b1beab48SLen Brown  * the C-state (top nibble) and sub-state (bottom nibble)
127b1beab48SLen Brown  * 0x00 means "MWAIT(C1)", 0x10 means "MWAIT(C2)" etc.
128b1beab48SLen Brown  *
129b1beab48SLen Brown  * We store the hint at the top of our "flags" for each state.
130b1beab48SLen Brown  */
131b1beab48SLen Brown #define flg2MWAIT(flags) (((flags) >> 24) & 0xFF)
132b1beab48SLen Brown #define MWAIT2flg(eax) ((eax & 0xFF) << 24)
133b1beab48SLen Brown 
__intel_idle(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index,bool irqoff)13432d4fd57SPeter Zijlstra static __always_inline int __intel_idle(struct cpuidle_device *dev,
13508beb0d4SPeter Zijlstra 					struct cpuidle_driver *drv,
13608beb0d4SPeter Zijlstra 					int index, bool irqoff)
13732d4fd57SPeter Zijlstra {
13832d4fd57SPeter Zijlstra 	struct cpuidle_state *state = &drv->states[index];
13932d4fd57SPeter Zijlstra 	unsigned long eax = flg2MWAIT(state->flags);
14008beb0d4SPeter Zijlstra 	unsigned long ecx = 1*irqoff; /* break on interrupt flag */
14132d4fd57SPeter Zijlstra 
14232d4fd57SPeter Zijlstra 	mwait_idle_with_hints(eax, ecx);
14332d4fd57SPeter Zijlstra 
14432d4fd57SPeter Zijlstra 	return index;
14532d4fd57SPeter Zijlstra }
14632d4fd57SPeter Zijlstra 
14730a996fbSRafael J. Wysocki /**
14830a996fbSRafael J. Wysocki  * intel_idle - Ask the processor to enter the given idle state.
14930a996fbSRafael J. Wysocki  * @dev: cpuidle device of the target CPU.
15030a996fbSRafael J. Wysocki  * @drv: cpuidle driver (assumed to point to intel_idle_driver).
15130a996fbSRafael J. Wysocki  * @index: Target idle state index.
15230a996fbSRafael J. Wysocki  *
15330a996fbSRafael J. Wysocki  * Use the MWAIT instruction to notify the processor that the CPU represented by
15430a996fbSRafael J. Wysocki  * @dev is idle and it can try to enter the idle state corresponding to @index.
15530a996fbSRafael J. Wysocki  *
15630a996fbSRafael J. Wysocki  * If the local APIC timer is not known to be reliable in the target idle state,
15730a996fbSRafael J. Wysocki  * enable one-shot tick broadcasting for the target CPU before executing MWAIT.
15830a996fbSRafael J. Wysocki  *
15930a996fbSRafael J. Wysocki  * Must be called under local_irq_disable().
16030a996fbSRafael J. Wysocki  */
intel_idle(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)16130a996fbSRafael J. Wysocki static __cpuidle int intel_idle(struct cpuidle_device *dev,
16230a996fbSRafael J. Wysocki 				struct cpuidle_driver *drv, int index)
16330a996fbSRafael J. Wysocki {
16408beb0d4SPeter Zijlstra 	return __intel_idle(dev, drv, index, true);
16532d4fd57SPeter Zijlstra }
16630a996fbSRafael J. Wysocki 
intel_idle_irq(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)16732d4fd57SPeter Zijlstra static __cpuidle int intel_idle_irq(struct cpuidle_device *dev,
16832d4fd57SPeter Zijlstra 				    struct cpuidle_driver *drv, int index)
16932d4fd57SPeter Zijlstra {
17008beb0d4SPeter Zijlstra 	return __intel_idle(dev, drv, index, false);
17130a996fbSRafael J. Wysocki }
17230a996fbSRafael J. Wysocki 
intel_idle_ibrs(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)173bf5835bcSPeter Zijlstra static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
174bf5835bcSPeter Zijlstra 				     struct cpuidle_driver *drv, int index)
175bf5835bcSPeter Zijlstra {
176bf5835bcSPeter Zijlstra 	bool smt_active = sched_smt_active();
177bf5835bcSPeter Zijlstra 	u64 spec_ctrl = spec_ctrl_current();
178bf5835bcSPeter Zijlstra 	int ret;
179bf5835bcSPeter Zijlstra 
180bf5835bcSPeter Zijlstra 	if (smt_active)
1819b461a6fSPeter Zijlstra 		native_wrmsrl(MSR_IA32_SPEC_CTRL, 0);
182bf5835bcSPeter Zijlstra 
18308beb0d4SPeter Zijlstra 	ret = __intel_idle(dev, drv, index, true);
184bf5835bcSPeter Zijlstra 
185bf5835bcSPeter Zijlstra 	if (smt_active)
1869b461a6fSPeter Zijlstra 		native_wrmsrl(MSR_IA32_SPEC_CTRL, spec_ctrl);
187bf5835bcSPeter Zijlstra 
188bf5835bcSPeter Zijlstra 	return ret;
189bf5835bcSPeter Zijlstra }
190bf5835bcSPeter Zijlstra 
intel_idle_xstate(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)1919f011293SChang S. Bae static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev,
1929f011293SChang S. Bae 				       struct cpuidle_driver *drv, int index)
1939f011293SChang S. Bae {
1949f011293SChang S. Bae 	fpu_idle_fpregs();
19508beb0d4SPeter Zijlstra 	return __intel_idle(dev, drv, index, true);
1969f011293SChang S. Bae }
1979f011293SChang S. Bae 
19830a996fbSRafael J. Wysocki /**
19930a996fbSRafael J. Wysocki  * intel_idle_s2idle - Ask the processor to enter the given idle state.
20030a996fbSRafael J. Wysocki  * @dev: cpuidle device of the target CPU.
20130a996fbSRafael J. Wysocki  * @drv: cpuidle driver (assumed to point to intel_idle_driver).
20230a996fbSRafael J. Wysocki  * @index: Target idle state index.
20330a996fbSRafael J. Wysocki  *
20430a996fbSRafael J. Wysocki  * Use the MWAIT instruction to notify the processor that the CPU represented by
20530a996fbSRafael J. Wysocki  * @dev is idle and it can try to enter the idle state corresponding to @index.
20630a996fbSRafael J. Wysocki  *
20730a996fbSRafael J. Wysocki  * Invoked as a suspend-to-idle callback routine with frozen user space, frozen
20830a996fbSRafael J. Wysocki  * scheduler tick and suspended scheduler clock on the target CPU.
20930a996fbSRafael J. Wysocki  */
intel_idle_s2idle(struct cpuidle_device * dev,struct cpuidle_driver * drv,int index)210efe97112SNeal Liu static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev,
21130a996fbSRafael J. Wysocki 				       struct cpuidle_driver *drv, int index)
21230a996fbSRafael J. Wysocki {
21330a996fbSRafael J. Wysocki 	unsigned long ecx = 1; /* break on interrupt flag */
2149f011293SChang S. Bae 	struct cpuidle_state *state = &drv->states[index];
2159f011293SChang S. Bae 	unsigned long eax = flg2MWAIT(state->flags);
2169f011293SChang S. Bae 
2179f011293SChang S. Bae 	if (state->flags & CPUIDLE_FLAG_INIT_XSTATE)
2189f011293SChang S. Bae 		fpu_idle_fpregs();
21930a996fbSRafael J. Wysocki 
22030a996fbSRafael J. Wysocki 	mwait_idle_with_hints(eax, ecx);
221efe97112SNeal Liu 
222efe97112SNeal Liu 	return 0;
22330a996fbSRafael J. Wysocki }
22430a996fbSRafael J. Wysocki 
225b1beab48SLen Brown /*
22626717172SLen Brown  * States are indexed by the cstate number,
22726717172SLen Brown  * which is also the index into the MWAIT hint array.
22826717172SLen Brown  * Thus C0 is a dummy.
22926717172SLen Brown  */
230ab1a8522SRafael J. Wysocki static struct cpuidle_state nehalem_cstates[] __initdata = {
231e022e7ebSLen Brown 	{
232de09cdd0SLen Brown 		.name = "C1",
23326717172SLen Brown 		.desc = "MWAIT 0x00",
234b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
23526717172SLen Brown 		.exit_latency = 3,
23626717172SLen Brown 		.target_residency = 6,
2375fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
23828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
239e022e7ebSLen Brown 	{
240de09cdd0SLen Brown 		.name = "C1E",
24132e95180SLen Brown 		.desc = "MWAIT 0x01",
242e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
24332e95180SLen Brown 		.exit_latency = 10,
24432e95180SLen Brown 		.target_residency = 20,
2455fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
24628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
24732e95180SLen Brown 	{
248de09cdd0SLen Brown 		.name = "C3",
24926717172SLen Brown 		.desc = "MWAIT 0x10",
250b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
25126717172SLen Brown 		.exit_latency = 20,
25226717172SLen Brown 		.target_residency = 80,
2535fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
25428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
255e022e7ebSLen Brown 	{
256de09cdd0SLen Brown 		.name = "C6",
25726717172SLen Brown 		.desc = "MWAIT 0x20",
258b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
25926717172SLen Brown 		.exit_latency = 200,
26026717172SLen Brown 		.target_residency = 800,
2615fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
26228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
263e022e7ebSLen Brown 	{
264e022e7ebSLen Brown 		.enter = NULL }
26526717172SLen Brown };
26626717172SLen Brown 
267ab1a8522SRafael J. Wysocki static struct cpuidle_state snb_cstates[] __initdata = {
268e022e7ebSLen Brown 	{
269de09cdd0SLen Brown 		.name = "C1",
270d13780d4SLen Brown 		.desc = "MWAIT 0x00",
271b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
27232e95180SLen Brown 		.exit_latency = 2,
27332e95180SLen Brown 		.target_residency = 2,
2745fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
27528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
27632e95180SLen Brown 	{
277de09cdd0SLen Brown 		.name = "C1E",
27832e95180SLen Brown 		.desc = "MWAIT 0x01",
279e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
28032e95180SLen Brown 		.exit_latency = 10,
28132e95180SLen Brown 		.target_residency = 20,
2825fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
28328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
284e022e7ebSLen Brown 	{
285de09cdd0SLen Brown 		.name = "C3",
286d13780d4SLen Brown 		.desc = "MWAIT 0x10",
287b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
288d13780d4SLen Brown 		.exit_latency = 80,
289ddbd550dSLen Brown 		.target_residency = 211,
2905fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
29128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
292e022e7ebSLen Brown 	{
293de09cdd0SLen Brown 		.name = "C6",
294d13780d4SLen Brown 		.desc = "MWAIT 0x20",
295b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
296d13780d4SLen Brown 		.exit_latency = 104,
297ddbd550dSLen Brown 		.target_residency = 345,
2985fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
29928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
300e022e7ebSLen Brown 	{
301de09cdd0SLen Brown 		.name = "C7",
302d13780d4SLen Brown 		.desc = "MWAIT 0x30",
303b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
304d13780d4SLen Brown 		.exit_latency = 109,
305ddbd550dSLen Brown 		.target_residency = 345,
3065fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
30728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
308e022e7ebSLen Brown 	{
309e022e7ebSLen Brown 		.enter = NULL }
310d13780d4SLen Brown };
311d13780d4SLen Brown 
312ab1a8522SRafael J. Wysocki static struct cpuidle_state byt_cstates[] __initdata = {
313718987d6SLen Brown 	{
314de09cdd0SLen Brown 		.name = "C1",
315718987d6SLen Brown 		.desc = "MWAIT 0x00",
316b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
317718987d6SLen Brown 		.exit_latency = 1,
318718987d6SLen Brown 		.target_residency = 1,
3195fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
32028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
321718987d6SLen Brown 	{
322de09cdd0SLen Brown 		.name = "C6N",
323718987d6SLen Brown 		.desc = "MWAIT 0x58",
324b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
325d7ef7671SLen Brown 		.exit_latency = 300,
326718987d6SLen Brown 		.target_residency = 275,
3275fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
32828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
329718987d6SLen Brown 	{
330de09cdd0SLen Brown 		.name = "C6S",
331718987d6SLen Brown 		.desc = "MWAIT 0x52",
332b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
333d7ef7671SLen Brown 		.exit_latency = 500,
334718987d6SLen Brown 		.target_residency = 560,
3355fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
33628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
337718987d6SLen Brown 	{
338de09cdd0SLen Brown 		.name = "C7",
339718987d6SLen Brown 		.desc = "MWAIT 0x60",
340b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
341718987d6SLen Brown 		.exit_latency = 1200,
342d7ef7671SLen Brown 		.target_residency = 4000,
3435fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
34428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
345718987d6SLen Brown 	{
346de09cdd0SLen Brown 		.name = "C7S",
347718987d6SLen Brown 		.desc = "MWAIT 0x64",
348b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
349718987d6SLen Brown 		.exit_latency = 10000,
350718987d6SLen Brown 		.target_residency = 20000,
3515fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
35228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
353718987d6SLen Brown 	{
354718987d6SLen Brown 		.enter = NULL }
355718987d6SLen Brown };
356718987d6SLen Brown 
357ab1a8522SRafael J. Wysocki static struct cpuidle_state cht_cstates[] __initdata = {
358cab07a56SLen Brown 	{
359de09cdd0SLen Brown 		.name = "C1",
360cab07a56SLen Brown 		.desc = "MWAIT 0x00",
361cab07a56SLen Brown 		.flags = MWAIT2flg(0x00),
362cab07a56SLen Brown 		.exit_latency = 1,
363cab07a56SLen Brown 		.target_residency = 1,
364cab07a56SLen Brown 		.enter = &intel_idle,
36528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
366cab07a56SLen Brown 	{
367de09cdd0SLen Brown 		.name = "C6N",
368cab07a56SLen Brown 		.desc = "MWAIT 0x58",
369cab07a56SLen Brown 		.flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED,
370cab07a56SLen Brown 		.exit_latency = 80,
371cab07a56SLen Brown 		.target_residency = 275,
372cab07a56SLen Brown 		.enter = &intel_idle,
37328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
374cab07a56SLen Brown 	{
375de09cdd0SLen Brown 		.name = "C6S",
376cab07a56SLen Brown 		.desc = "MWAIT 0x52",
377cab07a56SLen Brown 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
378cab07a56SLen Brown 		.exit_latency = 200,
379cab07a56SLen Brown 		.target_residency = 560,
380cab07a56SLen Brown 		.enter = &intel_idle,
38128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
382cab07a56SLen Brown 	{
383de09cdd0SLen Brown 		.name = "C7",
384cab07a56SLen Brown 		.desc = "MWAIT 0x60",
385cab07a56SLen Brown 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
386cab07a56SLen Brown 		.exit_latency = 1200,
387cab07a56SLen Brown 		.target_residency = 4000,
388cab07a56SLen Brown 		.enter = &intel_idle,
38928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
390cab07a56SLen Brown 	{
391de09cdd0SLen Brown 		.name = "C7S",
392cab07a56SLen Brown 		.desc = "MWAIT 0x64",
393cab07a56SLen Brown 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
394cab07a56SLen Brown 		.exit_latency = 10000,
395cab07a56SLen Brown 		.target_residency = 20000,
396cab07a56SLen Brown 		.enter = &intel_idle,
39728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
398cab07a56SLen Brown 	{
399cab07a56SLen Brown 		.enter = NULL }
400cab07a56SLen Brown };
401cab07a56SLen Brown 
402ab1a8522SRafael J. Wysocki static struct cpuidle_state ivb_cstates[] __initdata = {
403e022e7ebSLen Brown 	{
404de09cdd0SLen Brown 		.name = "C1",
4056edab08cSLen Brown 		.desc = "MWAIT 0x00",
406b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
4076edab08cSLen Brown 		.exit_latency = 1,
4086edab08cSLen Brown 		.target_residency = 1,
4095fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
41028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
411e022e7ebSLen Brown 	{
412de09cdd0SLen Brown 		.name = "C1E",
41332e95180SLen Brown 		.desc = "MWAIT 0x01",
414e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
41532e95180SLen Brown 		.exit_latency = 10,
41632e95180SLen Brown 		.target_residency = 20,
4175fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
41828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
41932e95180SLen Brown 	{
420de09cdd0SLen Brown 		.name = "C3",
4216edab08cSLen Brown 		.desc = "MWAIT 0x10",
422b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
4236edab08cSLen Brown 		.exit_latency = 59,
4246edab08cSLen Brown 		.target_residency = 156,
4255fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
42628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
427e022e7ebSLen Brown 	{
428de09cdd0SLen Brown 		.name = "C6",
4296edab08cSLen Brown 		.desc = "MWAIT 0x20",
430b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
4316edab08cSLen Brown 		.exit_latency = 80,
4326edab08cSLen Brown 		.target_residency = 300,
4335fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
43428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
435e022e7ebSLen Brown 	{
436de09cdd0SLen Brown 		.name = "C7",
4376edab08cSLen Brown 		.desc = "MWAIT 0x30",
438b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
4396edab08cSLen Brown 		.exit_latency = 87,
4406edab08cSLen Brown 		.target_residency = 300,
4415fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
44228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
443e022e7ebSLen Brown 	{
444e022e7ebSLen Brown 		.enter = NULL }
4456edab08cSLen Brown };
4466edab08cSLen Brown 
447ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates[] __initdata = {
4480138d8f0SLen Brown 	{
449de09cdd0SLen Brown 		.name = "C1",
4500138d8f0SLen Brown 		.desc = "MWAIT 0x00",
451b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
4520138d8f0SLen Brown 		.exit_latency = 1,
4530138d8f0SLen Brown 		.target_residency = 1,
4545fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
45528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4560138d8f0SLen Brown 	{
457de09cdd0SLen Brown 		.name = "C1E",
4580138d8f0SLen Brown 		.desc = "MWAIT 0x01",
459e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
4600138d8f0SLen Brown 		.exit_latency = 10,
4610138d8f0SLen Brown 		.target_residency = 80,
4625fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
46328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4640138d8f0SLen Brown 	{
465de09cdd0SLen Brown 		.name = "C3",
4660138d8f0SLen Brown 		.desc = "MWAIT 0x10",
467b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
4680138d8f0SLen Brown 		.exit_latency = 59,
4690138d8f0SLen Brown 		.target_residency = 156,
4705fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
47128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4720138d8f0SLen Brown 	{
473de09cdd0SLen Brown 		.name = "C6",
4740138d8f0SLen Brown 		.desc = "MWAIT 0x20",
475b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
4760138d8f0SLen Brown 		.exit_latency = 82,
4770138d8f0SLen Brown 		.target_residency = 300,
4785fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
47928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4800138d8f0SLen Brown 	{
4810138d8f0SLen Brown 		.enter = NULL }
4820138d8f0SLen Brown };
4830138d8f0SLen Brown 
484ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates_4s[] __initdata = {
4850138d8f0SLen Brown 	{
486de09cdd0SLen Brown 		.name = "C1",
4870138d8f0SLen Brown 		.desc = "MWAIT 0x00",
488b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
4890138d8f0SLen Brown 		.exit_latency = 1,
4900138d8f0SLen Brown 		.target_residency = 1,
4915fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
49228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
4930138d8f0SLen Brown 	{
494de09cdd0SLen Brown 		.name = "C1E",
4950138d8f0SLen Brown 		.desc = "MWAIT 0x01",
496e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
4970138d8f0SLen Brown 		.exit_latency = 10,
4980138d8f0SLen Brown 		.target_residency = 250,
4995fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
50028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5010138d8f0SLen Brown 	{
502de09cdd0SLen Brown 		.name = "C3",
5030138d8f0SLen Brown 		.desc = "MWAIT 0x10",
504b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
5050138d8f0SLen Brown 		.exit_latency = 59,
5060138d8f0SLen Brown 		.target_residency = 300,
5075fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
50828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5090138d8f0SLen Brown 	{
510de09cdd0SLen Brown 		.name = "C6",
5110138d8f0SLen Brown 		.desc = "MWAIT 0x20",
512b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
5130138d8f0SLen Brown 		.exit_latency = 84,
5140138d8f0SLen Brown 		.target_residency = 400,
5155fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
51628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5170138d8f0SLen Brown 	{
5180138d8f0SLen Brown 		.enter = NULL }
5190138d8f0SLen Brown };
5200138d8f0SLen Brown 
521ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates_8s[] __initdata = {
5220138d8f0SLen Brown 	{
523de09cdd0SLen Brown 		.name = "C1",
5240138d8f0SLen Brown 		.desc = "MWAIT 0x00",
525b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
5260138d8f0SLen Brown 		.exit_latency = 1,
5270138d8f0SLen Brown 		.target_residency = 1,
5285fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
52928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5300138d8f0SLen Brown 	{
531de09cdd0SLen Brown 		.name = "C1E",
5320138d8f0SLen Brown 		.desc = "MWAIT 0x01",
533e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
5340138d8f0SLen Brown 		.exit_latency = 10,
5350138d8f0SLen Brown 		.target_residency = 500,
5365fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
53728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5380138d8f0SLen Brown 	{
539de09cdd0SLen Brown 		.name = "C3",
5400138d8f0SLen Brown 		.desc = "MWAIT 0x10",
541b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
5420138d8f0SLen Brown 		.exit_latency = 59,
5430138d8f0SLen Brown 		.target_residency = 600,
5445fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
54528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5460138d8f0SLen Brown 	{
547de09cdd0SLen Brown 		.name = "C6",
5480138d8f0SLen Brown 		.desc = "MWAIT 0x20",
549b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
5500138d8f0SLen Brown 		.exit_latency = 88,
5510138d8f0SLen Brown 		.target_residency = 700,
5525fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
55328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
5540138d8f0SLen Brown 	{
5550138d8f0SLen Brown 		.enter = NULL }
5560138d8f0SLen Brown };
5570138d8f0SLen Brown 
558ab1a8522SRafael J. Wysocki static struct cpuidle_state hsw_cstates[] __initdata = {
559e022e7ebSLen Brown 	{
560de09cdd0SLen Brown 		.name = "C1",
56185a4d2d4SLen Brown 		.desc = "MWAIT 0x00",
562b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
56385a4d2d4SLen Brown 		.exit_latency = 2,
56485a4d2d4SLen Brown 		.target_residency = 2,
5655fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
56628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
567e022e7ebSLen Brown 	{
568de09cdd0SLen Brown 		.name = "C1E",
56932e95180SLen Brown 		.desc = "MWAIT 0x01",
570e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
57132e95180SLen Brown 		.exit_latency = 10,
57232e95180SLen Brown 		.target_residency = 20,
5735fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
57428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
57532e95180SLen Brown 	{
576de09cdd0SLen Brown 		.name = "C3",
57785a4d2d4SLen Brown 		.desc = "MWAIT 0x10",
578b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
57985a4d2d4SLen Brown 		.exit_latency = 33,
58085a4d2d4SLen Brown 		.target_residency = 100,
5815fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
58228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
583e022e7ebSLen Brown 	{
584de09cdd0SLen Brown 		.name = "C6",
58585a4d2d4SLen Brown 		.desc = "MWAIT 0x20",
586b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
58785a4d2d4SLen Brown 		.exit_latency = 133,
58885a4d2d4SLen Brown 		.target_residency = 400,
5895fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
59028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
591e022e7ebSLen Brown 	{
592de09cdd0SLen Brown 		.name = "C7s",
59385a4d2d4SLen Brown 		.desc = "MWAIT 0x32",
594b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
59585a4d2d4SLen Brown 		.exit_latency = 166,
59685a4d2d4SLen Brown 		.target_residency = 500,
5975fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
59828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
599e022e7ebSLen Brown 	{
600de09cdd0SLen Brown 		.name = "C8",
60186239cebSLen Brown 		.desc = "MWAIT 0x40",
602b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
60386239cebSLen Brown 		.exit_latency = 300,
60486239cebSLen Brown 		.target_residency = 900,
6055fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
60628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
60786239cebSLen Brown 	{
608de09cdd0SLen Brown 		.name = "C9",
60986239cebSLen Brown 		.desc = "MWAIT 0x50",
610b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
61186239cebSLen Brown 		.exit_latency = 600,
61286239cebSLen Brown 		.target_residency = 1800,
6135fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
61428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
61586239cebSLen Brown 	{
616de09cdd0SLen Brown 		.name = "C10",
61786239cebSLen Brown 		.desc = "MWAIT 0x60",
618b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
61986239cebSLen Brown 		.exit_latency = 2600,
62086239cebSLen Brown 		.target_residency = 7700,
6215fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
62228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
62386239cebSLen Brown 	{
624e022e7ebSLen Brown 		.enter = NULL }
62585a4d2d4SLen Brown };
626ab1a8522SRafael J. Wysocki static struct cpuidle_state bdw_cstates[] __initdata = {
627a138b568SLen Brown 	{
628de09cdd0SLen Brown 		.name = "C1",
629a138b568SLen Brown 		.desc = "MWAIT 0x00",
630b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
631a138b568SLen Brown 		.exit_latency = 2,
632a138b568SLen Brown 		.target_residency = 2,
6335fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
63428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
635a138b568SLen Brown 	{
636de09cdd0SLen Brown 		.name = "C1E",
637a138b568SLen Brown 		.desc = "MWAIT 0x01",
638e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
639a138b568SLen Brown 		.exit_latency = 10,
640a138b568SLen Brown 		.target_residency = 20,
6415fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
64228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
643a138b568SLen Brown 	{
644de09cdd0SLen Brown 		.name = "C3",
645a138b568SLen Brown 		.desc = "MWAIT 0x10",
646b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
647a138b568SLen Brown 		.exit_latency = 40,
648a138b568SLen Brown 		.target_residency = 100,
6495fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
65028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
651a138b568SLen Brown 	{
652de09cdd0SLen Brown 		.name = "C6",
653a138b568SLen Brown 		.desc = "MWAIT 0x20",
654b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
655a138b568SLen Brown 		.exit_latency = 133,
656a138b568SLen Brown 		.target_residency = 400,
6575fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
65828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
659a138b568SLen Brown 	{
660de09cdd0SLen Brown 		.name = "C7s",
661a138b568SLen Brown 		.desc = "MWAIT 0x32",
662b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED,
663a138b568SLen Brown 		.exit_latency = 166,
664a138b568SLen Brown 		.target_residency = 500,
6655fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
66628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
667a138b568SLen Brown 	{
668de09cdd0SLen Brown 		.name = "C8",
669a138b568SLen Brown 		.desc = "MWAIT 0x40",
670b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
671a138b568SLen Brown 		.exit_latency = 300,
672a138b568SLen Brown 		.target_residency = 900,
6735fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
67428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
675a138b568SLen Brown 	{
676de09cdd0SLen Brown 		.name = "C9",
677a138b568SLen Brown 		.desc = "MWAIT 0x50",
678b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
679a138b568SLen Brown 		.exit_latency = 600,
680a138b568SLen Brown 		.target_residency = 1800,
6815fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
68228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
683a138b568SLen Brown 	{
684de09cdd0SLen Brown 		.name = "C10",
685a138b568SLen Brown 		.desc = "MWAIT 0x60",
686b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
687a138b568SLen Brown 		.exit_latency = 2600,
688a138b568SLen Brown 		.target_residency = 7700,
6895fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
69028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
691a138b568SLen Brown 	{
692a138b568SLen Brown 		.enter = NULL }
693a138b568SLen Brown };
69485a4d2d4SLen Brown 
695ab1a8522SRafael J. Wysocki static struct cpuidle_state skl_cstates[] __initdata = {
696493f133fSLen Brown 	{
697de09cdd0SLen Brown 		.name = "C1",
698493f133fSLen Brown 		.desc = "MWAIT 0x00",
699493f133fSLen Brown 		.flags = MWAIT2flg(0x00),
700493f133fSLen Brown 		.exit_latency = 2,
701493f133fSLen Brown 		.target_residency = 2,
702493f133fSLen Brown 		.enter = &intel_idle,
70328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
704493f133fSLen Brown 	{
705de09cdd0SLen Brown 		.name = "C1E",
706493f133fSLen Brown 		.desc = "MWAIT 0x01",
707e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
708493f133fSLen Brown 		.exit_latency = 10,
709493f133fSLen Brown 		.target_residency = 20,
710493f133fSLen Brown 		.enter = &intel_idle,
71128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
712493f133fSLen Brown 	{
713de09cdd0SLen Brown 		.name = "C3",
714493f133fSLen Brown 		.desc = "MWAIT 0x10",
715493f133fSLen Brown 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
716493f133fSLen Brown 		.exit_latency = 70,
717493f133fSLen Brown 		.target_residency = 100,
718493f133fSLen Brown 		.enter = &intel_idle,
71928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
720493f133fSLen Brown 	{
721de09cdd0SLen Brown 		.name = "C6",
722493f133fSLen Brown 		.desc = "MWAIT 0x20",
723bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
724135919a3SLen Brown 		.exit_latency = 85,
725493f133fSLen Brown 		.target_residency = 200,
726493f133fSLen Brown 		.enter = &intel_idle,
72728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
728493f133fSLen Brown 	{
729de09cdd0SLen Brown 		.name = "C7s",
730493f133fSLen Brown 		.desc = "MWAIT 0x33",
731bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x33) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
732493f133fSLen Brown 		.exit_latency = 124,
733493f133fSLen Brown 		.target_residency = 800,
734493f133fSLen Brown 		.enter = &intel_idle,
73528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
736493f133fSLen Brown 	{
737de09cdd0SLen Brown 		.name = "C8",
738493f133fSLen Brown 		.desc = "MWAIT 0x40",
739bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
740135919a3SLen Brown 		.exit_latency = 200,
741493f133fSLen Brown 		.target_residency = 800,
742493f133fSLen Brown 		.enter = &intel_idle,
74328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
744493f133fSLen Brown 	{
745de09cdd0SLen Brown 		.name = "C9",
746135919a3SLen Brown 		.desc = "MWAIT 0x50",
747bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
748135919a3SLen Brown 		.exit_latency = 480,
749135919a3SLen Brown 		.target_residency = 5000,
750135919a3SLen Brown 		.enter = &intel_idle,
75128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
752135919a3SLen Brown 	{
753de09cdd0SLen Brown 		.name = "C10",
754493f133fSLen Brown 		.desc = "MWAIT 0x60",
755bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
756493f133fSLen Brown 		.exit_latency = 890,
757493f133fSLen Brown 		.target_residency = 5000,
758493f133fSLen Brown 		.enter = &intel_idle,
75928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
760493f133fSLen Brown 	{
761493f133fSLen Brown 		.enter = NULL }
762493f133fSLen Brown };
763493f133fSLen Brown 
764ab1a8522SRafael J. Wysocki static struct cpuidle_state skx_cstates[] __initdata = {
765f9e71657SLen Brown 	{
766de09cdd0SLen Brown 		.name = "C1",
767f9e71657SLen Brown 		.desc = "MWAIT 0x00",
768c227233aSArtem Bityutskiy 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
769f9e71657SLen Brown 		.exit_latency = 2,
770f9e71657SLen Brown 		.target_residency = 2,
771f9e71657SLen Brown 		.enter = &intel_idle,
77228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
773f9e71657SLen Brown 	{
774de09cdd0SLen Brown 		.name = "C1E",
775f9e71657SLen Brown 		.desc = "MWAIT 0x01",
776e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
777f9e71657SLen Brown 		.exit_latency = 10,
778f9e71657SLen Brown 		.target_residency = 20,
779f9e71657SLen Brown 		.enter = &intel_idle,
78028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
781f9e71657SLen Brown 	{
782de09cdd0SLen Brown 		.name = "C6",
783f9e71657SLen Brown 		.desc = "MWAIT 0x20",
784bf5835bcSPeter Zijlstra 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
785f9e71657SLen Brown 		.exit_latency = 133,
786f9e71657SLen Brown 		.target_residency = 600,
787f9e71657SLen Brown 		.enter = &intel_idle,
78828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
789f9e71657SLen Brown 	{
790f9e71657SLen Brown 		.enter = NULL }
791f9e71657SLen Brown };
792f9e71657SLen Brown 
793a472ad2bSChen Yu static struct cpuidle_state icx_cstates[] __initdata = {
794a472ad2bSChen Yu 	{
795a472ad2bSChen Yu 		.name = "C1",
796a472ad2bSChen Yu 		.desc = "MWAIT 0x00",
797c227233aSArtem Bityutskiy 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
798a472ad2bSChen Yu 		.exit_latency = 1,
799a472ad2bSChen Yu 		.target_residency = 1,
800a472ad2bSChen Yu 		.enter = &intel_idle,
801a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
802a472ad2bSChen Yu 	{
803a472ad2bSChen Yu 		.name = "C1E",
804a472ad2bSChen Yu 		.desc = "MWAIT 0x01",
805a472ad2bSChen Yu 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
806a472ad2bSChen Yu 		.exit_latency = 4,
807a472ad2bSChen Yu 		.target_residency = 4,
808a472ad2bSChen Yu 		.enter = &intel_idle,
809a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
810a472ad2bSChen Yu 	{
811a472ad2bSChen Yu 		.name = "C6",
812a472ad2bSChen Yu 		.desc = "MWAIT 0x20",
813a472ad2bSChen Yu 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
814d484b8bfSArtem Bityutskiy 		.exit_latency = 170,
815d484b8bfSArtem Bityutskiy 		.target_residency = 600,
816a472ad2bSChen Yu 		.enter = &intel_idle,
817a472ad2bSChen Yu 		.enter_s2idle = intel_idle_s2idle, },
818a472ad2bSChen Yu 	{
819a472ad2bSChen Yu 		.enter = NULL }
820a472ad2bSChen Yu };
821a472ad2bSChen Yu 
8229edf3c0fSArtem Bityutskiy /*
823d1cf8bbfSZhang Rui  * On AlderLake C1 has to be disabled if C1E is enabled, and vice versa.
824d1cf8bbfSZhang Rui  * C1E is enabled only if "C1E promotion" bit is set in MSR_IA32_POWER_CTL.
825d1cf8bbfSZhang Rui  * But in this case there is effectively no C1, because C1 requests are
826d1cf8bbfSZhang Rui  * promoted to C1E. If the "C1E promotion" bit is cleared, then both C1
827d1cf8bbfSZhang Rui  * and C1E requests end up with C1, so there is effectively no C1E.
828d1cf8bbfSZhang Rui  *
829d1cf8bbfSZhang Rui  * By default we enable C1E and disable C1 by marking it with
830d1cf8bbfSZhang Rui  * 'CPUIDLE_FLAG_UNUSABLE'.
831d1cf8bbfSZhang Rui  */
832d1cf8bbfSZhang Rui static struct cpuidle_state adl_cstates[] __initdata = {
833d1cf8bbfSZhang Rui 	{
834d1cf8bbfSZhang Rui 		.name = "C1",
835d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x00",
836d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
837d1cf8bbfSZhang Rui 		.exit_latency = 1,
838d1cf8bbfSZhang Rui 		.target_residency = 1,
839d1cf8bbfSZhang Rui 		.enter = &intel_idle,
840d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
841d1cf8bbfSZhang Rui 	{
842d1cf8bbfSZhang Rui 		.name = "C1E",
843d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x01",
844d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
845d1cf8bbfSZhang Rui 		.exit_latency = 2,
846d1cf8bbfSZhang Rui 		.target_residency = 4,
847d1cf8bbfSZhang Rui 		.enter = &intel_idle,
848d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
849d1cf8bbfSZhang Rui 	{
850d1cf8bbfSZhang Rui 		.name = "C6",
851d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x20",
852d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
853d1cf8bbfSZhang Rui 		.exit_latency = 220,
854d1cf8bbfSZhang Rui 		.target_residency = 600,
855d1cf8bbfSZhang Rui 		.enter = &intel_idle,
856d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
857d1cf8bbfSZhang Rui 	{
858d1cf8bbfSZhang Rui 		.name = "C8",
859d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x40",
860d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
861d1cf8bbfSZhang Rui 		.exit_latency = 280,
862d1cf8bbfSZhang Rui 		.target_residency = 800,
863d1cf8bbfSZhang Rui 		.enter = &intel_idle,
864d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
865d1cf8bbfSZhang Rui 	{
866d1cf8bbfSZhang Rui 		.name = "C10",
867d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x60",
868d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
869d1cf8bbfSZhang Rui 		.exit_latency = 680,
870d1cf8bbfSZhang Rui 		.target_residency = 2000,
871d1cf8bbfSZhang Rui 		.enter = &intel_idle,
872d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
873d1cf8bbfSZhang Rui 	{
874d1cf8bbfSZhang Rui 		.enter = NULL }
875d1cf8bbfSZhang Rui };
876d1cf8bbfSZhang Rui 
877d1cf8bbfSZhang Rui static struct cpuidle_state adl_l_cstates[] __initdata = {
878d1cf8bbfSZhang Rui 	{
879d1cf8bbfSZhang Rui 		.name = "C1",
880d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x00",
881d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
882d1cf8bbfSZhang Rui 		.exit_latency = 1,
883d1cf8bbfSZhang Rui 		.target_residency = 1,
884d1cf8bbfSZhang Rui 		.enter = &intel_idle,
885d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
886d1cf8bbfSZhang Rui 	{
887d1cf8bbfSZhang Rui 		.name = "C1E",
888d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x01",
889d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
890d1cf8bbfSZhang Rui 		.exit_latency = 2,
891d1cf8bbfSZhang Rui 		.target_residency = 4,
892d1cf8bbfSZhang Rui 		.enter = &intel_idle,
893d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
894d1cf8bbfSZhang Rui 	{
895d1cf8bbfSZhang Rui 		.name = "C6",
896d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x20",
897d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
898d1cf8bbfSZhang Rui 		.exit_latency = 170,
899d1cf8bbfSZhang Rui 		.target_residency = 500,
900d1cf8bbfSZhang Rui 		.enter = &intel_idle,
901d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
902d1cf8bbfSZhang Rui 	{
903d1cf8bbfSZhang Rui 		.name = "C8",
904d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x40",
905d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
906d1cf8bbfSZhang Rui 		.exit_latency = 200,
907d1cf8bbfSZhang Rui 		.target_residency = 600,
908d1cf8bbfSZhang Rui 		.enter = &intel_idle,
909d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
910d1cf8bbfSZhang Rui 	{
911d1cf8bbfSZhang Rui 		.name = "C10",
912d1cf8bbfSZhang Rui 		.desc = "MWAIT 0x60",
913d1cf8bbfSZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
914d1cf8bbfSZhang Rui 		.exit_latency = 230,
915d1cf8bbfSZhang Rui 		.target_residency = 700,
916d1cf8bbfSZhang Rui 		.enter = &intel_idle,
917d1cf8bbfSZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
918d1cf8bbfSZhang Rui 	{
919d1cf8bbfSZhang Rui 		.enter = NULL }
920d1cf8bbfSZhang Rui };
921d1cf8bbfSZhang Rui 
922882cdb06SPeter Zijlstra static struct cpuidle_state gmt_cstates[] __initdata = {
92365c0c236SZhang Rui 	{
92465c0c236SZhang Rui 		.name = "C1",
92565c0c236SZhang Rui 		.desc = "MWAIT 0x00",
92665c0c236SZhang Rui 		.flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
92765c0c236SZhang Rui 		.exit_latency = 1,
92865c0c236SZhang Rui 		.target_residency = 1,
92965c0c236SZhang Rui 		.enter = &intel_idle,
93065c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
93165c0c236SZhang Rui 	{
93265c0c236SZhang Rui 		.name = "C1E",
93365c0c236SZhang Rui 		.desc = "MWAIT 0x01",
93465c0c236SZhang Rui 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
93565c0c236SZhang Rui 		.exit_latency = 2,
93665c0c236SZhang Rui 		.target_residency = 4,
93765c0c236SZhang Rui 		.enter = &intel_idle,
93865c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
93965c0c236SZhang Rui 	{
94065c0c236SZhang Rui 		.name = "C6",
94165c0c236SZhang Rui 		.desc = "MWAIT 0x20",
94265c0c236SZhang Rui 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
94365c0c236SZhang Rui 		.exit_latency = 195,
94465c0c236SZhang Rui 		.target_residency = 585,
94565c0c236SZhang Rui 		.enter = &intel_idle,
94665c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
94765c0c236SZhang Rui 	{
94865c0c236SZhang Rui 		.name = "C8",
94965c0c236SZhang Rui 		.desc = "MWAIT 0x40",
95065c0c236SZhang Rui 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
95165c0c236SZhang Rui 		.exit_latency = 260,
95265c0c236SZhang Rui 		.target_residency = 1040,
95365c0c236SZhang Rui 		.enter = &intel_idle,
95465c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
95565c0c236SZhang Rui 	{
95665c0c236SZhang Rui 		.name = "C10",
95765c0c236SZhang Rui 		.desc = "MWAIT 0x60",
95865c0c236SZhang Rui 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
95965c0c236SZhang Rui 		.exit_latency = 660,
96065c0c236SZhang Rui 		.target_residency = 1980,
96165c0c236SZhang Rui 		.enter = &intel_idle,
96265c0c236SZhang Rui 		.enter_s2idle = intel_idle_s2idle, },
96365c0c236SZhang Rui 	{
96465c0c236SZhang Rui 		.enter = NULL }
96565c0c236SZhang Rui };
96665c0c236SZhang Rui 
9679edf3c0fSArtem Bityutskiy static struct cpuidle_state spr_cstates[] __initdata = {
9689edf3c0fSArtem Bityutskiy 	{
9699edf3c0fSArtem Bityutskiy 		.name = "C1",
9709edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x00",
9719edf3c0fSArtem Bityutskiy 		.flags = MWAIT2flg(0x00),
9729edf3c0fSArtem Bityutskiy 		.exit_latency = 1,
9739edf3c0fSArtem Bityutskiy 		.target_residency = 1,
9749edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
9759edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
9769edf3c0fSArtem Bityutskiy 	{
9779edf3c0fSArtem Bityutskiy 		.name = "C1E",
9789edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x01",
9791548fac4SArtem Bityutskiy 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
9809edf3c0fSArtem Bityutskiy 		.exit_latency = 2,
9819edf3c0fSArtem Bityutskiy 		.target_residency = 4,
9829edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
9839edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
9849edf3c0fSArtem Bityutskiy 	{
9859edf3c0fSArtem Bityutskiy 		.name = "C6",
9869edf3c0fSArtem Bityutskiy 		.desc = "MWAIT 0x20",
9879f011293SChang S. Bae 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED |
9889f011293SChang S. Bae 					   CPUIDLE_FLAG_INIT_XSTATE,
9899edf3c0fSArtem Bityutskiy 		.exit_latency = 290,
9909edf3c0fSArtem Bityutskiy 		.target_residency = 800,
9919edf3c0fSArtem Bityutskiy 		.enter = &intel_idle,
9929edf3c0fSArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
9939edf3c0fSArtem Bityutskiy 	{
9949edf3c0fSArtem Bityutskiy 		.enter = NULL }
9959edf3c0fSArtem Bityutskiy };
9969edf3c0fSArtem Bityutskiy 
997ab1a8522SRafael J. Wysocki static struct cpuidle_state atom_cstates[] __initdata = {
998e022e7ebSLen Brown 	{
999de09cdd0SLen Brown 		.name = "C1E",
100026717172SLen Brown 		.desc = "MWAIT 0x00",
1001b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
100232e95180SLen Brown 		.exit_latency = 10,
100332e95180SLen Brown 		.target_residency = 20,
10045fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
100528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1006e022e7ebSLen Brown 	{
1007de09cdd0SLen Brown 		.name = "C2",
100826717172SLen Brown 		.desc = "MWAIT 0x10",
1009b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x10),
101026717172SLen Brown 		.exit_latency = 20,
101126717172SLen Brown 		.target_residency = 80,
10125fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
101328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1014e022e7ebSLen Brown 	{
1015de09cdd0SLen Brown 		.name = "C4",
101626717172SLen Brown 		.desc = "MWAIT 0x30",
1017b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
101826717172SLen Brown 		.exit_latency = 100,
101926717172SLen Brown 		.target_residency = 400,
10205fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
102128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1022e022e7ebSLen Brown 	{
1023de09cdd0SLen Brown 		.name = "C6",
10247fcca7d9SLen Brown 		.desc = "MWAIT 0x52",
1025b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
10267fcca7d9SLen Brown 		.exit_latency = 140,
10277fcca7d9SLen Brown 		.target_residency = 560,
10285fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
102928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1030e022e7ebSLen Brown 	{
1031e022e7ebSLen Brown 		.enter = NULL }
103226717172SLen Brown };
1033ab1a8522SRafael J. Wysocki static struct cpuidle_state tangier_cstates[] __initdata = {
10345e7ec268SAndy Shevchenko 	{
1035de09cdd0SLen Brown 		.name = "C1",
10365e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x00",
10375e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x00),
10385e7ec268SAndy Shevchenko 		.exit_latency = 1,
10395e7ec268SAndy Shevchenko 		.target_residency = 4,
10405e7ec268SAndy Shevchenko 		.enter = &intel_idle,
104128ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10425e7ec268SAndy Shevchenko 	{
1043de09cdd0SLen Brown 		.name = "C4",
10445e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x30",
10455e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
10465e7ec268SAndy Shevchenko 		.exit_latency = 100,
10475e7ec268SAndy Shevchenko 		.target_residency = 400,
10485e7ec268SAndy Shevchenko 		.enter = &intel_idle,
104928ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10505e7ec268SAndy Shevchenko 	{
1051de09cdd0SLen Brown 		.name = "C6",
10525e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x52",
10535e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
10545e7ec268SAndy Shevchenko 		.exit_latency = 140,
10555e7ec268SAndy Shevchenko 		.target_residency = 560,
10565e7ec268SAndy Shevchenko 		.enter = &intel_idle,
105728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10585e7ec268SAndy Shevchenko 	{
1059de09cdd0SLen Brown 		.name = "C7",
10605e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x60",
10615e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
10625e7ec268SAndy Shevchenko 		.exit_latency = 1200,
10635e7ec268SAndy Shevchenko 		.target_residency = 4000,
10645e7ec268SAndy Shevchenko 		.enter = &intel_idle,
106528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10665e7ec268SAndy Shevchenko 	{
1067de09cdd0SLen Brown 		.name = "C9",
10685e7ec268SAndy Shevchenko 		.desc = "MWAIT 0x64",
10695e7ec268SAndy Shevchenko 		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
10705e7ec268SAndy Shevchenko 		.exit_latency = 10000,
10715e7ec268SAndy Shevchenko 		.target_residency = 20000,
10725e7ec268SAndy Shevchenko 		.enter = &intel_idle,
107328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
10745e7ec268SAndy Shevchenko 	{
10755e7ec268SAndy Shevchenko 		.enter = NULL }
10765e7ec268SAndy Shevchenko };
1077ab1a8522SRafael J. Wysocki static struct cpuidle_state avn_cstates[] __initdata = {
1078fab04b22SLen Brown 	{
1079de09cdd0SLen Brown 		.name = "C1",
1080fab04b22SLen Brown 		.desc = "MWAIT 0x00",
1081b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x00),
1082fab04b22SLen Brown 		.exit_latency = 2,
1083fab04b22SLen Brown 		.target_residency = 2,
10845fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
108528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
1086fab04b22SLen Brown 	{
1087de09cdd0SLen Brown 		.name = "C6",
1088fab04b22SLen Brown 		.desc = "MWAIT 0x51",
1089b82b6ccaSDaniel Lezcano 		.flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED,
1090fab04b22SLen Brown 		.exit_latency = 15,
1091fab04b22SLen Brown 		.target_residency = 45,
10925fe2e527SRafael J. Wysocki 		.enter = &intel_idle,
109328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
109488390996SJiang Liu 	{
109588390996SJiang Liu 		.enter = NULL }
1096fab04b22SLen Brown };
1097ab1a8522SRafael J. Wysocki static struct cpuidle_state knl_cstates[] __initdata = {
1098281baf7aSDasaratharaman Chandramouli 	{
1099de09cdd0SLen Brown 		.name = "C1",
1100281baf7aSDasaratharaman Chandramouli 		.desc = "MWAIT 0x00",
1101281baf7aSDasaratharaman Chandramouli 		.flags = MWAIT2flg(0x00),
1102281baf7aSDasaratharaman Chandramouli 		.exit_latency = 1,
1103281baf7aSDasaratharaman Chandramouli 		.target_residency = 2,
1104281baf7aSDasaratharaman Chandramouli 		.enter = &intel_idle,
110528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle },
1106281baf7aSDasaratharaman Chandramouli 	{
1107de09cdd0SLen Brown 		.name = "C6",
1108281baf7aSDasaratharaman Chandramouli 		.desc = "MWAIT 0x10",
1109281baf7aSDasaratharaman Chandramouli 		.flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED,
1110281baf7aSDasaratharaman Chandramouli 		.exit_latency = 120,
1111281baf7aSDasaratharaman Chandramouli 		.target_residency = 500,
1112281baf7aSDasaratharaman Chandramouli 		.enter = &intel_idle,
111328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle },
1114281baf7aSDasaratharaman Chandramouli 	{
1115281baf7aSDasaratharaman Chandramouli 		.enter = NULL }
1116281baf7aSDasaratharaman Chandramouli };
111726717172SLen Brown 
1118ab1a8522SRafael J. Wysocki static struct cpuidle_state bxt_cstates[] __initdata = {
11195dcef694SLen Brown 	{
1120de09cdd0SLen Brown 		.name = "C1",
11215dcef694SLen Brown 		.desc = "MWAIT 0x00",
11225dcef694SLen Brown 		.flags = MWAIT2flg(0x00),
11235dcef694SLen Brown 		.exit_latency = 2,
11245dcef694SLen Brown 		.target_residency = 2,
11255dcef694SLen Brown 		.enter = &intel_idle,
112628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11275dcef694SLen Brown 	{
1128de09cdd0SLen Brown 		.name = "C1E",
11295dcef694SLen Brown 		.desc = "MWAIT 0x01",
1130e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
11315dcef694SLen Brown 		.exit_latency = 10,
11325dcef694SLen Brown 		.target_residency = 20,
11335dcef694SLen Brown 		.enter = &intel_idle,
113428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11355dcef694SLen Brown 	{
1136de09cdd0SLen Brown 		.name = "C6",
11375dcef694SLen Brown 		.desc = "MWAIT 0x20",
11385dcef694SLen Brown 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
11395dcef694SLen Brown 		.exit_latency = 133,
11405dcef694SLen Brown 		.target_residency = 133,
11415dcef694SLen Brown 		.enter = &intel_idle,
114228ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11435dcef694SLen Brown 	{
1144de09cdd0SLen Brown 		.name = "C7s",
11455dcef694SLen Brown 		.desc = "MWAIT 0x31",
11465dcef694SLen Brown 		.flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
11475dcef694SLen Brown 		.exit_latency = 155,
11485dcef694SLen Brown 		.target_residency = 155,
11495dcef694SLen Brown 		.enter = &intel_idle,
115028ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11515dcef694SLen Brown 	{
1152de09cdd0SLen Brown 		.name = "C8",
11535dcef694SLen Brown 		.desc = "MWAIT 0x40",
11545dcef694SLen Brown 		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
11555dcef694SLen Brown 		.exit_latency = 1000,
11565dcef694SLen Brown 		.target_residency = 1000,
11575dcef694SLen Brown 		.enter = &intel_idle,
115828ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11595dcef694SLen Brown 	{
1160de09cdd0SLen Brown 		.name = "C9",
11615dcef694SLen Brown 		.desc = "MWAIT 0x50",
11625dcef694SLen Brown 		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
11635dcef694SLen Brown 		.exit_latency = 2000,
11645dcef694SLen Brown 		.target_residency = 2000,
11655dcef694SLen Brown 		.enter = &intel_idle,
116628ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11675dcef694SLen Brown 	{
1168de09cdd0SLen Brown 		.name = "C10",
11695dcef694SLen Brown 		.desc = "MWAIT 0x60",
11705dcef694SLen Brown 		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
11715dcef694SLen Brown 		.exit_latency = 10000,
11725dcef694SLen Brown 		.target_residency = 10000,
11735dcef694SLen Brown 		.enter = &intel_idle,
117428ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11755dcef694SLen Brown 	{
11765dcef694SLen Brown 		.enter = NULL }
11775dcef694SLen Brown };
11785dcef694SLen Brown 
1179ab1a8522SRafael J. Wysocki static struct cpuidle_state dnv_cstates[] __initdata = {
11800080d65bSJacob Pan 	{
1181de09cdd0SLen Brown 		.name = "C1",
11820080d65bSJacob Pan 		.desc = "MWAIT 0x00",
11830080d65bSJacob Pan 		.flags = MWAIT2flg(0x00),
11840080d65bSJacob Pan 		.exit_latency = 2,
11850080d65bSJacob Pan 		.target_residency = 2,
11860080d65bSJacob Pan 		.enter = &intel_idle,
118728ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11880080d65bSJacob Pan 	{
1189de09cdd0SLen Brown 		.name = "C1E",
11900080d65bSJacob Pan 		.desc = "MWAIT 0x01",
1191e6d4f08aSRafael J. Wysocki 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
11920080d65bSJacob Pan 		.exit_latency = 10,
11930080d65bSJacob Pan 		.target_residency = 20,
11940080d65bSJacob Pan 		.enter = &intel_idle,
119528ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
11960080d65bSJacob Pan 	{
1197de09cdd0SLen Brown 		.name = "C6",
11980080d65bSJacob Pan 		.desc = "MWAIT 0x20",
11990080d65bSJacob Pan 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
12000080d65bSJacob Pan 		.exit_latency = 50,
12010080d65bSJacob Pan 		.target_residency = 500,
12020080d65bSJacob Pan 		.enter = &intel_idle,
120328ba086eSRafael J. Wysocki 		.enter_s2idle = intel_idle_s2idle, },
12040080d65bSJacob Pan 	{
12050080d65bSJacob Pan 		.enter = NULL }
12060080d65bSJacob Pan };
12070080d65bSJacob Pan 
12089cf93f05SArtem Bityutskiy /*
12099cf93f05SArtem Bityutskiy  * Note, depending on HW and FW revision, SnowRidge SoC may or may not support
12109cf93f05SArtem Bityutskiy  * C6, and this is indicated in the CPUID mwait leaf.
12119cf93f05SArtem Bityutskiy  */
12129cf93f05SArtem Bityutskiy static struct cpuidle_state snr_cstates[] __initdata = {
12139cf93f05SArtem Bityutskiy 	{
12149cf93f05SArtem Bityutskiy 		.name = "C1",
12159cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x00",
12169cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x00),
12179cf93f05SArtem Bityutskiy 		.exit_latency = 2,
12189cf93f05SArtem Bityutskiy 		.target_residency = 2,
12199cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
12209cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
12219cf93f05SArtem Bityutskiy 	{
12229cf93f05SArtem Bityutskiy 		.name = "C1E",
12239cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x01",
12249cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
12259cf93f05SArtem Bityutskiy 		.exit_latency = 15,
12269cf93f05SArtem Bityutskiy 		.target_residency = 25,
12279cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
12289cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
12299cf93f05SArtem Bityutskiy 	{
12309cf93f05SArtem Bityutskiy 		.name = "C6",
12319cf93f05SArtem Bityutskiy 		.desc = "MWAIT 0x20",
12329cf93f05SArtem Bityutskiy 		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
12339cf93f05SArtem Bityutskiy 		.exit_latency = 130,
12349cf93f05SArtem Bityutskiy 		.target_residency = 500,
12359cf93f05SArtem Bityutskiy 		.enter = &intel_idle,
12369cf93f05SArtem Bityutskiy 		.enter_s2idle = intel_idle_s2idle, },
12379cf93f05SArtem Bityutskiy 	{
12389cf93f05SArtem Bityutskiy 		.enter = NULL }
12399cf93f05SArtem Bityutskiy };
12409cf93f05SArtem Bityutskiy 
1241ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_nehalem __initconst = {
1242b66b8b9aSAndi Kleen 	.state_table = nehalem_cstates,
1243b66b8b9aSAndi Kleen 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
124432e95180SLen Brown 	.disable_promotion_to_c1e = true,
1245b66b8b9aSAndi Kleen };
1246b66b8b9aSAndi Kleen 
1247ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_nhx __initconst = {
1248e6d4f08aSRafael J. Wysocki 	.state_table = nehalem_cstates,
1249e6d4f08aSRafael J. Wysocki 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
1250e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1251e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1252e6d4f08aSRafael J. Wysocki };
1253e6d4f08aSRafael J. Wysocki 
1254ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_atom __initconst = {
1255b66b8b9aSAndi Kleen 	.state_table = atom_cstates,
1256b66b8b9aSAndi Kleen };
1257b66b8b9aSAndi Kleen 
1258ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_tangier __initconst = {
12595e7ec268SAndy Shevchenko 	.state_table = tangier_cstates,
12605e7ec268SAndy Shevchenko };
12615e7ec268SAndy Shevchenko 
1262ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_lincroft __initconst = {
1263b66b8b9aSAndi Kleen 	.state_table = atom_cstates,
1264b66b8b9aSAndi Kleen 	.auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
1265b66b8b9aSAndi Kleen };
1266b66b8b9aSAndi Kleen 
1267ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_snb __initconst = {
1268b66b8b9aSAndi Kleen 	.state_table = snb_cstates,
126932e95180SLen Brown 	.disable_promotion_to_c1e = true,
1270b66b8b9aSAndi Kleen };
1271b66b8b9aSAndi Kleen 
1272ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_snx __initconst = {
1273e6d4f08aSRafael J. Wysocki 	.state_table = snb_cstates,
1274e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1275e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1276e6d4f08aSRafael J. Wysocki };
1277e6d4f08aSRafael J. Wysocki 
1278ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_byt __initconst = {
1279718987d6SLen Brown 	.state_table = byt_cstates,
1280718987d6SLen Brown 	.disable_promotion_to_c1e = true,
12818c058d53SLen Brown 	.byt_auto_demotion_disable_flag = true,
1282718987d6SLen Brown };
1283718987d6SLen Brown 
1284ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_cht __initconst = {
1285cab07a56SLen Brown 	.state_table = cht_cstates,
1286cab07a56SLen Brown 	.disable_promotion_to_c1e = true,
1287cab07a56SLen Brown 	.byt_auto_demotion_disable_flag = true,
1288cab07a56SLen Brown };
1289cab07a56SLen Brown 
1290ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_ivb __initconst = {
12916edab08cSLen Brown 	.state_table = ivb_cstates,
129232e95180SLen Brown 	.disable_promotion_to_c1e = true,
12936edab08cSLen Brown };
12946edab08cSLen Brown 
1295ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_ivt __initconst = {
12960138d8f0SLen Brown 	.state_table = ivt_cstates,
12970138d8f0SLen Brown 	.disable_promotion_to_c1e = true,
1298e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
12990138d8f0SLen Brown };
13000138d8f0SLen Brown 
1301ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_hsw __initconst = {
130285a4d2d4SLen Brown 	.state_table = hsw_cstates,
130332e95180SLen Brown 	.disable_promotion_to_c1e = true,
130485a4d2d4SLen Brown };
130585a4d2d4SLen Brown 
1306ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_hsx __initconst = {
1307e6d4f08aSRafael J. Wysocki 	.state_table = hsw_cstates,
1308e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1309e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1310e6d4f08aSRafael J. Wysocki };
1311e6d4f08aSRafael J. Wysocki 
1312ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bdw __initconst = {
1313a138b568SLen Brown 	.state_table = bdw_cstates,
1314a138b568SLen Brown 	.disable_promotion_to_c1e = true,
1315a138b568SLen Brown };
1316a138b568SLen Brown 
1317ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bdx __initconst = {
1318e6d4f08aSRafael J. Wysocki 	.state_table = bdw_cstates,
1319e6d4f08aSRafael J. Wysocki 	.disable_promotion_to_c1e = true,
1320e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1321e6d4f08aSRafael J. Wysocki };
1322e6d4f08aSRafael J. Wysocki 
1323ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_skl __initconst = {
1324493f133fSLen Brown 	.state_table = skl_cstates,
1325493f133fSLen Brown 	.disable_promotion_to_c1e = true,
1326493f133fSLen Brown };
1327493f133fSLen Brown 
1328ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_skx __initconst = {
1329f9e71657SLen Brown 	.state_table = skx_cstates,
1330f9e71657SLen Brown 	.disable_promotion_to_c1e = true,
1331e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1332f9e71657SLen Brown };
1333493f133fSLen Brown 
1334a472ad2bSChen Yu static const struct idle_cpu idle_cpu_icx __initconst = {
1335a472ad2bSChen Yu 	.state_table = icx_cstates,
1336a472ad2bSChen Yu 	.disable_promotion_to_c1e = true,
1337a472ad2bSChen Yu 	.use_acpi = true,
1338a472ad2bSChen Yu };
1339a472ad2bSChen Yu 
1340d1cf8bbfSZhang Rui static const struct idle_cpu idle_cpu_adl __initconst = {
1341d1cf8bbfSZhang Rui 	.state_table = adl_cstates,
1342d1cf8bbfSZhang Rui };
1343d1cf8bbfSZhang Rui 
1344d1cf8bbfSZhang Rui static const struct idle_cpu idle_cpu_adl_l __initconst = {
1345d1cf8bbfSZhang Rui 	.state_table = adl_l_cstates,
1346d1cf8bbfSZhang Rui };
1347d1cf8bbfSZhang Rui 
1348882cdb06SPeter Zijlstra static const struct idle_cpu idle_cpu_gmt __initconst = {
1349882cdb06SPeter Zijlstra 	.state_table = gmt_cstates,
135065c0c236SZhang Rui };
135165c0c236SZhang Rui 
13529edf3c0fSArtem Bityutskiy static const struct idle_cpu idle_cpu_spr __initconst = {
13539edf3c0fSArtem Bityutskiy 	.state_table = spr_cstates,
13549edf3c0fSArtem Bityutskiy 	.disable_promotion_to_c1e = true,
13559edf3c0fSArtem Bityutskiy 	.use_acpi = true,
13569edf3c0fSArtem Bityutskiy };
13579edf3c0fSArtem Bityutskiy 
1358ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_avn __initconst = {
1359fab04b22SLen Brown 	.state_table = avn_cstates,
1360fab04b22SLen Brown 	.disable_promotion_to_c1e = true,
1361e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1362fab04b22SLen Brown };
1363fab04b22SLen Brown 
1364ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_knl __initconst = {
1365281baf7aSDasaratharaman Chandramouli 	.state_table = knl_cstates,
1366e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
1367281baf7aSDasaratharaman Chandramouli };
1368281baf7aSDasaratharaman Chandramouli 
1369ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bxt __initconst = {
13705dcef694SLen Brown 	.state_table = bxt_cstates,
13715dcef694SLen Brown 	.disable_promotion_to_c1e = true,
13725dcef694SLen Brown };
13735dcef694SLen Brown 
1374ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_dnv __initconst = {
13750080d65bSJacob Pan 	.state_table = dnv_cstates,
13760080d65bSJacob Pan 	.disable_promotion_to_c1e = true,
1377e6d4f08aSRafael J. Wysocki 	.use_acpi = true,
13780080d65bSJacob Pan };
13790080d65bSJacob Pan 
13809cf93f05SArtem Bityutskiy static const struct idle_cpu idle_cpu_snr __initconst = {
13819cf93f05SArtem Bityutskiy 	.state_table = snr_cstates,
13829cf93f05SArtem Bityutskiy 	.disable_promotion_to_c1e = true,
13839cf93f05SArtem Bityutskiy 	.use_acpi = true,
13849cf93f05SArtem Bityutskiy };
13859cf93f05SArtem Bityutskiy 
1386d5cdc3c4SMathias Krause static const struct x86_cpu_id intel_idle_ids[] __initconst = {
13874a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EP,		&idle_cpu_nhx),
13884a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM,		&idle_cpu_nehalem),
13894a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_G,		&idle_cpu_nehalem),
13904a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE,		&idle_cpu_nehalem),
13914a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EP,		&idle_cpu_nhx),
13924a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EX,		&idle_cpu_nhx),
13934a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL,	&idle_cpu_atom),
13944a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL_MID,	&idle_cpu_lincroft),
13954a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EX,		&idle_cpu_nhx),
13964a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE,		&idle_cpu_snb),
13974a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X,	&idle_cpu_snx),
13984a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SALTWELL,	&idle_cpu_atom),
13994a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT,	&idle_cpu_byt),
14004a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID,	&idle_cpu_tangier),
14014a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT,	&idle_cpu_cht),
14024a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE,		&idle_cpu_ivb),
14034a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X,		&idle_cpu_ivt),
14044a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL,		&idle_cpu_hsw),
14054a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X,		&idle_cpu_hsx),
14064a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L,		&idle_cpu_hsw),
14074a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G,		&idle_cpu_hsw),
14084a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D,	&idle_cpu_avn),
14094a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL,		&idle_cpu_bdw),
14104a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G,		&idle_cpu_bdw),
14114a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X,		&idle_cpu_bdx),
14124a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D,		&idle_cpu_bdx),
14134a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L,		&idle_cpu_skl),
14144a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE,		&idle_cpu_skl),
14154a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L,		&idle_cpu_skl),
14164a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE,		&idle_cpu_skl),
14174a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X,		&idle_cpu_skx),
1418a472ad2bSChen Yu 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,		&idle_cpu_icx),
141922141d5fSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,		&idle_cpu_icx),
1420d1cf8bbfSZhang Rui 	X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE,		&idle_cpu_adl),
1421d1cf8bbfSZhang Rui 	X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L,		&idle_cpu_adl_l),
1422882cdb06SPeter Zijlstra 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT,	&idle_cpu_gmt),
14239edf3c0fSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,	&idle_cpu_spr),
142474528edfSArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X,	&idle_cpu_spr),
14254a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL,	&idle_cpu_knl),
14264a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM,	&idle_cpu_knl),
14274a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT,	&idle_cpu_bxt),
14284a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS,	&idle_cpu_bxt),
14294a9f45a0SThomas Gleixner 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D,	&idle_cpu_dnv),
14309cf93f05SArtem Bityutskiy 	X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,	&idle_cpu_snr),
1431b66b8b9aSAndi Kleen 	{}
1432b66b8b9aSAndi Kleen };
1433b66b8b9aSAndi Kleen 
143418734958SRafael J. Wysocki static const struct x86_cpu_id intel_mwait_ids[] __initconst = {
14354a9f45a0SThomas Gleixner 	X86_MATCH_VENDOR_FAM_FEATURE(INTEL, 6, X86_FEATURE_MWAIT, NULL),
143618734958SRafael J. Wysocki 	{}
143718734958SRafael J. Wysocki };
143818734958SRafael J. Wysocki 
intel_idle_max_cstate_reached(int cstate)1439095928aeSRafael J. Wysocki static bool __init intel_idle_max_cstate_reached(int cstate)
144018734958SRafael J. Wysocki {
144118734958SRafael J. Wysocki 	if (cstate + 1 > max_cstate) {
144218734958SRafael J. Wysocki 		pr_info("max_cstate %d reached\n", max_cstate);
144318734958SRafael J. Wysocki 		return true;
144418734958SRafael J. Wysocki 	}
144518734958SRafael J. Wysocki 	return false;
144618734958SRafael J. Wysocki }
144718734958SRafael J. Wysocki 
intel_idle_state_needs_timer_stop(struct cpuidle_state * state)14484d916140SPeter Zijlstra static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state)
14494d916140SPeter Zijlstra {
14504d916140SPeter Zijlstra 	unsigned long eax = flg2MWAIT(state->flags);
14514d916140SPeter Zijlstra 
14524d916140SPeter Zijlstra 	if (boot_cpu_has(X86_FEATURE_ARAT))
14534d916140SPeter Zijlstra 		return false;
14544d916140SPeter Zijlstra 
14554d916140SPeter Zijlstra 	/*
14564d916140SPeter Zijlstra 	 * Switch over to one-shot tick broadcast if the target C-state
14574d916140SPeter Zijlstra 	 * is deeper than C1.
14584d916140SPeter Zijlstra 	 */
14594d916140SPeter Zijlstra 	return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK);
14604d916140SPeter Zijlstra }
14614d916140SPeter Zijlstra 
146218734958SRafael J. Wysocki #ifdef CONFIG_ACPI_PROCESSOR_CSTATE
146318734958SRafael J. Wysocki #include <acpi/processor.h>
146418734958SRafael J. Wysocki 
14654ec32d9eSRafael J. Wysocki static bool no_acpi __read_mostly;
14664ec32d9eSRafael J. Wysocki module_param(no_acpi, bool, 0444);
14674ec32d9eSRafael J. Wysocki MODULE_PARM_DESC(no_acpi, "Do not use ACPI _CST for building the idle states list");
14684ec32d9eSRafael J. Wysocki 
14693a5be9b8SRafael J. Wysocki static bool force_use_acpi __read_mostly; /* No effect if no_acpi is set. */
14703a5be9b8SRafael J. Wysocki module_param_named(use_acpi, force_use_acpi, bool, 0444);
14713a5be9b8SRafael J. Wysocki MODULE_PARM_DESC(use_acpi, "Use ACPI _CST for building the idle states list");
14723a5be9b8SRafael J. Wysocki 
1473095928aeSRafael J. Wysocki static struct acpi_processor_power acpi_state_table __initdata;
147418734958SRafael J. Wysocki 
147518734958SRafael J. Wysocki /**
147618734958SRafael J. Wysocki  * intel_idle_cst_usable - Check if the _CST information can be used.
147718734958SRafael J. Wysocki  *
147818734958SRafael J. Wysocki  * Check if all of the C-states listed by _CST in the max_cstate range are
147918734958SRafael J. Wysocki  * ACPI_CSTATE_FFH, which means that they should be entered via MWAIT.
148018734958SRafael J. Wysocki  */
intel_idle_cst_usable(void)1481095928aeSRafael J. Wysocki static bool __init intel_idle_cst_usable(void)
148218734958SRafael J. Wysocki {
148318734958SRafael J. Wysocki 	int cstate, limit;
148418734958SRafael J. Wysocki 
148518734958SRafael J. Wysocki 	limit = min_t(int, min_t(int, CPUIDLE_STATE_MAX, max_cstate + 1),
148618734958SRafael J. Wysocki 		      acpi_state_table.count);
148718734958SRafael J. Wysocki 
148818734958SRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
148918734958SRafael J. Wysocki 		struct acpi_processor_cx *cx = &acpi_state_table.states[cstate];
149018734958SRafael J. Wysocki 
149118734958SRafael J. Wysocki 		if (cx->entry_method != ACPI_CSTATE_FFH)
149218734958SRafael J. Wysocki 			return false;
149318734958SRafael J. Wysocki 	}
149418734958SRafael J. Wysocki 
149518734958SRafael J. Wysocki 	return true;
149618734958SRafael J. Wysocki }
149718734958SRafael J. Wysocki 
intel_idle_acpi_cst_extract(void)1498095928aeSRafael J. Wysocki static bool __init intel_idle_acpi_cst_extract(void)
149918734958SRafael J. Wysocki {
150018734958SRafael J. Wysocki 	unsigned int cpu;
150118734958SRafael J. Wysocki 
15024ec32d9eSRafael J. Wysocki 	if (no_acpi) {
15034ec32d9eSRafael J. Wysocki 		pr_debug("Not allowed to use ACPI _CST\n");
15044ec32d9eSRafael J. Wysocki 		return false;
15054ec32d9eSRafael J. Wysocki 	}
15064ec32d9eSRafael J. Wysocki 
150718734958SRafael J. Wysocki 	for_each_possible_cpu(cpu) {
150818734958SRafael J. Wysocki 		struct acpi_processor *pr = per_cpu(processors, cpu);
150918734958SRafael J. Wysocki 
151018734958SRafael J. Wysocki 		if (!pr)
151118734958SRafael J. Wysocki 			continue;
151218734958SRafael J. Wysocki 
151318734958SRafael J. Wysocki 		if (acpi_processor_evaluate_cst(pr->handle, cpu, &acpi_state_table))
151418734958SRafael J. Wysocki 			continue;
151518734958SRafael J. Wysocki 
151618734958SRafael J. Wysocki 		acpi_state_table.count++;
151718734958SRafael J. Wysocki 
151818734958SRafael J. Wysocki 		if (!intel_idle_cst_usable())
151918734958SRafael J. Wysocki 			continue;
152018734958SRafael J. Wysocki 
152175af76d0SMel Gorman 		if (!acpi_processor_claim_cst_control())
152275af76d0SMel Gorman 			break;
152318734958SRafael J. Wysocki 
152418734958SRafael J. Wysocki 		return true;
152518734958SRafael J. Wysocki 	}
152618734958SRafael J. Wysocki 
152775af76d0SMel Gorman 	acpi_state_table.count = 0;
152818734958SRafael J. Wysocki 	pr_debug("ACPI _CST not found or not usable\n");
152918734958SRafael J. Wysocki 	return false;
153018734958SRafael J. Wysocki }
153118734958SRafael J. Wysocki 
intel_idle_init_cstates_acpi(struct cpuidle_driver * drv)1532095928aeSRafael J. Wysocki static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
153318734958SRafael J. Wysocki {
153418734958SRafael J. Wysocki 	int cstate, limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
153518734958SRafael J. Wysocki 
153618734958SRafael J. Wysocki 	/*
153718734958SRafael J. Wysocki 	 * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of
153818734958SRafael J. Wysocki 	 * the interesting states are ACPI_CSTATE_FFH.
153918734958SRafael J. Wysocki 	 */
154018734958SRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
154118734958SRafael J. Wysocki 		struct acpi_processor_cx *cx;
154218734958SRafael J. Wysocki 		struct cpuidle_state *state;
154318734958SRafael J. Wysocki 
15444e0ba557SChen Yu 		if (intel_idle_max_cstate_reached(cstate - 1))
154518734958SRafael J. Wysocki 			break;
154618734958SRafael J. Wysocki 
154718734958SRafael J. Wysocki 		cx = &acpi_state_table.states[cstate];
154818734958SRafael J. Wysocki 
154918734958SRafael J. Wysocki 		state = &drv->states[drv->state_count++];
155018734958SRafael J. Wysocki 
155118734958SRafael J. Wysocki 		snprintf(state->name, CPUIDLE_NAME_LEN, "C%d_ACPI", cstate);
15520dbc0f49SWolfram Sang 		strscpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
155318734958SRafael J. Wysocki 		state->exit_latency = cx->latency;
155418734958SRafael J. Wysocki 		/*
155518734958SRafael J. Wysocki 		 * For C1-type C-states use the same number for both the exit
155618734958SRafael J. Wysocki 		 * latency and target residency, because that is the case for
155718734958SRafael J. Wysocki 		 * C1 in the majority of the static C-states tables above.
155818734958SRafael J. Wysocki 		 * For the other types of C-states, however, set the target
155918734958SRafael J. Wysocki 		 * residency to 3 times the exit latency which should lead to
156018734958SRafael J. Wysocki 		 * a reasonable balance between energy-efficiency and
156118734958SRafael J. Wysocki 		 * performance in the majority of interesting cases.
156218734958SRafael J. Wysocki 		 */
156318734958SRafael J. Wysocki 		state->target_residency = cx->latency;
156418734958SRafael J. Wysocki 		if (cx->type > ACPI_STATE_C1)
156518734958SRafael J. Wysocki 			state->target_residency *= 3;
156618734958SRafael J. Wysocki 
156718734958SRafael J. Wysocki 		state->flags = MWAIT2flg(cx->address);
156818734958SRafael J. Wysocki 		if (cx->type > ACPI_STATE_C2)
156918734958SRafael J. Wysocki 			state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
157018734958SRafael J. Wysocki 
15714dcb78eeSRafael J. Wysocki 		if (disabled_states_mask & BIT(cstate))
15724dcb78eeSRafael J. Wysocki 			state->flags |= CPUIDLE_FLAG_OFF;
15734dcb78eeSRafael J. Wysocki 
15746e1d2bc6SPeter Zijlstra 		if (intel_idle_state_needs_timer_stop(state))
15756e1d2bc6SPeter Zijlstra 			state->flags |= CPUIDLE_FLAG_TIMER_STOP;
15766e1d2bc6SPeter Zijlstra 
1577*3b7d2d1bSThomas Gleixner 		if (cx->type > ACPI_STATE_C1 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
1578*3b7d2d1bSThomas Gleixner 			mark_tsc_unstable("TSC halts in idle");
1579*3b7d2d1bSThomas Gleixner 
158018734958SRafael J. Wysocki 		state->enter = intel_idle;
158118734958SRafael J. Wysocki 		state->enter_s2idle = intel_idle_s2idle;
158218734958SRafael J. Wysocki 	}
158318734958SRafael J. Wysocki }
1584bff8e60aSRafael J. Wysocki 
intel_idle_off_by_default(u32 mwait_hint)1585095928aeSRafael J. Wysocki static bool __init intel_idle_off_by_default(u32 mwait_hint)
1586bff8e60aSRafael J. Wysocki {
1587bff8e60aSRafael J. Wysocki 	int cstate, limit;
1588bff8e60aSRafael J. Wysocki 
1589bff8e60aSRafael J. Wysocki 	/*
1590bff8e60aSRafael J. Wysocki 	 * If there are no _CST C-states, do not disable any C-states by
1591bff8e60aSRafael J. Wysocki 	 * default.
1592bff8e60aSRafael J. Wysocki 	 */
1593bff8e60aSRafael J. Wysocki 	if (!acpi_state_table.count)
1594bff8e60aSRafael J. Wysocki 		return false;
1595bff8e60aSRafael J. Wysocki 
1596bff8e60aSRafael J. Wysocki 	limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
1597bff8e60aSRafael J. Wysocki 	/*
1598bff8e60aSRafael J. Wysocki 	 * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of
1599bff8e60aSRafael J. Wysocki 	 * the interesting states are ACPI_CSTATE_FFH.
1600bff8e60aSRafael J. Wysocki 	 */
1601bff8e60aSRafael J. Wysocki 	for (cstate = 1; cstate < limit; cstate++) {
1602bff8e60aSRafael J. Wysocki 		if (acpi_state_table.states[cstate].address == mwait_hint)
1603bff8e60aSRafael J. Wysocki 			return false;
1604bff8e60aSRafael J. Wysocki 	}
1605bff8e60aSRafael J. Wysocki 	return true;
1606bff8e60aSRafael J. Wysocki }
160718734958SRafael J. Wysocki #else /* !CONFIG_ACPI_PROCESSOR_CSTATE */
16083a5be9b8SRafael J. Wysocki #define force_use_acpi	(false)
16093a5be9b8SRafael J. Wysocki 
intel_idle_acpi_cst_extract(void)161018734958SRafael J. Wysocki static inline bool intel_idle_acpi_cst_extract(void) { return false; }
intel_idle_init_cstates_acpi(struct cpuidle_driver * drv)161118734958SRafael J. Wysocki static inline void intel_idle_init_cstates_acpi(struct cpuidle_driver *drv) { }
intel_idle_off_by_default(u32 mwait_hint)1612bff8e60aSRafael J. Wysocki static inline bool intel_idle_off_by_default(u32 mwait_hint) { return false; }
161318734958SRafael J. Wysocki #endif /* !CONFIG_ACPI_PROCESSOR_CSTATE */
161418734958SRafael J. Wysocki 
16156eacb15fSRafael J. Wysocki /**
16166eacb15fSRafael J. Wysocki  * ivt_idle_state_table_update - Tune the idle states table for Ivy Town.
16170138d8f0SLen Brown  *
16186eacb15fSRafael J. Wysocki  * Tune IVT multi-socket targets.
16196eacb15fSRafael J. Wysocki  * Assumption: num_sockets == (max_package_num + 1).
16200138d8f0SLen Brown  */
ivt_idle_state_table_update(void)1621095928aeSRafael J. Wysocki static void __init ivt_idle_state_table_update(void)
16220138d8f0SLen Brown {
16230138d8f0SLen Brown 	/* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
16240138d8f0SLen Brown 	int cpu, package_num, num_sockets = 1;
16250138d8f0SLen Brown 
16260138d8f0SLen Brown 	for_each_online_cpu(cpu) {
16270138d8f0SLen Brown 		package_num = topology_physical_package_id(cpu);
16280138d8f0SLen Brown 		if (package_num + 1 > num_sockets) {
16290138d8f0SLen Brown 			num_sockets = package_num + 1;
16300138d8f0SLen Brown 
1631d27dca42SChristoph Jaeger 			if (num_sockets > 4) {
16320138d8f0SLen Brown 				cpuidle_state_table = ivt_cstates_8s;
16330138d8f0SLen Brown 				return;
16340138d8f0SLen Brown 			}
16350138d8f0SLen Brown 		}
1636d27dca42SChristoph Jaeger 	}
16370138d8f0SLen Brown 
16380138d8f0SLen Brown 	if (num_sockets > 2)
16390138d8f0SLen Brown 		cpuidle_state_table = ivt_cstates_4s;
1640d70e28f5SLen Brown 
16410138d8f0SLen Brown 	/* else, 1 and 2 socket systems use default ivt_cstates */
16420138d8f0SLen Brown }
16435dcef694SLen Brown 
164486e9466aSRafael J. Wysocki /**
164586e9466aSRafael J. Wysocki  * irtl_2_usec - IRTL to microseconds conversion.
164686e9466aSRafael J. Wysocki  * @irtl: IRTL MSR value.
164786e9466aSRafael J. Wysocki  *
164886e9466aSRafael J. Wysocki  * Translate the IRTL (Interrupt Response Time Limit) MSR value to microseconds.
16495dcef694SLen Brown  */
irtl_2_usec(unsigned long long irtl)165086e9466aSRafael J. Wysocki static unsigned long long __init irtl_2_usec(unsigned long long irtl)
165186e9466aSRafael J. Wysocki {
1652095928aeSRafael J. Wysocki 	static const unsigned int irtl_ns_units[] __initconst = {
1653095928aeSRafael J. Wysocki 		1, 32, 1024, 32768, 1048576, 33554432, 0, 0
1654095928aeSRafael J. Wysocki 	};
16555dcef694SLen Brown 	unsigned long long ns;
16565dcef694SLen Brown 
16573451ab3eSJan Beulich 	if (!irtl)
16583451ab3eSJan Beulich 		return 0;
16593451ab3eSJan Beulich 
1660bef45096SJan Beulich 	ns = irtl_ns_units[(irtl >> 10) & 0x7];
16615dcef694SLen Brown 
166286e9466aSRafael J. Wysocki 	return div_u64((irtl & 0x3FF) * ns, NSEC_PER_USEC);
16635dcef694SLen Brown }
166486e9466aSRafael J. Wysocki 
16656eacb15fSRafael J. Wysocki /**
16666eacb15fSRafael J. Wysocki  * bxt_idle_state_table_update - Fix up the Broxton idle states table.
16675dcef694SLen Brown  *
16686eacb15fSRafael J. Wysocki  * On BXT, trust the IRTL (Interrupt Response Time Limit) MSR to show the
16696eacb15fSRafael J. Wysocki  * definitive maximum latency and use the same value for target_residency.
16705dcef694SLen Brown  */
bxt_idle_state_table_update(void)1671095928aeSRafael J. Wysocki static void __init bxt_idle_state_table_update(void)
16725dcef694SLen Brown {
16735dcef694SLen Brown 	unsigned long long msr;
16743451ab3eSJan Beulich 	unsigned int usec;
16755dcef694SLen Brown 
16765dcef694SLen Brown 	rdmsrl(MSR_PKGC6_IRTL, msr);
16773451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16783451ab3eSJan Beulich 	if (usec) {
16795dcef694SLen Brown 		bxt_cstates[2].exit_latency = usec;
16805dcef694SLen Brown 		bxt_cstates[2].target_residency = usec;
16815dcef694SLen Brown 	}
16825dcef694SLen Brown 
16835dcef694SLen Brown 	rdmsrl(MSR_PKGC7_IRTL, msr);
16843451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16853451ab3eSJan Beulich 	if (usec) {
16865dcef694SLen Brown 		bxt_cstates[3].exit_latency = usec;
16875dcef694SLen Brown 		bxt_cstates[3].target_residency = usec;
16885dcef694SLen Brown 	}
16895dcef694SLen Brown 
16905dcef694SLen Brown 	rdmsrl(MSR_PKGC8_IRTL, msr);
16913451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16923451ab3eSJan Beulich 	if (usec) {
16935dcef694SLen Brown 		bxt_cstates[4].exit_latency = usec;
16945dcef694SLen Brown 		bxt_cstates[4].target_residency = usec;
16955dcef694SLen Brown 	}
16965dcef694SLen Brown 
16975dcef694SLen Brown 	rdmsrl(MSR_PKGC9_IRTL, msr);
16983451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
16993451ab3eSJan Beulich 	if (usec) {
17005dcef694SLen Brown 		bxt_cstates[5].exit_latency = usec;
17015dcef694SLen Brown 		bxt_cstates[5].target_residency = usec;
17025dcef694SLen Brown 	}
17035dcef694SLen Brown 
17045dcef694SLen Brown 	rdmsrl(MSR_PKGC10_IRTL, msr);
17053451ab3eSJan Beulich 	usec = irtl_2_usec(msr);
17063451ab3eSJan Beulich 	if (usec) {
17075dcef694SLen Brown 		bxt_cstates[6].exit_latency = usec;
17085dcef694SLen Brown 		bxt_cstates[6].target_residency = usec;
17095dcef694SLen Brown 	}
17105dcef694SLen Brown 
17115dcef694SLen Brown }
17126eacb15fSRafael J. Wysocki 
17136eacb15fSRafael J. Wysocki /**
17146eacb15fSRafael J. Wysocki  * sklh_idle_state_table_update - Fix up the Sky Lake idle states table.
1715d70e28f5SLen Brown  *
17166eacb15fSRafael J. Wysocki  * On SKL-H (model 0x5e) skip C8 and C9 if C10 is enabled and SGX disabled.
1717d70e28f5SLen Brown  */
sklh_idle_state_table_update(void)1718095928aeSRafael J. Wysocki static void __init sklh_idle_state_table_update(void)
1719d70e28f5SLen Brown {
1720d70e28f5SLen Brown 	unsigned long long msr;
1721d70e28f5SLen Brown 	unsigned int eax, ebx, ecx, edx;
1722d70e28f5SLen Brown 
1723d70e28f5SLen Brown 
1724d70e28f5SLen Brown 	/* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */
1725d70e28f5SLen Brown 	if (max_cstate <= 7)
17260138d8f0SLen Brown 		return;
1727d70e28f5SLen Brown 
1728d70e28f5SLen Brown 	/* if PC10 not present in CPUID.MWAIT.EDX */
1729d70e28f5SLen Brown 	if ((mwait_substates & (0xF << 28)) == 0)
1730d70e28f5SLen Brown 		return;
1731d70e28f5SLen Brown 
17326cfb2374SLen Brown 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
1733d70e28f5SLen Brown 
1734d70e28f5SLen Brown 	/* PC10 is not enabled in PKG C-state limit */
1735d70e28f5SLen Brown 	if ((msr & 0xF) != 8)
1736d70e28f5SLen Brown 		return;
1737d70e28f5SLen Brown 
1738d70e28f5SLen Brown 	ecx = 0;
1739d70e28f5SLen Brown 	cpuid(7, &eax, &ebx, &ecx, &edx);
1740d70e28f5SLen Brown 
1741d70e28f5SLen Brown 	/* if SGX is present */
1742d70e28f5SLen Brown 	if (ebx & (1 << 2)) {
1743d70e28f5SLen Brown 
174432ad73dbSSean Christopherson 		rdmsrl(MSR_IA32_FEAT_CTL, msr);
1745d70e28f5SLen Brown 
1746d70e28f5SLen Brown 		/* if SGX is enabled */
1747d70e28f5SLen Brown 		if (msr & (1 << 18))
1748d70e28f5SLen Brown 			return;
1749d70e28f5SLen Brown 	}
1750d70e28f5SLen Brown 
1751ba1e78a1SRafael J. Wysocki 	skl_cstates[5].flags |= CPUIDLE_FLAG_UNUSABLE;	/* C8-SKL */
1752ba1e78a1SRafael J. Wysocki 	skl_cstates[6].flags |= CPUIDLE_FLAG_UNUSABLE;	/* C9-SKL */
1753d70e28f5SLen Brown }
1754d70e28f5SLen Brown 
175564233338SChen Yu /**
175664233338SChen Yu  * skx_idle_state_table_update - Adjust the Sky Lake/Cascade Lake
175764233338SChen Yu  * idle states table.
175864233338SChen Yu  */
skx_idle_state_table_update(void)175964233338SChen Yu static void __init skx_idle_state_table_update(void)
176064233338SChen Yu {
176164233338SChen Yu 	unsigned long long msr;
176264233338SChen Yu 
176364233338SChen Yu 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
176464233338SChen Yu 
176564233338SChen Yu 	/*
176664233338SChen Yu 	 * 000b: C0/C1 (no package C-state support)
176764233338SChen Yu 	 * 001b: C2
176864233338SChen Yu 	 * 010b: C6 (non-retention)
176964233338SChen Yu 	 * 011b: C6 (retention)
177064233338SChen Yu 	 * 111b: No Package C state limits.
177164233338SChen Yu 	 */
177264233338SChen Yu 	if ((msr & 0x7) < 2) {
177364233338SChen Yu 		/*
177464233338SChen Yu 		 * Uses the CC6 + PC0 latency and 3 times of
177564233338SChen Yu 		 * latency for target_residency if the PC6
177664233338SChen Yu 		 * is disabled in BIOS. This is consistent
177764233338SChen Yu 		 * with how intel_idle driver uses _CST
177864233338SChen Yu 		 * to set the target_residency.
177964233338SChen Yu 		 */
178064233338SChen Yu 		skx_cstates[2].exit_latency = 92;
178164233338SChen Yu 		skx_cstates[2].target_residency = 276;
178264233338SChen Yu 	}
178364233338SChen Yu }
178464233338SChen Yu 
1785da0e58c0SArtem Bityutskiy /**
1786d1cf8bbfSZhang Rui  * adl_idle_state_table_update - Adjust AlderLake idle states table.
1787d1cf8bbfSZhang Rui  */
adl_idle_state_table_update(void)1788d1cf8bbfSZhang Rui static void __init adl_idle_state_table_update(void)
1789d1cf8bbfSZhang Rui {
1790d1cf8bbfSZhang Rui 	/* Check if user prefers C1 over C1E. */
1791d1cf8bbfSZhang Rui 	if (preferred_states_mask & BIT(1) && !(preferred_states_mask & BIT(2))) {
1792d1cf8bbfSZhang Rui 		cpuidle_state_table[0].flags &= ~CPUIDLE_FLAG_UNUSABLE;
1793d1cf8bbfSZhang Rui 		cpuidle_state_table[1].flags |= CPUIDLE_FLAG_UNUSABLE;
1794d1cf8bbfSZhang Rui 
1795d1cf8bbfSZhang Rui 		/* Disable C1E by clearing the "C1E promotion" bit. */
1796d1cf8bbfSZhang Rui 		c1e_promotion = C1E_PROMOTION_DISABLE;
1797d1cf8bbfSZhang Rui 		return;
1798d1cf8bbfSZhang Rui 	}
1799d1cf8bbfSZhang Rui 
1800d1cf8bbfSZhang Rui 	/* Make sure C1E is enabled by default */
1801d1cf8bbfSZhang Rui 	c1e_promotion = C1E_PROMOTION_ENABLE;
1802d1cf8bbfSZhang Rui }
1803d1cf8bbfSZhang Rui 
1804d1cf8bbfSZhang Rui /**
1805da0e58c0SArtem Bityutskiy  * spr_idle_state_table_update - Adjust Sapphire Rapids idle states table.
1806da0e58c0SArtem Bityutskiy  */
spr_idle_state_table_update(void)1807da0e58c0SArtem Bityutskiy static void __init spr_idle_state_table_update(void)
1808da0e58c0SArtem Bityutskiy {
18093a9cf77bSArtem Bityutskiy 	unsigned long long msr;
18103a9cf77bSArtem Bityutskiy 
18113a9cf77bSArtem Bityutskiy 	/*
18123a9cf77bSArtem Bityutskiy 	 * By default, the C6 state assumes the worst-case scenario of package
18133a9cf77bSArtem Bityutskiy 	 * C6. However, if PC6 is disabled, we update the numbers to match
18143a9cf77bSArtem Bityutskiy 	 * core C6.
18153a9cf77bSArtem Bityutskiy 	 */
18163a9cf77bSArtem Bityutskiy 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr);
18173a9cf77bSArtem Bityutskiy 
18183a9cf77bSArtem Bityutskiy 	/* Limit value 2 and above allow for PC6. */
18193a9cf77bSArtem Bityutskiy 	if ((msr & 0x7) < 2) {
18203a9cf77bSArtem Bityutskiy 		spr_cstates[2].exit_latency = 190;
18213a9cf77bSArtem Bityutskiy 		spr_cstates[2].target_residency = 600;
18223a9cf77bSArtem Bityutskiy 	}
1823da0e58c0SArtem Bityutskiy }
1824da0e58c0SArtem Bityutskiy 
intel_idle_verify_cstate(unsigned int mwait_hint)18251aefbd7aSRafael J. Wysocki static bool __init intel_idle_verify_cstate(unsigned int mwait_hint)
18261aefbd7aSRafael J. Wysocki {
18271aefbd7aSRafael J. Wysocki 	unsigned int mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint) + 1;
18281aefbd7aSRafael J. Wysocki 	unsigned int num_substates = (mwait_substates >> mwait_cstate * 4) &
18291aefbd7aSRafael J. Wysocki 					MWAIT_SUBSTATE_MASK;
18301aefbd7aSRafael J. Wysocki 
18311aefbd7aSRafael J. Wysocki 	/* Ignore the C-state if there are NO sub-states in CPUID for it. */
18321aefbd7aSRafael J. Wysocki 	if (num_substates == 0)
18331aefbd7aSRafael J. Wysocki 		return false;
18341aefbd7aSRafael J. Wysocki 
18351aefbd7aSRafael J. Wysocki 	if (mwait_cstate > 2 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
18361aefbd7aSRafael J. Wysocki 		mark_tsc_unstable("TSC halts in idle states deeper than C2");
18371aefbd7aSRafael J. Wysocki 
18381aefbd7aSRafael J. Wysocki 	return true;
18391aefbd7aSRafael J. Wysocki }
18401aefbd7aSRafael J. Wysocki 
state_update_enter_method(struct cpuidle_state * state,int cstate)18414622ba92SArjan van de Ven static void state_update_enter_method(struct cpuidle_state *state, int cstate)
18424622ba92SArjan van de Ven {
18434622ba92SArjan van de Ven 	if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) {
18444622ba92SArjan van de Ven 		/*
18454622ba92SArjan van de Ven 		 * Combining with XSTATE with IBRS or IRQ_ENABLE flags
18464622ba92SArjan van de Ven 		 * is not currently supported but this driver.
18474622ba92SArjan van de Ven 		 */
18484622ba92SArjan van de Ven 		WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IBRS);
18494622ba92SArjan van de Ven 		WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
18504622ba92SArjan van de Ven 		state->enter = intel_idle_xstate;
18517826c069SArjan van de Ven 		return;
18527826c069SArjan van de Ven 	}
18537826c069SArjan van de Ven 
18547826c069SArjan van de Ven 	if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) &&
18554622ba92SArjan van de Ven 			   state->flags & CPUIDLE_FLAG_IBRS) {
18564622ba92SArjan van de Ven 		/*
18574622ba92SArjan van de Ven 		 * IBRS mitigation requires that C-states are entered
18584622ba92SArjan van de Ven 		 * with interrupts disabled.
18594622ba92SArjan van de Ven 		 */
18604622ba92SArjan van de Ven 		WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
18614622ba92SArjan van de Ven 		state->enter = intel_idle_ibrs;
18627826c069SArjan van de Ven 		return;
18637826c069SArjan van de Ven 	}
18647826c069SArjan van de Ven 
18657826c069SArjan van de Ven 	if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE) {
18664622ba92SArjan van de Ven 		state->enter = intel_idle_irq;
18677826c069SArjan van de Ven 		return;
18687826c069SArjan van de Ven 	}
18697826c069SArjan van de Ven 
18707826c069SArjan van de Ven 	if (force_irq_on) {
18714622ba92SArjan van de Ven 		pr_info("forced intel_idle_irq for state %d\n", cstate);
18724622ba92SArjan van de Ven 		state->enter = intel_idle_irq;
18734622ba92SArjan van de Ven 	}
18744622ba92SArjan van de Ven }
18754622ba92SArjan van de Ven 
intel_idle_init_cstates_icpu(struct cpuidle_driver * drv)1876095928aeSRafael J. Wysocki static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
1877d70e28f5SLen Brown {
18783d3a1ae9SRafael J. Wysocki 	int cstate;
1879d70e28f5SLen Brown 
18803d3a1ae9SRafael J. Wysocki 	switch (boot_cpu_data.x86_model) {
1881db73c5a8SDave Hansen 	case INTEL_FAM6_IVYBRIDGE_X:
1882d70e28f5SLen Brown 		ivt_idle_state_table_update();
1883d70e28f5SLen Brown 		break;
1884db73c5a8SDave Hansen 	case INTEL_FAM6_ATOM_GOLDMONT:
1885f2c4db1bSPeter Zijlstra 	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
18865dcef694SLen Brown 		bxt_idle_state_table_update();
18875dcef694SLen Brown 		break;
1888c66f78a6SPeter Zijlstra 	case INTEL_FAM6_SKYLAKE:
1889d70e28f5SLen Brown 		sklh_idle_state_table_update();
1890d70e28f5SLen Brown 		break;
189164233338SChen Yu 	case INTEL_FAM6_SKYLAKE_X:
189264233338SChen Yu 		skx_idle_state_table_update();
189364233338SChen Yu 		break;
1894da0e58c0SArtem Bityutskiy 	case INTEL_FAM6_SAPPHIRERAPIDS_X:
189574528edfSArtem Bityutskiy 	case INTEL_FAM6_EMERALDRAPIDS_X:
1896da0e58c0SArtem Bityutskiy 		spr_idle_state_table_update();
1897da0e58c0SArtem Bityutskiy 		break;
1898d1cf8bbfSZhang Rui 	case INTEL_FAM6_ALDERLAKE:
1899d1cf8bbfSZhang Rui 	case INTEL_FAM6_ALDERLAKE_L:
1900882cdb06SPeter Zijlstra 	case INTEL_FAM6_ATOM_GRACEMONT:
1901d1cf8bbfSZhang Rui 		adl_idle_state_table_update();
1902d1cf8bbfSZhang Rui 		break;
1903d70e28f5SLen Brown 	}
190446bcfad7SDeepthi Dharwar 
1905e022e7ebSLen Brown 	for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
19061abffbd8SArtem Bityutskiy 		struct cpuidle_state *state;
19079f3d6dafSRafael J. Wysocki 		unsigned int mwait_hint;
190846bcfad7SDeepthi Dharwar 
190918734958SRafael J. Wysocki 		if (intel_idle_max_cstate_reached(cstate))
191018734958SRafael J. Wysocki 			break;
191118734958SRafael J. Wysocki 
19129f3d6dafSRafael J. Wysocki 		if (!cpuidle_state_table[cstate].enter &&
19139f3d6dafSRafael J. Wysocki 		    !cpuidle_state_table[cstate].enter_s2idle)
1914e022e7ebSLen Brown 			break;
1915e022e7ebSLen Brown 
19169f3d6dafSRafael J. Wysocki 		/* If marked as unusable, skip this state. */
1917ba1e78a1SRafael J. Wysocki 		if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_UNUSABLE) {
1918654d08a4SJoe Perches 			pr_debug("state %s is disabled\n",
1919d70e28f5SLen Brown 				 cpuidle_state_table[cstate].name);
1920d70e28f5SLen Brown 			continue;
1921d70e28f5SLen Brown 		}
1922d70e28f5SLen Brown 
19239f3d6dafSRafael J. Wysocki 		mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
19245534f446SRafael J. Wysocki 		if (!intel_idle_verify_cstate(mwait_hint))
19259f3d6dafSRafael J. Wysocki 			continue;
1926d70e28f5SLen Brown 
19279f3d6dafSRafael J. Wysocki 		/* Structure copy. */
1928bff8e60aSRafael J. Wysocki 		drv->states[drv->state_count] = cpuidle_state_table[cstate];
19291abffbd8SArtem Bityutskiy 		state = &drv->states[drv->state_count];
1930bff8e60aSRafael J. Wysocki 
19314622ba92SArjan van de Ven 		state_update_enter_method(state, cstate);
19324622ba92SArjan van de Ven 
193332d4fd57SPeter Zijlstra 
19344dcb78eeSRafael J. Wysocki 		if ((disabled_states_mask & BIT(drv->state_count)) ||
19354dcb78eeSRafael J. Wysocki 		    ((icpu->use_acpi || force_use_acpi) &&
19363a5be9b8SRafael J. Wysocki 		     intel_idle_off_by_default(mwait_hint) &&
19371abffbd8SArtem Bityutskiy 		     !(state->flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
19381abffbd8SArtem Bityutskiy 			state->flags |= CPUIDLE_FLAG_OFF;
1939bff8e60aSRafael J. Wysocki 
19401abffbd8SArtem Bityutskiy 		if (intel_idle_state_needs_timer_stop(state))
19411abffbd8SArtem Bityutskiy 			state->flags |= CPUIDLE_FLAG_TIMER_STOP;
19426e1d2bc6SPeter Zijlstra 
1943bff8e60aSRafael J. Wysocki 		drv->state_count++;
194446bcfad7SDeepthi Dharwar 	}
194546bcfad7SDeepthi Dharwar 
19468c058d53SLen Brown 	if (icpu->byt_auto_demotion_disable_flag) {
19478c058d53SLen Brown 		wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0);
19488c058d53SLen Brown 		wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0);
19498c058d53SLen Brown 	}
195046bcfad7SDeepthi Dharwar }
195146bcfad7SDeepthi Dharwar 
19526eacb15fSRafael J. Wysocki /**
19536eacb15fSRafael J. Wysocki  * intel_idle_cpuidle_driver_init - Create the list of available idle states.
19546eacb15fSRafael J. Wysocki  * @drv: cpuidle driver structure to initialize.
195518734958SRafael J. Wysocki  */
intel_idle_cpuidle_driver_init(struct cpuidle_driver * drv)19563d3a1ae9SRafael J. Wysocki static void __init intel_idle_cpuidle_driver_init(struct cpuidle_driver *drv)
195718734958SRafael J. Wysocki {
195818734958SRafael J. Wysocki 	cpuidle_poll_state_init(drv);
19594dcb78eeSRafael J. Wysocki 
19604dcb78eeSRafael J. Wysocki 	if (disabled_states_mask & BIT(0))
19614dcb78eeSRafael J. Wysocki 		drv->states[0].flags |= CPUIDLE_FLAG_OFF;
19624dcb78eeSRafael J. Wysocki 
196318734958SRafael J. Wysocki 	drv->state_count = 1;
196418734958SRafael J. Wysocki 
196518734958SRafael J. Wysocki 	if (icpu)
196618734958SRafael J. Wysocki 		intel_idle_init_cstates_icpu(drv);
196718734958SRafael J. Wysocki 	else
196818734958SRafael J. Wysocki 		intel_idle_init_cstates_acpi(drv);
196918734958SRafael J. Wysocki }
197046bcfad7SDeepthi Dharwar 
auto_demotion_disable(void)19711aefbd7aSRafael J. Wysocki static void auto_demotion_disable(void)
19721aefbd7aSRafael J. Wysocki {
19731aefbd7aSRafael J. Wysocki 	unsigned long long msr_bits;
19741aefbd7aSRafael J. Wysocki 
19751aefbd7aSRafael J. Wysocki 	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
19767f843dd7SRafael J. Wysocki 	msr_bits &= ~auto_demotion_disable_flags;
19771aefbd7aSRafael J. Wysocki 	wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits);
19781aefbd7aSRafael J. Wysocki }
19791aefbd7aSRafael J. Wysocki 
c1e_promotion_enable(void)1980da0e58c0SArtem Bityutskiy static void c1e_promotion_enable(void)
1981da0e58c0SArtem Bityutskiy {
1982da0e58c0SArtem Bityutskiy 	unsigned long long msr_bits;
1983da0e58c0SArtem Bityutskiy 
1984da0e58c0SArtem Bityutskiy 	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
1985da0e58c0SArtem Bityutskiy 	msr_bits |= 0x2;
1986da0e58c0SArtem Bityutskiy 	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
1987da0e58c0SArtem Bityutskiy }
1988da0e58c0SArtem Bityutskiy 
c1e_promotion_disable(void)19891aefbd7aSRafael J. Wysocki static void c1e_promotion_disable(void)
19901aefbd7aSRafael J. Wysocki {
19911aefbd7aSRafael J. Wysocki 	unsigned long long msr_bits;
19921aefbd7aSRafael J. Wysocki 
19931aefbd7aSRafael J. Wysocki 	rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
19941aefbd7aSRafael J. Wysocki 	msr_bits &= ~0x2;
19951aefbd7aSRafael J. Wysocki 	wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
19961aefbd7aSRafael J. Wysocki }
19971aefbd7aSRafael J. Wysocki 
19986eacb15fSRafael J. Wysocki /**
19996eacb15fSRafael J. Wysocki  * intel_idle_cpu_init - Register the target CPU with the cpuidle core.
20006eacb15fSRafael J. Wysocki  * @cpu: CPU to initialize.
20016eacb15fSRafael J. Wysocki  *
20026eacb15fSRafael J. Wysocki  * Register a cpuidle device object for @cpu and update its MSRs in accordance
20036eacb15fSRafael J. Wysocki  * with the processor model flags.
200426717172SLen Brown  */
intel_idle_cpu_init(unsigned int cpu)2005fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_init(unsigned int cpu)
200626717172SLen Brown {
200726717172SLen Brown 	struct cpuidle_device *dev;
200826717172SLen Brown 
200965b7f839SThomas Renninger 	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
201065b7f839SThomas Renninger 	dev->cpu = cpu;
201126717172SLen Brown 
201226717172SLen Brown 	if (cpuidle_register_device(dev)) {
2013654d08a4SJoe Perches 		pr_debug("cpuidle_register_device %d failed!\n", cpu);
201426717172SLen Brown 		return -EIO;
201526717172SLen Brown 	}
201665b7f839SThomas Renninger 
20177f843dd7SRafael J. Wysocki 	if (auto_demotion_disable_flags)
2018fb1013a0SSebastian Andrzej Siewior 		auto_demotion_disable();
201926717172SLen Brown 
202039c184a6SArtem Bityutskiy 	if (c1e_promotion == C1E_PROMOTION_ENABLE)
202139c184a6SArtem Bityutskiy 		c1e_promotion_enable();
202239c184a6SArtem Bityutskiy 	else if (c1e_promotion == C1E_PROMOTION_DISABLE)
2023fb1013a0SSebastian Andrzej Siewior 		c1e_promotion_disable();
2024fb1013a0SSebastian Andrzej Siewior 
2025fb1013a0SSebastian Andrzej Siewior 	return 0;
2026fb1013a0SSebastian Andrzej Siewior }
2027fb1013a0SSebastian Andrzej Siewior 
intel_idle_cpu_online(unsigned int cpu)2028fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_online(unsigned int cpu)
2029fb1013a0SSebastian Andrzej Siewior {
2030fb1013a0SSebastian Andrzej Siewior 	struct cpuidle_device *dev;
2031fb1013a0SSebastian Andrzej Siewior 
2032dab20177SRafael J. Wysocki 	if (!boot_cpu_has(X86_FEATURE_ARAT))
2033cbd2c4c2SRafael J. Wysocki 		tick_broadcast_enable();
2034fb1013a0SSebastian Andrzej Siewior 
2035fb1013a0SSebastian Andrzej Siewior 	/*
2036fb1013a0SSebastian Andrzej Siewior 	 * Some systems can hotplug a cpu at runtime after
2037fb1013a0SSebastian Andrzej Siewior 	 * the kernel has booted, we have to initialize the
2038fb1013a0SSebastian Andrzej Siewior 	 * driver in this case
2039fb1013a0SSebastian Andrzej Siewior 	 */
2040fb1013a0SSebastian Andrzej Siewior 	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
2041fb1013a0SSebastian Andrzej Siewior 	if (!dev->registered)
2042fb1013a0SSebastian Andrzej Siewior 		return intel_idle_cpu_init(cpu);
2043dbf87ab8SBartlomiej Zolnierkiewicz 
204426717172SLen Brown 	return 0;
204526717172SLen Brown }
204626717172SLen Brown 
20470755a9bdSRafael J. Wysocki /**
20480755a9bdSRafael J. Wysocki  * intel_idle_cpuidle_devices_uninit - Unregister all cpuidle devices.
20490755a9bdSRafael J. Wysocki  */
intel_idle_cpuidle_devices_uninit(void)20500755a9bdSRafael J. Wysocki static void __init intel_idle_cpuidle_devices_uninit(void)
20510755a9bdSRafael J. Wysocki {
20520755a9bdSRafael J. Wysocki 	int i;
20530755a9bdSRafael J. Wysocki 
20540755a9bdSRafael J. Wysocki 	for_each_online_cpu(i)
20550755a9bdSRafael J. Wysocki 		cpuidle_unregister_device(per_cpu_ptr(intel_idle_cpuidle_devices, i));
20560755a9bdSRafael J. Wysocki }
20570755a9bdSRafael J. Wysocki 
intel_idle_init(void)205826717172SLen Brown static int __init intel_idle_init(void)
205926717172SLen Brown {
2060a6c86e33SRafael J. Wysocki 	const struct x86_cpu_id *id;
2061a6c86e33SRafael J. Wysocki 	unsigned int eax, ebx, ecx;
2062fb1013a0SSebastian Andrzej Siewior 	int retval;
206326717172SLen Brown 
2064d1896049SThomas Renninger 	/* Do not load intel_idle at all for now if idle= is passed */
2065d1896049SThomas Renninger 	if (boot_option_idle_override != IDLE_NO_OVERRIDE)
2066d1896049SThomas Renninger 		return -ENODEV;
2067d1896049SThomas Renninger 
2068a6c86e33SRafael J. Wysocki 	if (max_cstate == 0) {
2069a6c86e33SRafael J. Wysocki 		pr_debug("disabled\n");
2070a6c86e33SRafael J. Wysocki 		return -EPERM;
2071a6c86e33SRafael J. Wysocki 	}
2072a6c86e33SRafael J. Wysocki 
2073a6c86e33SRafael J. Wysocki 	id = x86_match_cpu(intel_idle_ids);
2074a6c86e33SRafael J. Wysocki 	if (id) {
2075a6c86e33SRafael J. Wysocki 		if (!boot_cpu_has(X86_FEATURE_MWAIT)) {
2076a6c86e33SRafael J. Wysocki 			pr_debug("Please enable MWAIT in BIOS SETUP\n");
2077a6c86e33SRafael J. Wysocki 			return -ENODEV;
2078a6c86e33SRafael J. Wysocki 		}
2079a6c86e33SRafael J. Wysocki 	} else {
2080a6c86e33SRafael J. Wysocki 		id = x86_match_cpu(intel_mwait_ids);
2081a6c86e33SRafael J. Wysocki 		if (!id)
2082a6c86e33SRafael J. Wysocki 			return -ENODEV;
2083a6c86e33SRafael J. Wysocki 	}
2084a6c86e33SRafael J. Wysocki 
2085a6c86e33SRafael J. Wysocki 	if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
2086a6c86e33SRafael J. Wysocki 		return -ENODEV;
2087a6c86e33SRafael J. Wysocki 
2088a6c86e33SRafael J. Wysocki 	cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
2089a6c86e33SRafael J. Wysocki 
2090a6c86e33SRafael J. Wysocki 	if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
2091a6c86e33SRafael J. Wysocki 	    !(ecx & CPUID5_ECX_INTERRUPT_BREAK) ||
2092a6c86e33SRafael J. Wysocki 	    !mwait_substates)
2093a6c86e33SRafael J. Wysocki 			return -ENODEV;
2094a6c86e33SRafael J. Wysocki 
2095a6c86e33SRafael J. Wysocki 	pr_debug("MWAIT substates: 0x%x\n", mwait_substates);
2096a6c86e33SRafael J. Wysocki 
2097a6c86e33SRafael J. Wysocki 	icpu = (const struct idle_cpu *)id->driver_data;
2098a6c86e33SRafael J. Wysocki 	if (icpu) {
2099a6c86e33SRafael J. Wysocki 		cpuidle_state_table = icpu->state_table;
21007f843dd7SRafael J. Wysocki 		auto_demotion_disable_flags = icpu->auto_demotion_disable_flags;
210139c184a6SArtem Bityutskiy 		if (icpu->disable_promotion_to_c1e)
210239c184a6SArtem Bityutskiy 			c1e_promotion = C1E_PROMOTION_DISABLE;
21033a5be9b8SRafael J. Wysocki 		if (icpu->use_acpi || force_use_acpi)
2104a6c86e33SRafael J. Wysocki 			intel_idle_acpi_cst_extract();
2105a6c86e33SRafael J. Wysocki 	} else if (!intel_idle_acpi_cst_extract()) {
2106a6c86e33SRafael J. Wysocki 		return -ENODEV;
2107a6c86e33SRafael J. Wysocki 	}
2108a6c86e33SRafael J. Wysocki 
2109a6c86e33SRafael J. Wysocki 	pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n",
2110a6c86e33SRafael J. Wysocki 		 boot_cpu_data.x86_model);
211126717172SLen Brown 
2112e9df69ccSRichard Cochran 	intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
2113533da74aSRafael J. Wysocki 	if (!intel_idle_cpuidle_devices)
2114e9df69ccSRichard Cochran 		return -ENOMEM;
2115e9df69ccSRichard Cochran 
21163d3a1ae9SRafael J. Wysocki 	intel_idle_cpuidle_driver_init(&intel_idle_driver);
21173d3a1ae9SRafael J. Wysocki 
211826717172SLen Brown 	retval = cpuidle_register_driver(&intel_idle_driver);
211926717172SLen Brown 	if (retval) {
21203735d524SKonrad Rzeszutek Wilk 		struct cpuidle_driver *drv = cpuidle_get_driver();
2121654d08a4SJoe Perches 		printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"),
21223735d524SKonrad Rzeszutek Wilk 		       drv ? drv->name : "none");
2123fb1013a0SSebastian Andrzej Siewior 		goto init_driver_fail;
212426717172SLen Brown 	}
212526717172SLen Brown 
2126fb1013a0SSebastian Andrzej Siewior 	retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
2127fb1013a0SSebastian Andrzej Siewior 				   intel_idle_cpu_online, NULL);
2128fb1013a0SSebastian Andrzej Siewior 	if (retval < 0)
2129fb1013a0SSebastian Andrzej Siewior 		goto hp_setup_fail;
213026717172SLen Brown 
213140ab82e0SRafael J. Wysocki 	pr_debug("Local APIC timer is reliable in %s\n",
2132dab20177SRafael J. Wysocki 		 boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1");
21332259a819SRichard Cochran 
213426717172SLen Brown 	return 0;
2135fb1013a0SSebastian Andrzej Siewior 
2136fb1013a0SSebastian Andrzej Siewior hp_setup_fail:
2137fb1013a0SSebastian Andrzej Siewior 	intel_idle_cpuidle_devices_uninit();
2138fb1013a0SSebastian Andrzej Siewior 	cpuidle_unregister_driver(&intel_idle_driver);
2139fb1013a0SSebastian Andrzej Siewior init_driver_fail:
2140fb1013a0SSebastian Andrzej Siewior 	free_percpu(intel_idle_cpuidle_devices);
2141fb1013a0SSebastian Andrzej Siewior 	return retval;
2142fb1013a0SSebastian Andrzej Siewior 
214326717172SLen Brown }
214402c4fae9SPaul Gortmaker device_initcall(intel_idle_init);
214526717172SLen Brown 
214602c4fae9SPaul Gortmaker /*
214702c4fae9SPaul Gortmaker  * We are not really modular, but we used to support that.  Meaning we also
214802c4fae9SPaul Gortmaker  * support "intel_idle.max_cstate=..." at boot and also a read-only export of
214902c4fae9SPaul Gortmaker  * it at /sys/module/intel_idle/parameters/max_cstate -- so using module_param
215002c4fae9SPaul Gortmaker  * is the easiest way (currently) to continue doing that.
215102c4fae9SPaul Gortmaker  */
215226717172SLen Brown module_param(max_cstate, int, 0444);
21534dcb78eeSRafael J. Wysocki /*
21544dcb78eeSRafael J. Wysocki  * The positions of the bits that are set in this number are the indices of the
21554dcb78eeSRafael J. Wysocki  * idle states to be disabled by default (as reflected by the names of the
21564dcb78eeSRafael J. Wysocki  * corresponding idle state directories in sysfs, "state0", "state1" ...
21574dcb78eeSRafael J. Wysocki  * "state<i>" ..., where <i> is the index of the given state).
21584dcb78eeSRafael J. Wysocki  */
21594dcb78eeSRafael J. Wysocki module_param_named(states_off, disabled_states_mask, uint, 0444);
21604dcb78eeSRafael J. Wysocki MODULE_PARM_DESC(states_off, "Mask of disabled idle states");
2161da0e58c0SArtem Bityutskiy /*
2162da0e58c0SArtem Bityutskiy  * Some platforms come with mutually exclusive C-states, so that if one is
2163da0e58c0SArtem Bityutskiy  * enabled, the other C-states must not be used. Example: C1 and C1E on
2164da0e58c0SArtem Bityutskiy  * Sapphire Rapids platform. This parameter allows for selecting the
2165da0e58c0SArtem Bityutskiy  * preferred C-states among the groups of mutually exclusive C-states - the
2166da0e58c0SArtem Bityutskiy  * selected C-states will be registered, the other C-states from the mutually
2167da0e58c0SArtem Bityutskiy  * exclusive group won't be registered. If the platform has no mutually
2168da0e58c0SArtem Bityutskiy  * exclusive C-states, this parameter has no effect.
2169da0e58c0SArtem Bityutskiy  */
2170da0e58c0SArtem Bityutskiy module_param_named(preferred_cstates, preferred_states_mask, uint, 0444);
2171da0e58c0SArtem Bityutskiy MODULE_PARM_DESC(preferred_cstates, "Mask of preferred idle states");
21724152379aSArtem Bityutskiy /*
21734152379aSArtem Bityutskiy  * Debugging option that forces the driver to enter all C-states with
21744152379aSArtem Bityutskiy  * interrupts enabled. Does not apply to C-states with
21754152379aSArtem Bityutskiy  * 'CPUIDLE_FLAG_INIT_XSTATE' and 'CPUIDLE_FLAG_IBRS' flags.
21764152379aSArtem Bityutskiy  */
21774152379aSArtem Bityutskiy module_param(force_irq_on, bool, 0444);
2178