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