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> 599f011293SChang S. Bae #include <asm/fpu/api.h> 6026717172SLen Brown 61317e5ec3SRafael J. Wysocki #define INTEL_IDLE_VERSION "0.5.1" 6226717172SLen Brown 6326717172SLen Brown static struct cpuidle_driver intel_idle_driver = { 6426717172SLen Brown .name = "intel_idle", 6526717172SLen Brown .owner = THIS_MODULE, 6626717172SLen Brown }; 6726717172SLen Brown /* intel_idle.max_cstate=0 disables driver */ 68137ecc77SLen Brown static int max_cstate = CPUIDLE_STATE_MAX - 1; 69bd446829SArtem Bityutskiy static unsigned int disabled_states_mask __read_mostly; 70bd446829SArtem Bityutskiy static unsigned int preferred_states_mask __read_mostly; 714152379aSArtem Bityutskiy static bool force_irq_on __read_mostly; 7226717172SLen Brown 736eb0443aSRafael J. Wysocki static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; 747f843dd7SRafael J. Wysocki 757f843dd7SRafael J. Wysocki static unsigned long auto_demotion_disable_flags; 7639c184a6SArtem Bityutskiy 7739c184a6SArtem Bityutskiy static enum { 7839c184a6SArtem Bityutskiy C1E_PROMOTION_PRESERVE, 7939c184a6SArtem Bityutskiy C1E_PROMOTION_ENABLE, 8039c184a6SArtem Bityutskiy C1E_PROMOTION_DISABLE 8139c184a6SArtem Bityutskiy } c1e_promotion = C1E_PROMOTION_PRESERVE; 827f843dd7SRafael J. Wysocki 83b66b8b9aSAndi Kleen struct idle_cpu { 84b66b8b9aSAndi Kleen struct cpuidle_state *state_table; 8526717172SLen Brown 8626717172SLen Brown /* 8714796fcaSLen Brown * Hardware C-state auto-demotion may not always be optimal. 8814796fcaSLen Brown * Indicate which enable bits to clear here. 8914796fcaSLen Brown */ 90b66b8b9aSAndi Kleen unsigned long auto_demotion_disable_flags; 918c058d53SLen Brown bool byt_auto_demotion_disable_flag; 9232e95180SLen Brown bool disable_promotion_to_c1e; 93bff8e60aSRafael J. Wysocki bool use_acpi; 94b66b8b9aSAndi Kleen }; 95b66b8b9aSAndi Kleen 967f843dd7SRafael J. Wysocki static const struct idle_cpu *icpu __initdata; 977f843dd7SRafael J. Wysocki static struct cpuidle_state *cpuidle_state_table __initdata; 9814796fcaSLen Brown 996eb0443aSRafael J. Wysocki static unsigned int mwait_substates __initdata; 1006eb0443aSRafael J. Wysocki 10114796fcaSLen Brown /* 102c227233aSArtem Bityutskiy * Enable interrupts before entering the C-state. On some platforms and for 103c227233aSArtem Bityutskiy * some C-states, this may measurably decrease interrupt latency. 104c227233aSArtem Bityutskiy */ 105c227233aSArtem Bityutskiy #define CPUIDLE_FLAG_IRQ_ENABLE BIT(14) 106c227233aSArtem Bityutskiy 107c227233aSArtem Bityutskiy /* 108bff8e60aSRafael J. Wysocki * Enable this state by default even if the ACPI _CST does not list it. 109bff8e60aSRafael J. Wysocki */ 110bff8e60aSRafael J. Wysocki #define CPUIDLE_FLAG_ALWAYS_ENABLE BIT(15) 111bff8e60aSRafael J. Wysocki 112bff8e60aSRafael J. Wysocki /* 113bf5835bcSPeter Zijlstra * Disable IBRS across idle (when KERNEL_IBRS), is exclusive vs IRQ_ENABLE 114bf5835bcSPeter Zijlstra * above. 115bf5835bcSPeter Zijlstra */ 116bf5835bcSPeter Zijlstra #define CPUIDLE_FLAG_IBRS BIT(16) 117bf5835bcSPeter Zijlstra 118bf5835bcSPeter Zijlstra /* 1199f011293SChang S. Bae * Initialize large xstate for the C6-state entrance. 1209f011293SChang S. Bae */ 1219f011293SChang S. Bae #define CPUIDLE_FLAG_INIT_XSTATE BIT(17) 1229f011293SChang S. Bae 1239f011293SChang S. Bae /* 124b1beab48SLen Brown * MWAIT takes an 8-bit "hint" in EAX "suggesting" 125b1beab48SLen Brown * the C-state (top nibble) and sub-state (bottom nibble) 126b1beab48SLen Brown * 0x00 means "MWAIT(C1)", 0x10 means "MWAIT(C2)" etc. 127b1beab48SLen Brown * 128b1beab48SLen Brown * We store the hint at the top of our "flags" for each state. 129b1beab48SLen Brown */ 130b1beab48SLen Brown #define flg2MWAIT(flags) (((flags) >> 24) & 0xFF) 131b1beab48SLen Brown #define MWAIT2flg(eax) ((eax & 0xFF) << 24) 132b1beab48SLen Brown 13332d4fd57SPeter Zijlstra static __always_inline int __intel_idle(struct cpuidle_device *dev, 13432d4fd57SPeter Zijlstra struct cpuidle_driver *drv, int index) 13532d4fd57SPeter Zijlstra { 13632d4fd57SPeter Zijlstra struct cpuidle_state *state = &drv->states[index]; 13732d4fd57SPeter Zijlstra unsigned long eax = flg2MWAIT(state->flags); 13832d4fd57SPeter Zijlstra unsigned long ecx = 1; /* break on interrupt flag */ 13932d4fd57SPeter Zijlstra 14032d4fd57SPeter Zijlstra mwait_idle_with_hints(eax, ecx); 14132d4fd57SPeter Zijlstra 14232d4fd57SPeter Zijlstra return index; 14332d4fd57SPeter Zijlstra } 14432d4fd57SPeter Zijlstra 14530a996fbSRafael J. Wysocki /** 14630a996fbSRafael J. Wysocki * intel_idle - Ask the processor to enter the given idle state. 14730a996fbSRafael J. Wysocki * @dev: cpuidle device of the target CPU. 14830a996fbSRafael J. Wysocki * @drv: cpuidle driver (assumed to point to intel_idle_driver). 14930a996fbSRafael J. Wysocki * @index: Target idle state index. 15030a996fbSRafael J. Wysocki * 15130a996fbSRafael J. Wysocki * Use the MWAIT instruction to notify the processor that the CPU represented by 15230a996fbSRafael J. Wysocki * @dev is idle and it can try to enter the idle state corresponding to @index. 15330a996fbSRafael J. Wysocki * 15430a996fbSRafael J. Wysocki * If the local APIC timer is not known to be reliable in the target idle state, 15530a996fbSRafael J. Wysocki * enable one-shot tick broadcasting for the target CPU before executing MWAIT. 15630a996fbSRafael J. Wysocki * 15730a996fbSRafael J. Wysocki * Must be called under local_irq_disable(). 15830a996fbSRafael J. Wysocki */ 15930a996fbSRafael J. Wysocki static __cpuidle int intel_idle(struct cpuidle_device *dev, 16030a996fbSRafael J. Wysocki struct cpuidle_driver *drv, int index) 16130a996fbSRafael J. Wysocki { 16232d4fd57SPeter Zijlstra return __intel_idle(dev, drv, index); 16332d4fd57SPeter Zijlstra } 16430a996fbSRafael J. Wysocki 16532d4fd57SPeter Zijlstra static __cpuidle int intel_idle_irq(struct cpuidle_device *dev, 16632d4fd57SPeter Zijlstra struct cpuidle_driver *drv, int index) 16732d4fd57SPeter Zijlstra { 16832d4fd57SPeter Zijlstra int ret; 169c227233aSArtem Bityutskiy 17032d4fd57SPeter Zijlstra raw_local_irq_enable(); 17132d4fd57SPeter Zijlstra ret = __intel_idle(dev, drv, index); 1726d9c7f51SPeter Zijlstra raw_local_irq_disable(); 17330a996fbSRafael J. Wysocki 17432d4fd57SPeter Zijlstra return ret; 17530a996fbSRafael J. Wysocki } 17630a996fbSRafael J. Wysocki 177bf5835bcSPeter Zijlstra static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev, 178bf5835bcSPeter Zijlstra struct cpuidle_driver *drv, int index) 179bf5835bcSPeter Zijlstra { 180bf5835bcSPeter Zijlstra bool smt_active = sched_smt_active(); 181bf5835bcSPeter Zijlstra u64 spec_ctrl = spec_ctrl_current(); 182bf5835bcSPeter Zijlstra int ret; 183bf5835bcSPeter Zijlstra 184bf5835bcSPeter Zijlstra if (smt_active) 1859b461a6fSPeter Zijlstra native_wrmsrl(MSR_IA32_SPEC_CTRL, 0); 186bf5835bcSPeter Zijlstra 187bf5835bcSPeter Zijlstra ret = __intel_idle(dev, drv, index); 188bf5835bcSPeter Zijlstra 189bf5835bcSPeter Zijlstra if (smt_active) 1909b461a6fSPeter Zijlstra native_wrmsrl(MSR_IA32_SPEC_CTRL, spec_ctrl); 191bf5835bcSPeter Zijlstra 192bf5835bcSPeter Zijlstra return ret; 193bf5835bcSPeter Zijlstra } 194bf5835bcSPeter Zijlstra 1959f011293SChang S. Bae static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev, 1969f011293SChang S. Bae struct cpuidle_driver *drv, int index) 1979f011293SChang S. Bae { 1989f011293SChang S. Bae fpu_idle_fpregs(); 1999f011293SChang S. Bae return __intel_idle(dev, drv, index); 2009f011293SChang S. Bae } 2019f011293SChang S. Bae 2022f3d08f0SArjan van de Ven static __always_inline int __intel_idle_hlt(struct cpuidle_device *dev, 2032f3d08f0SArjan van de Ven struct cpuidle_driver *drv, int index) 2042f3d08f0SArjan van de Ven { 2052f3d08f0SArjan van de Ven raw_safe_halt(); 2062f3d08f0SArjan van de Ven raw_local_irq_disable(); 2072f3d08f0SArjan van de Ven return index; 2082f3d08f0SArjan van de Ven } 2092f3d08f0SArjan van de Ven 2102f3d08f0SArjan van de Ven /** 2112f3d08f0SArjan van de Ven * intel_idle_hlt - Ask the processor to enter the given idle state using hlt. 2122f3d08f0SArjan van de Ven * @dev: cpuidle device of the target CPU. 2132f3d08f0SArjan van de Ven * @drv: cpuidle driver (assumed to point to intel_idle_driver). 2142f3d08f0SArjan van de Ven * @index: Target idle state index. 2152f3d08f0SArjan van de Ven * 2162f3d08f0SArjan van de Ven * Use the HLT instruction to notify the processor that the CPU represented by 2172f3d08f0SArjan van de Ven * @dev is idle and it can try to enter the idle state corresponding to @index. 2182f3d08f0SArjan van de Ven * 2192f3d08f0SArjan van de Ven * Must be called under local_irq_disable(). 2202f3d08f0SArjan van de Ven */ 2212f3d08f0SArjan van de Ven static __cpuidle int intel_idle_hlt(struct cpuidle_device *dev, 2222f3d08f0SArjan van de Ven struct cpuidle_driver *drv, int index) 2232f3d08f0SArjan van de Ven { 2242f3d08f0SArjan van de Ven return __intel_idle_hlt(dev, drv, index); 2252f3d08f0SArjan van de Ven } 2262f3d08f0SArjan van de Ven 2272f3d08f0SArjan van de Ven static __cpuidle int intel_idle_hlt_irq_on(struct cpuidle_device *dev, 2282f3d08f0SArjan van de Ven struct cpuidle_driver *drv, int index) 2292f3d08f0SArjan van de Ven { 2302f3d08f0SArjan van de Ven int ret; 2312f3d08f0SArjan van de Ven 2322f3d08f0SArjan van de Ven raw_local_irq_enable(); 2332f3d08f0SArjan van de Ven ret = __intel_idle_hlt(dev, drv, index); 2342f3d08f0SArjan van de Ven raw_local_irq_disable(); 2352f3d08f0SArjan van de Ven 2362f3d08f0SArjan van de Ven return ret; 2372f3d08f0SArjan van de Ven } 2382f3d08f0SArjan van de Ven 23930a996fbSRafael J. Wysocki /** 24030a996fbSRafael J. Wysocki * intel_idle_s2idle - Ask the processor to enter the given idle state. 24130a996fbSRafael J. Wysocki * @dev: cpuidle device of the target CPU. 24230a996fbSRafael J. Wysocki * @drv: cpuidle driver (assumed to point to intel_idle_driver). 24330a996fbSRafael J. Wysocki * @index: Target idle state index. 24430a996fbSRafael J. Wysocki * 24530a996fbSRafael J. Wysocki * Use the MWAIT instruction to notify the processor that the CPU represented by 24630a996fbSRafael J. Wysocki * @dev is idle and it can try to enter the idle state corresponding to @index. 24730a996fbSRafael J. Wysocki * 24830a996fbSRafael J. Wysocki * Invoked as a suspend-to-idle callback routine with frozen user space, frozen 24930a996fbSRafael J. Wysocki * scheduler tick and suspended scheduler clock on the target CPU. 25030a996fbSRafael J. Wysocki */ 251efe97112SNeal Liu static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev, 25230a996fbSRafael J. Wysocki struct cpuidle_driver *drv, int index) 25330a996fbSRafael J. Wysocki { 25430a996fbSRafael J. Wysocki unsigned long ecx = 1; /* break on interrupt flag */ 2559f011293SChang S. Bae struct cpuidle_state *state = &drv->states[index]; 2569f011293SChang S. Bae unsigned long eax = flg2MWAIT(state->flags); 2579f011293SChang S. Bae 2589f011293SChang S. Bae if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) 2599f011293SChang S. Bae fpu_idle_fpregs(); 26030a996fbSRafael J. Wysocki 26130a996fbSRafael J. Wysocki mwait_idle_with_hints(eax, ecx); 262efe97112SNeal Liu 263efe97112SNeal Liu return 0; 26430a996fbSRafael J. Wysocki } 26530a996fbSRafael J. Wysocki 266b1beab48SLen Brown /* 26726717172SLen Brown * States are indexed by the cstate number, 26826717172SLen Brown * which is also the index into the MWAIT hint array. 26926717172SLen Brown * Thus C0 is a dummy. 27026717172SLen Brown */ 271ab1a8522SRafael J. Wysocki static struct cpuidle_state nehalem_cstates[] __initdata = { 272e022e7ebSLen Brown { 273de09cdd0SLen Brown .name = "C1", 27426717172SLen Brown .desc = "MWAIT 0x00", 275b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 27626717172SLen Brown .exit_latency = 3, 27726717172SLen Brown .target_residency = 6, 2785fe2e527SRafael J. Wysocki .enter = &intel_idle, 27928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 280e022e7ebSLen Brown { 281de09cdd0SLen Brown .name = "C1E", 28232e95180SLen Brown .desc = "MWAIT 0x01", 283e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 28432e95180SLen Brown .exit_latency = 10, 28532e95180SLen Brown .target_residency = 20, 2865fe2e527SRafael J. Wysocki .enter = &intel_idle, 28728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 28832e95180SLen Brown { 289de09cdd0SLen Brown .name = "C3", 29026717172SLen Brown .desc = "MWAIT 0x10", 291b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 29226717172SLen Brown .exit_latency = 20, 29326717172SLen Brown .target_residency = 80, 2945fe2e527SRafael J. Wysocki .enter = &intel_idle, 29528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 296e022e7ebSLen Brown { 297de09cdd0SLen Brown .name = "C6", 29826717172SLen Brown .desc = "MWAIT 0x20", 299b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 30026717172SLen Brown .exit_latency = 200, 30126717172SLen Brown .target_residency = 800, 3025fe2e527SRafael J. Wysocki .enter = &intel_idle, 30328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 304e022e7ebSLen Brown { 305e022e7ebSLen Brown .enter = NULL } 30626717172SLen Brown }; 30726717172SLen Brown 308ab1a8522SRafael J. Wysocki static struct cpuidle_state snb_cstates[] __initdata = { 309e022e7ebSLen Brown { 310de09cdd0SLen Brown .name = "C1", 311d13780d4SLen Brown .desc = "MWAIT 0x00", 312b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 31332e95180SLen Brown .exit_latency = 2, 31432e95180SLen Brown .target_residency = 2, 3155fe2e527SRafael J. Wysocki .enter = &intel_idle, 31628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 31732e95180SLen Brown { 318de09cdd0SLen Brown .name = "C1E", 31932e95180SLen Brown .desc = "MWAIT 0x01", 320e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 32132e95180SLen Brown .exit_latency = 10, 32232e95180SLen Brown .target_residency = 20, 3235fe2e527SRafael J. Wysocki .enter = &intel_idle, 32428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 325e022e7ebSLen Brown { 326de09cdd0SLen Brown .name = "C3", 327d13780d4SLen Brown .desc = "MWAIT 0x10", 328b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 329d13780d4SLen Brown .exit_latency = 80, 330ddbd550dSLen Brown .target_residency = 211, 3315fe2e527SRafael J. Wysocki .enter = &intel_idle, 33228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 333e022e7ebSLen Brown { 334de09cdd0SLen Brown .name = "C6", 335d13780d4SLen Brown .desc = "MWAIT 0x20", 336b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 337d13780d4SLen Brown .exit_latency = 104, 338ddbd550dSLen Brown .target_residency = 345, 3395fe2e527SRafael J. Wysocki .enter = &intel_idle, 34028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 341e022e7ebSLen Brown { 342de09cdd0SLen Brown .name = "C7", 343d13780d4SLen Brown .desc = "MWAIT 0x30", 344b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 345d13780d4SLen Brown .exit_latency = 109, 346ddbd550dSLen Brown .target_residency = 345, 3475fe2e527SRafael J. Wysocki .enter = &intel_idle, 34828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 349e022e7ebSLen Brown { 350e022e7ebSLen Brown .enter = NULL } 351d13780d4SLen Brown }; 352d13780d4SLen Brown 353ab1a8522SRafael J. Wysocki static struct cpuidle_state byt_cstates[] __initdata = { 354718987d6SLen Brown { 355de09cdd0SLen Brown .name = "C1", 356718987d6SLen Brown .desc = "MWAIT 0x00", 357b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 358718987d6SLen Brown .exit_latency = 1, 359718987d6SLen Brown .target_residency = 1, 3605fe2e527SRafael J. Wysocki .enter = &intel_idle, 36128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 362718987d6SLen Brown { 363de09cdd0SLen Brown .name = "C6N", 364718987d6SLen Brown .desc = "MWAIT 0x58", 365b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, 366d7ef7671SLen Brown .exit_latency = 300, 367718987d6SLen Brown .target_residency = 275, 3685fe2e527SRafael J. Wysocki .enter = &intel_idle, 36928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 370718987d6SLen Brown { 371de09cdd0SLen Brown .name = "C6S", 372718987d6SLen Brown .desc = "MWAIT 0x52", 373b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 374d7ef7671SLen Brown .exit_latency = 500, 375718987d6SLen Brown .target_residency = 560, 3765fe2e527SRafael J. Wysocki .enter = &intel_idle, 37728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 378718987d6SLen Brown { 379de09cdd0SLen Brown .name = "C7", 380718987d6SLen Brown .desc = "MWAIT 0x60", 381b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 382718987d6SLen Brown .exit_latency = 1200, 383d7ef7671SLen Brown .target_residency = 4000, 3845fe2e527SRafael J. Wysocki .enter = &intel_idle, 38528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 386718987d6SLen Brown { 387de09cdd0SLen Brown .name = "C7S", 388718987d6SLen Brown .desc = "MWAIT 0x64", 389b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, 390718987d6SLen Brown .exit_latency = 10000, 391718987d6SLen Brown .target_residency = 20000, 3925fe2e527SRafael J. Wysocki .enter = &intel_idle, 39328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 394718987d6SLen Brown { 395718987d6SLen Brown .enter = NULL } 396718987d6SLen Brown }; 397718987d6SLen Brown 398ab1a8522SRafael J. Wysocki static struct cpuidle_state cht_cstates[] __initdata = { 399cab07a56SLen Brown { 400de09cdd0SLen Brown .name = "C1", 401cab07a56SLen Brown .desc = "MWAIT 0x00", 402cab07a56SLen Brown .flags = MWAIT2flg(0x00), 403cab07a56SLen Brown .exit_latency = 1, 404cab07a56SLen Brown .target_residency = 1, 405cab07a56SLen Brown .enter = &intel_idle, 40628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 407cab07a56SLen Brown { 408de09cdd0SLen Brown .name = "C6N", 409cab07a56SLen Brown .desc = "MWAIT 0x58", 410cab07a56SLen Brown .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, 411cab07a56SLen Brown .exit_latency = 80, 412cab07a56SLen Brown .target_residency = 275, 413cab07a56SLen Brown .enter = &intel_idle, 41428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 415cab07a56SLen Brown { 416de09cdd0SLen Brown .name = "C6S", 417cab07a56SLen Brown .desc = "MWAIT 0x52", 418cab07a56SLen Brown .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 419cab07a56SLen Brown .exit_latency = 200, 420cab07a56SLen Brown .target_residency = 560, 421cab07a56SLen Brown .enter = &intel_idle, 42228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 423cab07a56SLen Brown { 424de09cdd0SLen Brown .name = "C7", 425cab07a56SLen Brown .desc = "MWAIT 0x60", 426cab07a56SLen Brown .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 427cab07a56SLen Brown .exit_latency = 1200, 428cab07a56SLen Brown .target_residency = 4000, 429cab07a56SLen Brown .enter = &intel_idle, 43028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 431cab07a56SLen Brown { 432de09cdd0SLen Brown .name = "C7S", 433cab07a56SLen Brown .desc = "MWAIT 0x64", 434cab07a56SLen Brown .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, 435cab07a56SLen Brown .exit_latency = 10000, 436cab07a56SLen Brown .target_residency = 20000, 437cab07a56SLen Brown .enter = &intel_idle, 43828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 439cab07a56SLen Brown { 440cab07a56SLen Brown .enter = NULL } 441cab07a56SLen Brown }; 442cab07a56SLen Brown 443ab1a8522SRafael J. Wysocki static struct cpuidle_state ivb_cstates[] __initdata = { 444e022e7ebSLen Brown { 445de09cdd0SLen Brown .name = "C1", 4466edab08cSLen Brown .desc = "MWAIT 0x00", 447b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 4486edab08cSLen Brown .exit_latency = 1, 4496edab08cSLen Brown .target_residency = 1, 4505fe2e527SRafael J. Wysocki .enter = &intel_idle, 45128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 452e022e7ebSLen Brown { 453de09cdd0SLen Brown .name = "C1E", 45432e95180SLen Brown .desc = "MWAIT 0x01", 455e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 45632e95180SLen Brown .exit_latency = 10, 45732e95180SLen Brown .target_residency = 20, 4585fe2e527SRafael J. Wysocki .enter = &intel_idle, 45928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 46032e95180SLen Brown { 461de09cdd0SLen Brown .name = "C3", 4626edab08cSLen Brown .desc = "MWAIT 0x10", 463b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 4646edab08cSLen Brown .exit_latency = 59, 4656edab08cSLen Brown .target_residency = 156, 4665fe2e527SRafael J. Wysocki .enter = &intel_idle, 46728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 468e022e7ebSLen Brown { 469de09cdd0SLen Brown .name = "C6", 4706edab08cSLen Brown .desc = "MWAIT 0x20", 471b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 4726edab08cSLen Brown .exit_latency = 80, 4736edab08cSLen Brown .target_residency = 300, 4745fe2e527SRafael J. Wysocki .enter = &intel_idle, 47528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 476e022e7ebSLen Brown { 477de09cdd0SLen Brown .name = "C7", 4786edab08cSLen Brown .desc = "MWAIT 0x30", 479b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 4806edab08cSLen Brown .exit_latency = 87, 4816edab08cSLen Brown .target_residency = 300, 4825fe2e527SRafael J. Wysocki .enter = &intel_idle, 48328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 484e022e7ebSLen Brown { 485e022e7ebSLen Brown .enter = NULL } 4866edab08cSLen Brown }; 4876edab08cSLen Brown 488ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates[] __initdata = { 4890138d8f0SLen Brown { 490de09cdd0SLen Brown .name = "C1", 4910138d8f0SLen Brown .desc = "MWAIT 0x00", 492b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 4930138d8f0SLen Brown .exit_latency = 1, 4940138d8f0SLen Brown .target_residency = 1, 4955fe2e527SRafael J. Wysocki .enter = &intel_idle, 49628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 4970138d8f0SLen Brown { 498de09cdd0SLen Brown .name = "C1E", 4990138d8f0SLen Brown .desc = "MWAIT 0x01", 500e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 5010138d8f0SLen Brown .exit_latency = 10, 5020138d8f0SLen Brown .target_residency = 80, 5035fe2e527SRafael J. Wysocki .enter = &intel_idle, 50428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5050138d8f0SLen Brown { 506de09cdd0SLen Brown .name = "C3", 5070138d8f0SLen Brown .desc = "MWAIT 0x10", 508b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 5090138d8f0SLen Brown .exit_latency = 59, 5100138d8f0SLen Brown .target_residency = 156, 5115fe2e527SRafael J. Wysocki .enter = &intel_idle, 51228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5130138d8f0SLen Brown { 514de09cdd0SLen Brown .name = "C6", 5150138d8f0SLen Brown .desc = "MWAIT 0x20", 516b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 5170138d8f0SLen Brown .exit_latency = 82, 5180138d8f0SLen Brown .target_residency = 300, 5195fe2e527SRafael J. Wysocki .enter = &intel_idle, 52028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5210138d8f0SLen Brown { 5220138d8f0SLen Brown .enter = NULL } 5230138d8f0SLen Brown }; 5240138d8f0SLen Brown 525ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates_4s[] __initdata = { 5260138d8f0SLen Brown { 527de09cdd0SLen Brown .name = "C1", 5280138d8f0SLen Brown .desc = "MWAIT 0x00", 529b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 5300138d8f0SLen Brown .exit_latency = 1, 5310138d8f0SLen Brown .target_residency = 1, 5325fe2e527SRafael J. Wysocki .enter = &intel_idle, 53328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5340138d8f0SLen Brown { 535de09cdd0SLen Brown .name = "C1E", 5360138d8f0SLen Brown .desc = "MWAIT 0x01", 537e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 5380138d8f0SLen Brown .exit_latency = 10, 5390138d8f0SLen Brown .target_residency = 250, 5405fe2e527SRafael J. Wysocki .enter = &intel_idle, 54128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5420138d8f0SLen Brown { 543de09cdd0SLen Brown .name = "C3", 5440138d8f0SLen Brown .desc = "MWAIT 0x10", 545b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 5460138d8f0SLen Brown .exit_latency = 59, 5470138d8f0SLen Brown .target_residency = 300, 5485fe2e527SRafael J. Wysocki .enter = &intel_idle, 54928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5500138d8f0SLen Brown { 551de09cdd0SLen Brown .name = "C6", 5520138d8f0SLen Brown .desc = "MWAIT 0x20", 553b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 5540138d8f0SLen Brown .exit_latency = 84, 5550138d8f0SLen Brown .target_residency = 400, 5565fe2e527SRafael J. Wysocki .enter = &intel_idle, 55728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5580138d8f0SLen Brown { 5590138d8f0SLen Brown .enter = NULL } 5600138d8f0SLen Brown }; 5610138d8f0SLen Brown 562ab1a8522SRafael J. Wysocki static struct cpuidle_state ivt_cstates_8s[] __initdata = { 5630138d8f0SLen Brown { 564de09cdd0SLen Brown .name = "C1", 5650138d8f0SLen Brown .desc = "MWAIT 0x00", 566b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 5670138d8f0SLen Brown .exit_latency = 1, 5680138d8f0SLen Brown .target_residency = 1, 5695fe2e527SRafael J. Wysocki .enter = &intel_idle, 57028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5710138d8f0SLen Brown { 572de09cdd0SLen Brown .name = "C1E", 5730138d8f0SLen Brown .desc = "MWAIT 0x01", 574e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 5750138d8f0SLen Brown .exit_latency = 10, 5760138d8f0SLen Brown .target_residency = 500, 5775fe2e527SRafael J. Wysocki .enter = &intel_idle, 57828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5790138d8f0SLen Brown { 580de09cdd0SLen Brown .name = "C3", 5810138d8f0SLen Brown .desc = "MWAIT 0x10", 582b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 5830138d8f0SLen Brown .exit_latency = 59, 5840138d8f0SLen Brown .target_residency = 600, 5855fe2e527SRafael J. Wysocki .enter = &intel_idle, 58628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5870138d8f0SLen Brown { 588de09cdd0SLen Brown .name = "C6", 5890138d8f0SLen Brown .desc = "MWAIT 0x20", 590b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 5910138d8f0SLen Brown .exit_latency = 88, 5920138d8f0SLen Brown .target_residency = 700, 5935fe2e527SRafael J. Wysocki .enter = &intel_idle, 59428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 5950138d8f0SLen Brown { 5960138d8f0SLen Brown .enter = NULL } 5970138d8f0SLen Brown }; 5980138d8f0SLen Brown 599ab1a8522SRafael J. Wysocki static struct cpuidle_state hsw_cstates[] __initdata = { 600e022e7ebSLen Brown { 601de09cdd0SLen Brown .name = "C1", 60285a4d2d4SLen Brown .desc = "MWAIT 0x00", 603b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 60485a4d2d4SLen Brown .exit_latency = 2, 60585a4d2d4SLen Brown .target_residency = 2, 6065fe2e527SRafael J. Wysocki .enter = &intel_idle, 60728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 608e022e7ebSLen Brown { 609de09cdd0SLen Brown .name = "C1E", 61032e95180SLen Brown .desc = "MWAIT 0x01", 611e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 61232e95180SLen Brown .exit_latency = 10, 61332e95180SLen Brown .target_residency = 20, 6145fe2e527SRafael J. Wysocki .enter = &intel_idle, 61528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 61632e95180SLen Brown { 617de09cdd0SLen Brown .name = "C3", 61885a4d2d4SLen Brown .desc = "MWAIT 0x10", 619b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 62085a4d2d4SLen Brown .exit_latency = 33, 62185a4d2d4SLen Brown .target_residency = 100, 6225fe2e527SRafael J. Wysocki .enter = &intel_idle, 62328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 624e022e7ebSLen Brown { 625de09cdd0SLen Brown .name = "C6", 62685a4d2d4SLen Brown .desc = "MWAIT 0x20", 627b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 62885a4d2d4SLen Brown .exit_latency = 133, 62985a4d2d4SLen Brown .target_residency = 400, 6305fe2e527SRafael J. Wysocki .enter = &intel_idle, 63128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 632e022e7ebSLen Brown { 633de09cdd0SLen Brown .name = "C7s", 63485a4d2d4SLen Brown .desc = "MWAIT 0x32", 635b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED, 63685a4d2d4SLen Brown .exit_latency = 166, 63785a4d2d4SLen Brown .target_residency = 500, 6385fe2e527SRafael J. Wysocki .enter = &intel_idle, 63928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 640e022e7ebSLen Brown { 641de09cdd0SLen Brown .name = "C8", 64286239cebSLen Brown .desc = "MWAIT 0x40", 643b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 64486239cebSLen Brown .exit_latency = 300, 64586239cebSLen Brown .target_residency = 900, 6465fe2e527SRafael J. Wysocki .enter = &intel_idle, 64728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 64886239cebSLen Brown { 649de09cdd0SLen Brown .name = "C9", 65086239cebSLen Brown .desc = "MWAIT 0x50", 651b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, 65286239cebSLen Brown .exit_latency = 600, 65386239cebSLen Brown .target_residency = 1800, 6545fe2e527SRafael J. Wysocki .enter = &intel_idle, 65528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 65686239cebSLen Brown { 657de09cdd0SLen Brown .name = "C10", 65886239cebSLen Brown .desc = "MWAIT 0x60", 659b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 66086239cebSLen Brown .exit_latency = 2600, 66186239cebSLen Brown .target_residency = 7700, 6625fe2e527SRafael J. Wysocki .enter = &intel_idle, 66328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 66486239cebSLen Brown { 665e022e7ebSLen Brown .enter = NULL } 66685a4d2d4SLen Brown }; 667ab1a8522SRafael J. Wysocki static struct cpuidle_state bdw_cstates[] __initdata = { 668a138b568SLen Brown { 669de09cdd0SLen Brown .name = "C1", 670a138b568SLen Brown .desc = "MWAIT 0x00", 671b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 672a138b568SLen Brown .exit_latency = 2, 673a138b568SLen Brown .target_residency = 2, 6745fe2e527SRafael J. Wysocki .enter = &intel_idle, 67528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 676a138b568SLen Brown { 677de09cdd0SLen Brown .name = "C1E", 678a138b568SLen Brown .desc = "MWAIT 0x01", 679e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 680a138b568SLen Brown .exit_latency = 10, 681a138b568SLen Brown .target_residency = 20, 6825fe2e527SRafael J. Wysocki .enter = &intel_idle, 68328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 684a138b568SLen Brown { 685de09cdd0SLen Brown .name = "C3", 686a138b568SLen Brown .desc = "MWAIT 0x10", 687b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 688a138b568SLen Brown .exit_latency = 40, 689a138b568SLen Brown .target_residency = 100, 6905fe2e527SRafael J. Wysocki .enter = &intel_idle, 69128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 692a138b568SLen Brown { 693de09cdd0SLen Brown .name = "C6", 694a138b568SLen Brown .desc = "MWAIT 0x20", 695b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 696a138b568SLen Brown .exit_latency = 133, 697a138b568SLen Brown .target_residency = 400, 6985fe2e527SRafael J. Wysocki .enter = &intel_idle, 69928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 700a138b568SLen Brown { 701de09cdd0SLen Brown .name = "C7s", 702a138b568SLen Brown .desc = "MWAIT 0x32", 703b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED, 704a138b568SLen Brown .exit_latency = 166, 705a138b568SLen Brown .target_residency = 500, 7065fe2e527SRafael J. Wysocki .enter = &intel_idle, 70728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 708a138b568SLen Brown { 709de09cdd0SLen Brown .name = "C8", 710a138b568SLen Brown .desc = "MWAIT 0x40", 711b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 712a138b568SLen Brown .exit_latency = 300, 713a138b568SLen Brown .target_residency = 900, 7145fe2e527SRafael J. Wysocki .enter = &intel_idle, 71528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 716a138b568SLen Brown { 717de09cdd0SLen Brown .name = "C9", 718a138b568SLen Brown .desc = "MWAIT 0x50", 719b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, 720a138b568SLen Brown .exit_latency = 600, 721a138b568SLen Brown .target_residency = 1800, 7225fe2e527SRafael J. Wysocki .enter = &intel_idle, 72328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 724a138b568SLen Brown { 725de09cdd0SLen Brown .name = "C10", 726a138b568SLen Brown .desc = "MWAIT 0x60", 727b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 728a138b568SLen Brown .exit_latency = 2600, 729a138b568SLen Brown .target_residency = 7700, 7305fe2e527SRafael J. Wysocki .enter = &intel_idle, 73128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 732a138b568SLen Brown { 733a138b568SLen Brown .enter = NULL } 734a138b568SLen Brown }; 73585a4d2d4SLen Brown 736ab1a8522SRafael J. Wysocki static struct cpuidle_state skl_cstates[] __initdata = { 737493f133fSLen Brown { 738de09cdd0SLen Brown .name = "C1", 739493f133fSLen Brown .desc = "MWAIT 0x00", 740493f133fSLen Brown .flags = MWAIT2flg(0x00), 741493f133fSLen Brown .exit_latency = 2, 742493f133fSLen Brown .target_residency = 2, 743493f133fSLen Brown .enter = &intel_idle, 74428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 745493f133fSLen Brown { 746de09cdd0SLen Brown .name = "C1E", 747493f133fSLen Brown .desc = "MWAIT 0x01", 748e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 749493f133fSLen Brown .exit_latency = 10, 750493f133fSLen Brown .target_residency = 20, 751493f133fSLen Brown .enter = &intel_idle, 75228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 753493f133fSLen Brown { 754de09cdd0SLen Brown .name = "C3", 755493f133fSLen Brown .desc = "MWAIT 0x10", 756493f133fSLen Brown .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 757493f133fSLen Brown .exit_latency = 70, 758493f133fSLen Brown .target_residency = 100, 759493f133fSLen Brown .enter = &intel_idle, 76028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 761493f133fSLen Brown { 762de09cdd0SLen Brown .name = "C6", 763493f133fSLen Brown .desc = "MWAIT 0x20", 764bf5835bcSPeter Zijlstra .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 765135919a3SLen Brown .exit_latency = 85, 766493f133fSLen Brown .target_residency = 200, 767493f133fSLen Brown .enter = &intel_idle, 76828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 769493f133fSLen Brown { 770de09cdd0SLen Brown .name = "C7s", 771493f133fSLen Brown .desc = "MWAIT 0x33", 772bf5835bcSPeter Zijlstra .flags = MWAIT2flg(0x33) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 773493f133fSLen Brown .exit_latency = 124, 774493f133fSLen Brown .target_residency = 800, 775493f133fSLen Brown .enter = &intel_idle, 77628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 777493f133fSLen Brown { 778de09cdd0SLen Brown .name = "C8", 779493f133fSLen Brown .desc = "MWAIT 0x40", 780bf5835bcSPeter Zijlstra .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 781135919a3SLen Brown .exit_latency = 200, 782493f133fSLen Brown .target_residency = 800, 783493f133fSLen Brown .enter = &intel_idle, 78428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 785493f133fSLen Brown { 786de09cdd0SLen Brown .name = "C9", 787135919a3SLen Brown .desc = "MWAIT 0x50", 788bf5835bcSPeter Zijlstra .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 789135919a3SLen Brown .exit_latency = 480, 790135919a3SLen Brown .target_residency = 5000, 791135919a3SLen Brown .enter = &intel_idle, 79228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 793135919a3SLen Brown { 794de09cdd0SLen Brown .name = "C10", 795493f133fSLen Brown .desc = "MWAIT 0x60", 796bf5835bcSPeter Zijlstra .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 797493f133fSLen Brown .exit_latency = 890, 798493f133fSLen Brown .target_residency = 5000, 799493f133fSLen Brown .enter = &intel_idle, 80028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 801493f133fSLen Brown { 802493f133fSLen Brown .enter = NULL } 803493f133fSLen Brown }; 804493f133fSLen Brown 805ab1a8522SRafael J. Wysocki static struct cpuidle_state skx_cstates[] __initdata = { 806f9e71657SLen Brown { 807de09cdd0SLen Brown .name = "C1", 808f9e71657SLen Brown .desc = "MWAIT 0x00", 809c227233aSArtem Bityutskiy .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE, 810f9e71657SLen Brown .exit_latency = 2, 811f9e71657SLen Brown .target_residency = 2, 812f9e71657SLen Brown .enter = &intel_idle, 81328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 814f9e71657SLen Brown { 815de09cdd0SLen Brown .name = "C1E", 816f9e71657SLen Brown .desc = "MWAIT 0x01", 817e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 818f9e71657SLen Brown .exit_latency = 10, 819f9e71657SLen Brown .target_residency = 20, 820f9e71657SLen Brown .enter = &intel_idle, 82128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 822f9e71657SLen Brown { 823de09cdd0SLen Brown .name = "C6", 824f9e71657SLen Brown .desc = "MWAIT 0x20", 825bf5835bcSPeter Zijlstra .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS, 826f9e71657SLen Brown .exit_latency = 133, 827f9e71657SLen Brown .target_residency = 600, 828f9e71657SLen Brown .enter = &intel_idle, 82928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 830f9e71657SLen Brown { 831f9e71657SLen Brown .enter = NULL } 832f9e71657SLen Brown }; 833f9e71657SLen Brown 834a472ad2bSChen Yu static struct cpuidle_state icx_cstates[] __initdata = { 835a472ad2bSChen Yu { 836a472ad2bSChen Yu .name = "C1", 837a472ad2bSChen Yu .desc = "MWAIT 0x00", 838c227233aSArtem Bityutskiy .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE, 839a472ad2bSChen Yu .exit_latency = 1, 840a472ad2bSChen Yu .target_residency = 1, 841a472ad2bSChen Yu .enter = &intel_idle, 842a472ad2bSChen Yu .enter_s2idle = intel_idle_s2idle, }, 843a472ad2bSChen Yu { 844a472ad2bSChen Yu .name = "C1E", 845a472ad2bSChen Yu .desc = "MWAIT 0x01", 846a472ad2bSChen Yu .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 847a472ad2bSChen Yu .exit_latency = 4, 848a472ad2bSChen Yu .target_residency = 4, 849a472ad2bSChen Yu .enter = &intel_idle, 850a472ad2bSChen Yu .enter_s2idle = intel_idle_s2idle, }, 851a472ad2bSChen Yu { 852a472ad2bSChen Yu .name = "C6", 853a472ad2bSChen Yu .desc = "MWAIT 0x20", 854a472ad2bSChen Yu .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 855d484b8bfSArtem Bityutskiy .exit_latency = 170, 856d484b8bfSArtem Bityutskiy .target_residency = 600, 857a472ad2bSChen Yu .enter = &intel_idle, 858a472ad2bSChen Yu .enter_s2idle = intel_idle_s2idle, }, 859a472ad2bSChen Yu { 860a472ad2bSChen Yu .enter = NULL } 861a472ad2bSChen Yu }; 862a472ad2bSChen Yu 8639edf3c0fSArtem Bityutskiy /* 864d1cf8bbfSZhang Rui * On AlderLake C1 has to be disabled if C1E is enabled, and vice versa. 865d1cf8bbfSZhang Rui * C1E is enabled only if "C1E promotion" bit is set in MSR_IA32_POWER_CTL. 866d1cf8bbfSZhang Rui * But in this case there is effectively no C1, because C1 requests are 867d1cf8bbfSZhang Rui * promoted to C1E. If the "C1E promotion" bit is cleared, then both C1 868d1cf8bbfSZhang Rui * and C1E requests end up with C1, so there is effectively no C1E. 869d1cf8bbfSZhang Rui * 870d1cf8bbfSZhang Rui * By default we enable C1E and disable C1 by marking it with 871d1cf8bbfSZhang Rui * 'CPUIDLE_FLAG_UNUSABLE'. 872d1cf8bbfSZhang Rui */ 873d1cf8bbfSZhang Rui static struct cpuidle_state adl_cstates[] __initdata = { 874d1cf8bbfSZhang Rui { 875d1cf8bbfSZhang Rui .name = "C1", 876d1cf8bbfSZhang Rui .desc = "MWAIT 0x00", 877d1cf8bbfSZhang Rui .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE, 878d1cf8bbfSZhang Rui .exit_latency = 1, 879d1cf8bbfSZhang Rui .target_residency = 1, 880d1cf8bbfSZhang Rui .enter = &intel_idle, 881d1cf8bbfSZhang Rui .enter_s2idle = intel_idle_s2idle, }, 882d1cf8bbfSZhang Rui { 883d1cf8bbfSZhang Rui .name = "C1E", 884d1cf8bbfSZhang Rui .desc = "MWAIT 0x01", 885d1cf8bbfSZhang Rui .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 886d1cf8bbfSZhang Rui .exit_latency = 2, 887d1cf8bbfSZhang Rui .target_residency = 4, 888d1cf8bbfSZhang Rui .enter = &intel_idle, 889d1cf8bbfSZhang Rui .enter_s2idle = intel_idle_s2idle, }, 890d1cf8bbfSZhang Rui { 891d1cf8bbfSZhang Rui .name = "C6", 892d1cf8bbfSZhang Rui .desc = "MWAIT 0x20", 893d1cf8bbfSZhang Rui .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 894d1cf8bbfSZhang Rui .exit_latency = 220, 895d1cf8bbfSZhang Rui .target_residency = 600, 896d1cf8bbfSZhang Rui .enter = &intel_idle, 897d1cf8bbfSZhang Rui .enter_s2idle = intel_idle_s2idle, }, 898d1cf8bbfSZhang Rui { 899d1cf8bbfSZhang Rui .name = "C8", 900d1cf8bbfSZhang Rui .desc = "MWAIT 0x40", 901d1cf8bbfSZhang Rui .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 902d1cf8bbfSZhang Rui .exit_latency = 280, 903d1cf8bbfSZhang Rui .target_residency = 800, 904d1cf8bbfSZhang Rui .enter = &intel_idle, 905d1cf8bbfSZhang Rui .enter_s2idle = intel_idle_s2idle, }, 906d1cf8bbfSZhang Rui { 907d1cf8bbfSZhang Rui .name = "C10", 908d1cf8bbfSZhang Rui .desc = "MWAIT 0x60", 909d1cf8bbfSZhang Rui .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 910d1cf8bbfSZhang Rui .exit_latency = 680, 911d1cf8bbfSZhang Rui .target_residency = 2000, 912d1cf8bbfSZhang Rui .enter = &intel_idle, 913d1cf8bbfSZhang Rui .enter_s2idle = intel_idle_s2idle, }, 914d1cf8bbfSZhang Rui { 915d1cf8bbfSZhang Rui .enter = NULL } 916d1cf8bbfSZhang Rui }; 917d1cf8bbfSZhang Rui 918d1cf8bbfSZhang Rui static struct cpuidle_state adl_l_cstates[] __initdata = { 919d1cf8bbfSZhang Rui { 920d1cf8bbfSZhang Rui .name = "C1", 921d1cf8bbfSZhang Rui .desc = "MWAIT 0x00", 922d1cf8bbfSZhang Rui .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE, 923d1cf8bbfSZhang Rui .exit_latency = 1, 924d1cf8bbfSZhang Rui .target_residency = 1, 925d1cf8bbfSZhang Rui .enter = &intel_idle, 926d1cf8bbfSZhang Rui .enter_s2idle = intel_idle_s2idle, }, 927d1cf8bbfSZhang Rui { 928d1cf8bbfSZhang Rui .name = "C1E", 929d1cf8bbfSZhang Rui .desc = "MWAIT 0x01", 930d1cf8bbfSZhang Rui .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 931d1cf8bbfSZhang Rui .exit_latency = 2, 932d1cf8bbfSZhang Rui .target_residency = 4, 933d1cf8bbfSZhang Rui .enter = &intel_idle, 934d1cf8bbfSZhang Rui .enter_s2idle = intel_idle_s2idle, }, 935d1cf8bbfSZhang Rui { 936d1cf8bbfSZhang Rui .name = "C6", 937d1cf8bbfSZhang Rui .desc = "MWAIT 0x20", 938d1cf8bbfSZhang Rui .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 939d1cf8bbfSZhang Rui .exit_latency = 170, 940d1cf8bbfSZhang Rui .target_residency = 500, 941d1cf8bbfSZhang Rui .enter = &intel_idle, 942d1cf8bbfSZhang Rui .enter_s2idle = intel_idle_s2idle, }, 943d1cf8bbfSZhang Rui { 944d1cf8bbfSZhang Rui .name = "C8", 945d1cf8bbfSZhang Rui .desc = "MWAIT 0x40", 946d1cf8bbfSZhang Rui .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 947d1cf8bbfSZhang Rui .exit_latency = 200, 948d1cf8bbfSZhang Rui .target_residency = 600, 949d1cf8bbfSZhang Rui .enter = &intel_idle, 950d1cf8bbfSZhang Rui .enter_s2idle = intel_idle_s2idle, }, 951d1cf8bbfSZhang Rui { 952d1cf8bbfSZhang Rui .name = "C10", 953d1cf8bbfSZhang Rui .desc = "MWAIT 0x60", 954d1cf8bbfSZhang Rui .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 955d1cf8bbfSZhang Rui .exit_latency = 230, 956d1cf8bbfSZhang Rui .target_residency = 700, 957d1cf8bbfSZhang Rui .enter = &intel_idle, 958d1cf8bbfSZhang Rui .enter_s2idle = intel_idle_s2idle, }, 959d1cf8bbfSZhang Rui { 960d1cf8bbfSZhang Rui .enter = NULL } 961d1cf8bbfSZhang Rui }; 962d1cf8bbfSZhang Rui 96365c0c236SZhang Rui static struct cpuidle_state adl_n_cstates[] __initdata = { 96465c0c236SZhang Rui { 96565c0c236SZhang Rui .name = "C1", 96665c0c236SZhang Rui .desc = "MWAIT 0x00", 96765c0c236SZhang Rui .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE, 96865c0c236SZhang Rui .exit_latency = 1, 96965c0c236SZhang Rui .target_residency = 1, 97065c0c236SZhang Rui .enter = &intel_idle, 97165c0c236SZhang Rui .enter_s2idle = intel_idle_s2idle, }, 97265c0c236SZhang Rui { 97365c0c236SZhang Rui .name = "C1E", 97465c0c236SZhang Rui .desc = "MWAIT 0x01", 97565c0c236SZhang Rui .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 97665c0c236SZhang Rui .exit_latency = 2, 97765c0c236SZhang Rui .target_residency = 4, 97865c0c236SZhang Rui .enter = &intel_idle, 97965c0c236SZhang Rui .enter_s2idle = intel_idle_s2idle, }, 98065c0c236SZhang Rui { 98165c0c236SZhang Rui .name = "C6", 98265c0c236SZhang Rui .desc = "MWAIT 0x20", 98365c0c236SZhang Rui .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 98465c0c236SZhang Rui .exit_latency = 195, 98565c0c236SZhang Rui .target_residency = 585, 98665c0c236SZhang Rui .enter = &intel_idle, 98765c0c236SZhang Rui .enter_s2idle = intel_idle_s2idle, }, 98865c0c236SZhang Rui { 98965c0c236SZhang Rui .name = "C8", 99065c0c236SZhang Rui .desc = "MWAIT 0x40", 99165c0c236SZhang Rui .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 99265c0c236SZhang Rui .exit_latency = 260, 99365c0c236SZhang Rui .target_residency = 1040, 99465c0c236SZhang Rui .enter = &intel_idle, 99565c0c236SZhang Rui .enter_s2idle = intel_idle_s2idle, }, 99665c0c236SZhang Rui { 99765c0c236SZhang Rui .name = "C10", 99865c0c236SZhang Rui .desc = "MWAIT 0x60", 99965c0c236SZhang Rui .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 100065c0c236SZhang Rui .exit_latency = 660, 100165c0c236SZhang Rui .target_residency = 1980, 100265c0c236SZhang Rui .enter = &intel_idle, 100365c0c236SZhang Rui .enter_s2idle = intel_idle_s2idle, }, 100465c0c236SZhang Rui { 100565c0c236SZhang Rui .enter = NULL } 100665c0c236SZhang Rui }; 100765c0c236SZhang Rui 10089edf3c0fSArtem Bityutskiy static struct cpuidle_state spr_cstates[] __initdata = { 10099edf3c0fSArtem Bityutskiy { 10109edf3c0fSArtem Bityutskiy .name = "C1", 10119edf3c0fSArtem Bityutskiy .desc = "MWAIT 0x00", 10129edf3c0fSArtem Bityutskiy .flags = MWAIT2flg(0x00), 10139edf3c0fSArtem Bityutskiy .exit_latency = 1, 10149edf3c0fSArtem Bityutskiy .target_residency = 1, 10159edf3c0fSArtem Bityutskiy .enter = &intel_idle, 10169edf3c0fSArtem Bityutskiy .enter_s2idle = intel_idle_s2idle, }, 10179edf3c0fSArtem Bityutskiy { 10189edf3c0fSArtem Bityutskiy .name = "C1E", 10199edf3c0fSArtem Bityutskiy .desc = "MWAIT 0x01", 10201548fac4SArtem Bityutskiy .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 10219edf3c0fSArtem Bityutskiy .exit_latency = 2, 10229edf3c0fSArtem Bityutskiy .target_residency = 4, 10239edf3c0fSArtem Bityutskiy .enter = &intel_idle, 10249edf3c0fSArtem Bityutskiy .enter_s2idle = intel_idle_s2idle, }, 10259edf3c0fSArtem Bityutskiy { 10269edf3c0fSArtem Bityutskiy .name = "C6", 10279edf3c0fSArtem Bityutskiy .desc = "MWAIT 0x20", 10289f011293SChang S. Bae .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | 10299f011293SChang S. Bae CPUIDLE_FLAG_INIT_XSTATE, 10309edf3c0fSArtem Bityutskiy .exit_latency = 290, 10319edf3c0fSArtem Bityutskiy .target_residency = 800, 10329edf3c0fSArtem Bityutskiy .enter = &intel_idle, 10339edf3c0fSArtem Bityutskiy .enter_s2idle = intel_idle_s2idle, }, 10349edf3c0fSArtem Bityutskiy { 10359edf3c0fSArtem Bityutskiy .enter = NULL } 10369edf3c0fSArtem Bityutskiy }; 10379edf3c0fSArtem Bityutskiy 1038ab1a8522SRafael J. Wysocki static struct cpuidle_state atom_cstates[] __initdata = { 1039e022e7ebSLen Brown { 1040de09cdd0SLen Brown .name = "C1E", 104126717172SLen Brown .desc = "MWAIT 0x00", 1042b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 104332e95180SLen Brown .exit_latency = 10, 104432e95180SLen Brown .target_residency = 20, 10455fe2e527SRafael J. Wysocki .enter = &intel_idle, 104628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 1047e022e7ebSLen Brown { 1048de09cdd0SLen Brown .name = "C2", 104926717172SLen Brown .desc = "MWAIT 0x10", 1050b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10), 105126717172SLen Brown .exit_latency = 20, 105226717172SLen Brown .target_residency = 80, 10535fe2e527SRafael J. Wysocki .enter = &intel_idle, 105428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 1055e022e7ebSLen Brown { 1056de09cdd0SLen Brown .name = "C4", 105726717172SLen Brown .desc = "MWAIT 0x30", 1058b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 105926717172SLen Brown .exit_latency = 100, 106026717172SLen Brown .target_residency = 400, 10615fe2e527SRafael J. Wysocki .enter = &intel_idle, 106228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 1063e022e7ebSLen Brown { 1064de09cdd0SLen Brown .name = "C6", 10657fcca7d9SLen Brown .desc = "MWAIT 0x52", 1066b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 10677fcca7d9SLen Brown .exit_latency = 140, 10687fcca7d9SLen Brown .target_residency = 560, 10695fe2e527SRafael J. Wysocki .enter = &intel_idle, 107028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 1071e022e7ebSLen Brown { 1072e022e7ebSLen Brown .enter = NULL } 107326717172SLen Brown }; 1074ab1a8522SRafael J. Wysocki static struct cpuidle_state tangier_cstates[] __initdata = { 10755e7ec268SAndy Shevchenko { 1076de09cdd0SLen Brown .name = "C1", 10775e7ec268SAndy Shevchenko .desc = "MWAIT 0x00", 10785e7ec268SAndy Shevchenko .flags = MWAIT2flg(0x00), 10795e7ec268SAndy Shevchenko .exit_latency = 1, 10805e7ec268SAndy Shevchenko .target_residency = 4, 10815e7ec268SAndy Shevchenko .enter = &intel_idle, 108228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 10835e7ec268SAndy Shevchenko { 1084de09cdd0SLen Brown .name = "C4", 10855e7ec268SAndy Shevchenko .desc = "MWAIT 0x30", 10865e7ec268SAndy Shevchenko .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 10875e7ec268SAndy Shevchenko .exit_latency = 100, 10885e7ec268SAndy Shevchenko .target_residency = 400, 10895e7ec268SAndy Shevchenko .enter = &intel_idle, 109028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 10915e7ec268SAndy Shevchenko { 1092de09cdd0SLen Brown .name = "C6", 10935e7ec268SAndy Shevchenko .desc = "MWAIT 0x52", 10945e7ec268SAndy Shevchenko .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 10955e7ec268SAndy Shevchenko .exit_latency = 140, 10965e7ec268SAndy Shevchenko .target_residency = 560, 10975e7ec268SAndy Shevchenko .enter = &intel_idle, 109828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 10995e7ec268SAndy Shevchenko { 1100de09cdd0SLen Brown .name = "C7", 11015e7ec268SAndy Shevchenko .desc = "MWAIT 0x60", 11025e7ec268SAndy Shevchenko .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 11035e7ec268SAndy Shevchenko .exit_latency = 1200, 11045e7ec268SAndy Shevchenko .target_residency = 4000, 11055e7ec268SAndy Shevchenko .enter = &intel_idle, 110628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 11075e7ec268SAndy Shevchenko { 1108de09cdd0SLen Brown .name = "C9", 11095e7ec268SAndy Shevchenko .desc = "MWAIT 0x64", 11105e7ec268SAndy Shevchenko .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, 11115e7ec268SAndy Shevchenko .exit_latency = 10000, 11125e7ec268SAndy Shevchenko .target_residency = 20000, 11135e7ec268SAndy Shevchenko .enter = &intel_idle, 111428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 11155e7ec268SAndy Shevchenko { 11165e7ec268SAndy Shevchenko .enter = NULL } 11175e7ec268SAndy Shevchenko }; 1118ab1a8522SRafael J. Wysocki static struct cpuidle_state avn_cstates[] __initdata = { 1119fab04b22SLen Brown { 1120de09cdd0SLen Brown .name = "C1", 1121fab04b22SLen Brown .desc = "MWAIT 0x00", 1122b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 1123fab04b22SLen Brown .exit_latency = 2, 1124fab04b22SLen Brown .target_residency = 2, 11255fe2e527SRafael J. Wysocki .enter = &intel_idle, 112628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 1127fab04b22SLen Brown { 1128de09cdd0SLen Brown .name = "C6", 1129fab04b22SLen Brown .desc = "MWAIT 0x51", 1130b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED, 1131fab04b22SLen Brown .exit_latency = 15, 1132fab04b22SLen Brown .target_residency = 45, 11335fe2e527SRafael J. Wysocki .enter = &intel_idle, 113428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 113588390996SJiang Liu { 113688390996SJiang Liu .enter = NULL } 1137fab04b22SLen Brown }; 1138ab1a8522SRafael J. Wysocki static struct cpuidle_state knl_cstates[] __initdata = { 1139281baf7aSDasaratharaman Chandramouli { 1140de09cdd0SLen Brown .name = "C1", 1141281baf7aSDasaratharaman Chandramouli .desc = "MWAIT 0x00", 1142281baf7aSDasaratharaman Chandramouli .flags = MWAIT2flg(0x00), 1143281baf7aSDasaratharaman Chandramouli .exit_latency = 1, 1144281baf7aSDasaratharaman Chandramouli .target_residency = 2, 1145281baf7aSDasaratharaman Chandramouli .enter = &intel_idle, 114628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle }, 1147281baf7aSDasaratharaman Chandramouli { 1148de09cdd0SLen Brown .name = "C6", 1149281baf7aSDasaratharaman Chandramouli .desc = "MWAIT 0x10", 1150281baf7aSDasaratharaman Chandramouli .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 1151281baf7aSDasaratharaman Chandramouli .exit_latency = 120, 1152281baf7aSDasaratharaman Chandramouli .target_residency = 500, 1153281baf7aSDasaratharaman Chandramouli .enter = &intel_idle, 115428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle }, 1155281baf7aSDasaratharaman Chandramouli { 1156281baf7aSDasaratharaman Chandramouli .enter = NULL } 1157281baf7aSDasaratharaman Chandramouli }; 115826717172SLen Brown 1159ab1a8522SRafael J. Wysocki static struct cpuidle_state bxt_cstates[] __initdata = { 11605dcef694SLen Brown { 1161de09cdd0SLen Brown .name = "C1", 11625dcef694SLen Brown .desc = "MWAIT 0x00", 11635dcef694SLen Brown .flags = MWAIT2flg(0x00), 11645dcef694SLen Brown .exit_latency = 2, 11655dcef694SLen Brown .target_residency = 2, 11665dcef694SLen Brown .enter = &intel_idle, 116728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 11685dcef694SLen Brown { 1169de09cdd0SLen Brown .name = "C1E", 11705dcef694SLen Brown .desc = "MWAIT 0x01", 1171e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 11725dcef694SLen Brown .exit_latency = 10, 11735dcef694SLen Brown .target_residency = 20, 11745dcef694SLen Brown .enter = &intel_idle, 117528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 11765dcef694SLen Brown { 1177de09cdd0SLen Brown .name = "C6", 11785dcef694SLen Brown .desc = "MWAIT 0x20", 11795dcef694SLen Brown .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 11805dcef694SLen Brown .exit_latency = 133, 11815dcef694SLen Brown .target_residency = 133, 11825dcef694SLen Brown .enter = &intel_idle, 118328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 11845dcef694SLen Brown { 1185de09cdd0SLen Brown .name = "C7s", 11865dcef694SLen Brown .desc = "MWAIT 0x31", 11875dcef694SLen Brown .flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED, 11885dcef694SLen Brown .exit_latency = 155, 11895dcef694SLen Brown .target_residency = 155, 11905dcef694SLen Brown .enter = &intel_idle, 119128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 11925dcef694SLen Brown { 1193de09cdd0SLen Brown .name = "C8", 11945dcef694SLen Brown .desc = "MWAIT 0x40", 11955dcef694SLen Brown .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 11965dcef694SLen Brown .exit_latency = 1000, 11975dcef694SLen Brown .target_residency = 1000, 11985dcef694SLen Brown .enter = &intel_idle, 119928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 12005dcef694SLen Brown { 1201de09cdd0SLen Brown .name = "C9", 12025dcef694SLen Brown .desc = "MWAIT 0x50", 12035dcef694SLen Brown .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, 12045dcef694SLen Brown .exit_latency = 2000, 12055dcef694SLen Brown .target_residency = 2000, 12065dcef694SLen Brown .enter = &intel_idle, 120728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 12085dcef694SLen Brown { 1209de09cdd0SLen Brown .name = "C10", 12105dcef694SLen Brown .desc = "MWAIT 0x60", 12115dcef694SLen Brown .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 12125dcef694SLen Brown .exit_latency = 10000, 12135dcef694SLen Brown .target_residency = 10000, 12145dcef694SLen Brown .enter = &intel_idle, 121528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 12165dcef694SLen Brown { 12175dcef694SLen Brown .enter = NULL } 12185dcef694SLen Brown }; 12195dcef694SLen Brown 1220ab1a8522SRafael J. Wysocki static struct cpuidle_state dnv_cstates[] __initdata = { 12210080d65bSJacob Pan { 1222de09cdd0SLen Brown .name = "C1", 12230080d65bSJacob Pan .desc = "MWAIT 0x00", 12240080d65bSJacob Pan .flags = MWAIT2flg(0x00), 12250080d65bSJacob Pan .exit_latency = 2, 12260080d65bSJacob Pan .target_residency = 2, 12270080d65bSJacob Pan .enter = &intel_idle, 122828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 12290080d65bSJacob Pan { 1230de09cdd0SLen Brown .name = "C1E", 12310080d65bSJacob Pan .desc = "MWAIT 0x01", 1232e6d4f08aSRafael J. Wysocki .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 12330080d65bSJacob Pan .exit_latency = 10, 12340080d65bSJacob Pan .target_residency = 20, 12350080d65bSJacob Pan .enter = &intel_idle, 123628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 12370080d65bSJacob Pan { 1238de09cdd0SLen Brown .name = "C6", 12390080d65bSJacob Pan .desc = "MWAIT 0x20", 12400080d65bSJacob Pan .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 12410080d65bSJacob Pan .exit_latency = 50, 12420080d65bSJacob Pan .target_residency = 500, 12430080d65bSJacob Pan .enter = &intel_idle, 124428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 12450080d65bSJacob Pan { 12460080d65bSJacob Pan .enter = NULL } 12470080d65bSJacob Pan }; 12480080d65bSJacob Pan 12499cf93f05SArtem Bityutskiy /* 12509cf93f05SArtem Bityutskiy * Note, depending on HW and FW revision, SnowRidge SoC may or may not support 12519cf93f05SArtem Bityutskiy * C6, and this is indicated in the CPUID mwait leaf. 12529cf93f05SArtem Bityutskiy */ 12539cf93f05SArtem Bityutskiy static struct cpuidle_state snr_cstates[] __initdata = { 12549cf93f05SArtem Bityutskiy { 12559cf93f05SArtem Bityutskiy .name = "C1", 12569cf93f05SArtem Bityutskiy .desc = "MWAIT 0x00", 12579cf93f05SArtem Bityutskiy .flags = MWAIT2flg(0x00), 12589cf93f05SArtem Bityutskiy .exit_latency = 2, 12599cf93f05SArtem Bityutskiy .target_residency = 2, 12609cf93f05SArtem Bityutskiy .enter = &intel_idle, 12619cf93f05SArtem Bityutskiy .enter_s2idle = intel_idle_s2idle, }, 12629cf93f05SArtem Bityutskiy { 12639cf93f05SArtem Bityutskiy .name = "C1E", 12649cf93f05SArtem Bityutskiy .desc = "MWAIT 0x01", 12659cf93f05SArtem Bityutskiy .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE, 12669cf93f05SArtem Bityutskiy .exit_latency = 15, 12679cf93f05SArtem Bityutskiy .target_residency = 25, 12689cf93f05SArtem Bityutskiy .enter = &intel_idle, 12699cf93f05SArtem Bityutskiy .enter_s2idle = intel_idle_s2idle, }, 12709cf93f05SArtem Bityutskiy { 12719cf93f05SArtem Bityutskiy .name = "C6", 12729cf93f05SArtem Bityutskiy .desc = "MWAIT 0x20", 12739cf93f05SArtem Bityutskiy .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 12749cf93f05SArtem Bityutskiy .exit_latency = 130, 12759cf93f05SArtem Bityutskiy .target_residency = 500, 12769cf93f05SArtem Bityutskiy .enter = &intel_idle, 12779cf93f05SArtem Bityutskiy .enter_s2idle = intel_idle_s2idle, }, 12789cf93f05SArtem Bityutskiy { 12799cf93f05SArtem Bityutskiy .enter = NULL } 12809cf93f05SArtem Bityutskiy }; 12819cf93f05SArtem Bityutskiy 12822f3d08f0SArjan van de Ven static struct cpuidle_state vmguest_cstates[] __initdata = { 12832f3d08f0SArjan van de Ven { 12842f3d08f0SArjan van de Ven .name = "C1", 12852f3d08f0SArjan van de Ven .desc = "HLT", 12862f3d08f0SArjan van de Ven .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE, 12872f3d08f0SArjan van de Ven .exit_latency = 5, 12882f3d08f0SArjan van de Ven .target_residency = 10, 12892f3d08f0SArjan van de Ven .enter = &intel_idle_hlt, }, 12902f3d08f0SArjan van de Ven { 1291*0fac214bSArjan van de Ven .name = "C1L", 1292*0fac214bSArjan van de Ven .desc = "Long HLT", 1293*0fac214bSArjan van de Ven .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TLB_FLUSHED, 1294*0fac214bSArjan van de Ven .exit_latency = 5, 1295*0fac214bSArjan van de Ven .target_residency = 200, 1296*0fac214bSArjan van de Ven .enter = &intel_idle_hlt, }, 1297*0fac214bSArjan van de Ven { 12982f3d08f0SArjan van de Ven .enter = NULL } 12992f3d08f0SArjan van de Ven }; 13002f3d08f0SArjan van de Ven 1301ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_nehalem __initconst = { 1302b66b8b9aSAndi Kleen .state_table = nehalem_cstates, 1303b66b8b9aSAndi Kleen .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, 130432e95180SLen Brown .disable_promotion_to_c1e = true, 1305b66b8b9aSAndi Kleen }; 1306b66b8b9aSAndi Kleen 1307ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_nhx __initconst = { 1308e6d4f08aSRafael J. Wysocki .state_table = nehalem_cstates, 1309e6d4f08aSRafael J. Wysocki .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, 1310e6d4f08aSRafael J. Wysocki .disable_promotion_to_c1e = true, 1311e6d4f08aSRafael J. Wysocki .use_acpi = true, 1312e6d4f08aSRafael J. Wysocki }; 1313e6d4f08aSRafael J. Wysocki 1314ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_atom __initconst = { 1315b66b8b9aSAndi Kleen .state_table = atom_cstates, 1316b66b8b9aSAndi Kleen }; 1317b66b8b9aSAndi Kleen 1318ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_tangier __initconst = { 13195e7ec268SAndy Shevchenko .state_table = tangier_cstates, 13205e7ec268SAndy Shevchenko }; 13215e7ec268SAndy Shevchenko 1322ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_lincroft __initconst = { 1323b66b8b9aSAndi Kleen .state_table = atom_cstates, 1324b66b8b9aSAndi Kleen .auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE, 1325b66b8b9aSAndi Kleen }; 1326b66b8b9aSAndi Kleen 1327ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_snb __initconst = { 1328b66b8b9aSAndi Kleen .state_table = snb_cstates, 132932e95180SLen Brown .disable_promotion_to_c1e = true, 1330b66b8b9aSAndi Kleen }; 1331b66b8b9aSAndi Kleen 1332ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_snx __initconst = { 1333e6d4f08aSRafael J. Wysocki .state_table = snb_cstates, 1334e6d4f08aSRafael J. Wysocki .disable_promotion_to_c1e = true, 1335e6d4f08aSRafael J. Wysocki .use_acpi = true, 1336e6d4f08aSRafael J. Wysocki }; 1337e6d4f08aSRafael J. Wysocki 1338ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_byt __initconst = { 1339718987d6SLen Brown .state_table = byt_cstates, 1340718987d6SLen Brown .disable_promotion_to_c1e = true, 13418c058d53SLen Brown .byt_auto_demotion_disable_flag = true, 1342718987d6SLen Brown }; 1343718987d6SLen Brown 1344ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_cht __initconst = { 1345cab07a56SLen Brown .state_table = cht_cstates, 1346cab07a56SLen Brown .disable_promotion_to_c1e = true, 1347cab07a56SLen Brown .byt_auto_demotion_disable_flag = true, 1348cab07a56SLen Brown }; 1349cab07a56SLen Brown 1350ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_ivb __initconst = { 13516edab08cSLen Brown .state_table = ivb_cstates, 135232e95180SLen Brown .disable_promotion_to_c1e = true, 13536edab08cSLen Brown }; 13546edab08cSLen Brown 1355ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_ivt __initconst = { 13560138d8f0SLen Brown .state_table = ivt_cstates, 13570138d8f0SLen Brown .disable_promotion_to_c1e = true, 1358e6d4f08aSRafael J. Wysocki .use_acpi = true, 13590138d8f0SLen Brown }; 13600138d8f0SLen Brown 1361ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_hsw __initconst = { 136285a4d2d4SLen Brown .state_table = hsw_cstates, 136332e95180SLen Brown .disable_promotion_to_c1e = true, 136485a4d2d4SLen Brown }; 136585a4d2d4SLen Brown 1366ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_hsx __initconst = { 1367e6d4f08aSRafael J. Wysocki .state_table = hsw_cstates, 1368e6d4f08aSRafael J. Wysocki .disable_promotion_to_c1e = true, 1369e6d4f08aSRafael J. Wysocki .use_acpi = true, 1370e6d4f08aSRafael J. Wysocki }; 1371e6d4f08aSRafael J. Wysocki 1372ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bdw __initconst = { 1373a138b568SLen Brown .state_table = bdw_cstates, 1374a138b568SLen Brown .disable_promotion_to_c1e = true, 1375a138b568SLen Brown }; 1376a138b568SLen Brown 1377ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bdx __initconst = { 1378e6d4f08aSRafael J. Wysocki .state_table = bdw_cstates, 1379e6d4f08aSRafael J. Wysocki .disable_promotion_to_c1e = true, 1380e6d4f08aSRafael J. Wysocki .use_acpi = true, 1381e6d4f08aSRafael J. Wysocki }; 1382e6d4f08aSRafael J. Wysocki 1383ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_skl __initconst = { 1384493f133fSLen Brown .state_table = skl_cstates, 1385493f133fSLen Brown .disable_promotion_to_c1e = true, 1386493f133fSLen Brown }; 1387493f133fSLen Brown 1388ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_skx __initconst = { 1389f9e71657SLen Brown .state_table = skx_cstates, 1390f9e71657SLen Brown .disable_promotion_to_c1e = true, 1391e6d4f08aSRafael J. Wysocki .use_acpi = true, 1392f9e71657SLen Brown }; 1393493f133fSLen Brown 1394a472ad2bSChen Yu static const struct idle_cpu idle_cpu_icx __initconst = { 1395a472ad2bSChen Yu .state_table = icx_cstates, 1396a472ad2bSChen Yu .disable_promotion_to_c1e = true, 1397a472ad2bSChen Yu .use_acpi = true, 1398a472ad2bSChen Yu }; 1399a472ad2bSChen Yu 1400d1cf8bbfSZhang Rui static const struct idle_cpu idle_cpu_adl __initconst = { 1401d1cf8bbfSZhang Rui .state_table = adl_cstates, 1402d1cf8bbfSZhang Rui }; 1403d1cf8bbfSZhang Rui 1404d1cf8bbfSZhang Rui static const struct idle_cpu idle_cpu_adl_l __initconst = { 1405d1cf8bbfSZhang Rui .state_table = adl_l_cstates, 1406d1cf8bbfSZhang Rui }; 1407d1cf8bbfSZhang Rui 140865c0c236SZhang Rui static const struct idle_cpu idle_cpu_adl_n __initconst = { 140965c0c236SZhang Rui .state_table = adl_n_cstates, 141065c0c236SZhang Rui }; 141165c0c236SZhang Rui 14129edf3c0fSArtem Bityutskiy static const struct idle_cpu idle_cpu_spr __initconst = { 14139edf3c0fSArtem Bityutskiy .state_table = spr_cstates, 14149edf3c0fSArtem Bityutskiy .disable_promotion_to_c1e = true, 14159edf3c0fSArtem Bityutskiy .use_acpi = true, 14169edf3c0fSArtem Bityutskiy }; 14179edf3c0fSArtem Bityutskiy 1418ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_avn __initconst = { 1419fab04b22SLen Brown .state_table = avn_cstates, 1420fab04b22SLen Brown .disable_promotion_to_c1e = true, 1421e6d4f08aSRafael J. Wysocki .use_acpi = true, 1422fab04b22SLen Brown }; 1423fab04b22SLen Brown 1424ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_knl __initconst = { 1425281baf7aSDasaratharaman Chandramouli .state_table = knl_cstates, 1426e6d4f08aSRafael J. Wysocki .use_acpi = true, 1427281baf7aSDasaratharaman Chandramouli }; 1428281baf7aSDasaratharaman Chandramouli 1429ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_bxt __initconst = { 14305dcef694SLen Brown .state_table = bxt_cstates, 14315dcef694SLen Brown .disable_promotion_to_c1e = true, 14325dcef694SLen Brown }; 14335dcef694SLen Brown 1434ab1a8522SRafael J. Wysocki static const struct idle_cpu idle_cpu_dnv __initconst = { 14350080d65bSJacob Pan .state_table = dnv_cstates, 14360080d65bSJacob Pan .disable_promotion_to_c1e = true, 1437e6d4f08aSRafael J. Wysocki .use_acpi = true, 14380080d65bSJacob Pan }; 14390080d65bSJacob Pan 14409cf93f05SArtem Bityutskiy static const struct idle_cpu idle_cpu_snr __initconst = { 14419cf93f05SArtem Bityutskiy .state_table = snr_cstates, 14429cf93f05SArtem Bityutskiy .disable_promotion_to_c1e = true, 14439cf93f05SArtem Bityutskiy .use_acpi = true, 14449cf93f05SArtem Bityutskiy }; 14459cf93f05SArtem Bityutskiy 1446d5cdc3c4SMathias Krause static const struct x86_cpu_id intel_idle_ids[] __initconst = { 14474a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EP, &idle_cpu_nhx), 14484a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(NEHALEM, &idle_cpu_nehalem), 14494a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_G, &idle_cpu_nehalem), 14504a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(WESTMERE, &idle_cpu_nehalem), 14514a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EP, &idle_cpu_nhx), 14524a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EX, &idle_cpu_nhx), 14534a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL, &idle_cpu_atom), 14544a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(ATOM_BONNELL_MID, &idle_cpu_lincroft), 14554a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(WESTMERE_EX, &idle_cpu_nhx), 14564a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE, &idle_cpu_snb), 14574a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, &idle_cpu_snx), 14584a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(ATOM_SALTWELL, &idle_cpu_atom), 14594a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, &idle_cpu_byt), 14604a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_MID, &idle_cpu_tangier), 14614a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, &idle_cpu_cht), 14624a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE, &idle_cpu_ivb), 14634a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X, &idle_cpu_ivt), 14644a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(HASWELL, &idle_cpu_hsw), 14654a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X, &idle_cpu_hsx), 14664a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L, &idle_cpu_hsw), 14674a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G, &idle_cpu_hsw), 14684a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D, &idle_cpu_avn), 14694a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(BROADWELL, &idle_cpu_bdw), 14704a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G, &idle_cpu_bdw), 14714a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X, &idle_cpu_bdx), 14724a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D, &idle_cpu_bdx), 14734a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, &idle_cpu_skl), 14744a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, &idle_cpu_skl), 14754a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, &idle_cpu_skl), 14764a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, &idle_cpu_skl), 14774a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X, &idle_cpu_skx), 1478a472ad2bSChen Yu X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, &idle_cpu_icx), 147922141d5fSArtem Bityutskiy X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, &idle_cpu_icx), 1480d1cf8bbfSZhang Rui X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &idle_cpu_adl), 1481d1cf8bbfSZhang Rui X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &idle_cpu_adl_l), 148265c0c236SZhang Rui X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, &idle_cpu_adl_n), 14839edf3c0fSArtem Bityutskiy X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, &idle_cpu_spr), 148474528edfSArtem Bityutskiy X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X, &idle_cpu_spr), 14854a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &idle_cpu_knl), 14864a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &idle_cpu_knl), 14874a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &idle_cpu_bxt), 14884a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS, &idle_cpu_bxt), 14894a9f45a0SThomas Gleixner X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D, &idle_cpu_dnv), 14909cf93f05SArtem Bityutskiy X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D, &idle_cpu_snr), 1491b66b8b9aSAndi Kleen {} 1492b66b8b9aSAndi Kleen }; 1493b66b8b9aSAndi Kleen 149418734958SRafael J. Wysocki static const struct x86_cpu_id intel_mwait_ids[] __initconst = { 14954a9f45a0SThomas Gleixner X86_MATCH_VENDOR_FAM_FEATURE(INTEL, 6, X86_FEATURE_MWAIT, NULL), 149618734958SRafael J. Wysocki {} 149718734958SRafael J. Wysocki }; 149818734958SRafael J. Wysocki 1499095928aeSRafael J. Wysocki static bool __init intel_idle_max_cstate_reached(int cstate) 150018734958SRafael J. Wysocki { 150118734958SRafael J. Wysocki if (cstate + 1 > max_cstate) { 150218734958SRafael J. Wysocki pr_info("max_cstate %d reached\n", max_cstate); 150318734958SRafael J. Wysocki return true; 150418734958SRafael J. Wysocki } 150518734958SRafael J. Wysocki return false; 150618734958SRafael J. Wysocki } 150718734958SRafael J. Wysocki 15084d916140SPeter Zijlstra static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state) 15094d916140SPeter Zijlstra { 15104d916140SPeter Zijlstra unsigned long eax = flg2MWAIT(state->flags); 15114d916140SPeter Zijlstra 15124d916140SPeter Zijlstra if (boot_cpu_has(X86_FEATURE_ARAT)) 15134d916140SPeter Zijlstra return false; 15144d916140SPeter Zijlstra 15154d916140SPeter Zijlstra /* 15164d916140SPeter Zijlstra * Switch over to one-shot tick broadcast if the target C-state 15174d916140SPeter Zijlstra * is deeper than C1. 15184d916140SPeter Zijlstra */ 15194d916140SPeter Zijlstra return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK); 15204d916140SPeter Zijlstra } 15214d916140SPeter Zijlstra 152218734958SRafael J. Wysocki #ifdef CONFIG_ACPI_PROCESSOR_CSTATE 152318734958SRafael J. Wysocki #include <acpi/processor.h> 152418734958SRafael J. Wysocki 15254ec32d9eSRafael J. Wysocki static bool no_acpi __read_mostly; 15264ec32d9eSRafael J. Wysocki module_param(no_acpi, bool, 0444); 15274ec32d9eSRafael J. Wysocki MODULE_PARM_DESC(no_acpi, "Do not use ACPI _CST for building the idle states list"); 15284ec32d9eSRafael J. Wysocki 15293a5be9b8SRafael J. Wysocki static bool force_use_acpi __read_mostly; /* No effect if no_acpi is set. */ 15303a5be9b8SRafael J. Wysocki module_param_named(use_acpi, force_use_acpi, bool, 0444); 15313a5be9b8SRafael J. Wysocki MODULE_PARM_DESC(use_acpi, "Use ACPI _CST for building the idle states list"); 15323a5be9b8SRafael J. Wysocki 1533095928aeSRafael J. Wysocki static struct acpi_processor_power acpi_state_table __initdata; 153418734958SRafael J. Wysocki 153518734958SRafael J. Wysocki /** 153618734958SRafael J. Wysocki * intel_idle_cst_usable - Check if the _CST information can be used. 153718734958SRafael J. Wysocki * 153818734958SRafael J. Wysocki * Check if all of the C-states listed by _CST in the max_cstate range are 153918734958SRafael J. Wysocki * ACPI_CSTATE_FFH, which means that they should be entered via MWAIT. 154018734958SRafael J. Wysocki */ 1541095928aeSRafael J. Wysocki static bool __init intel_idle_cst_usable(void) 154218734958SRafael J. Wysocki { 154318734958SRafael J. Wysocki int cstate, limit; 154418734958SRafael J. Wysocki 154518734958SRafael J. Wysocki limit = min_t(int, min_t(int, CPUIDLE_STATE_MAX, max_cstate + 1), 154618734958SRafael J. Wysocki acpi_state_table.count); 154718734958SRafael J. Wysocki 154818734958SRafael J. Wysocki for (cstate = 1; cstate < limit; cstate++) { 154918734958SRafael J. Wysocki struct acpi_processor_cx *cx = &acpi_state_table.states[cstate]; 155018734958SRafael J. Wysocki 155118734958SRafael J. Wysocki if (cx->entry_method != ACPI_CSTATE_FFH) 155218734958SRafael J. Wysocki return false; 155318734958SRafael J. Wysocki } 155418734958SRafael J. Wysocki 155518734958SRafael J. Wysocki return true; 155618734958SRafael J. Wysocki } 155718734958SRafael J. Wysocki 1558095928aeSRafael J. Wysocki static bool __init intel_idle_acpi_cst_extract(void) 155918734958SRafael J. Wysocki { 156018734958SRafael J. Wysocki unsigned int cpu; 156118734958SRafael J. Wysocki 15624ec32d9eSRafael J. Wysocki if (no_acpi) { 15634ec32d9eSRafael J. Wysocki pr_debug("Not allowed to use ACPI _CST\n"); 15644ec32d9eSRafael J. Wysocki return false; 15654ec32d9eSRafael J. Wysocki } 15664ec32d9eSRafael J. Wysocki 156718734958SRafael J. Wysocki for_each_possible_cpu(cpu) { 156818734958SRafael J. Wysocki struct acpi_processor *pr = per_cpu(processors, cpu); 156918734958SRafael J. Wysocki 157018734958SRafael J. Wysocki if (!pr) 157118734958SRafael J. Wysocki continue; 157218734958SRafael J. Wysocki 157318734958SRafael J. Wysocki if (acpi_processor_evaluate_cst(pr->handle, cpu, &acpi_state_table)) 157418734958SRafael J. Wysocki continue; 157518734958SRafael J. Wysocki 157618734958SRafael J. Wysocki acpi_state_table.count++; 157718734958SRafael J. Wysocki 157818734958SRafael J. Wysocki if (!intel_idle_cst_usable()) 157918734958SRafael J. Wysocki continue; 158018734958SRafael J. Wysocki 158175af76d0SMel Gorman if (!acpi_processor_claim_cst_control()) 158275af76d0SMel Gorman break; 158318734958SRafael J. Wysocki 158418734958SRafael J. Wysocki return true; 158518734958SRafael J. Wysocki } 158618734958SRafael J. Wysocki 158775af76d0SMel Gorman acpi_state_table.count = 0; 158818734958SRafael J. Wysocki pr_debug("ACPI _CST not found or not usable\n"); 158918734958SRafael J. Wysocki return false; 159018734958SRafael J. Wysocki } 159118734958SRafael J. Wysocki 1592095928aeSRafael J. Wysocki static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv) 159318734958SRafael J. Wysocki { 159418734958SRafael J. Wysocki int cstate, limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count); 159518734958SRafael J. Wysocki 159618734958SRafael J. Wysocki /* 159718734958SRafael J. Wysocki * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of 159818734958SRafael J. Wysocki * the interesting states are ACPI_CSTATE_FFH. 159918734958SRafael J. Wysocki */ 160018734958SRafael J. Wysocki for (cstate = 1; cstate < limit; cstate++) { 160118734958SRafael J. Wysocki struct acpi_processor_cx *cx; 160218734958SRafael J. Wysocki struct cpuidle_state *state; 160318734958SRafael J. Wysocki 16044e0ba557SChen Yu if (intel_idle_max_cstate_reached(cstate - 1)) 160518734958SRafael J. Wysocki break; 160618734958SRafael J. Wysocki 160718734958SRafael J. Wysocki cx = &acpi_state_table.states[cstate]; 160818734958SRafael J. Wysocki 160918734958SRafael J. Wysocki state = &drv->states[drv->state_count++]; 161018734958SRafael J. Wysocki 161118734958SRafael J. Wysocki snprintf(state->name, CPUIDLE_NAME_LEN, "C%d_ACPI", cstate); 16120dbc0f49SWolfram Sang strscpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); 161318734958SRafael J. Wysocki state->exit_latency = cx->latency; 161418734958SRafael J. Wysocki /* 161518734958SRafael J. Wysocki * For C1-type C-states use the same number for both the exit 161618734958SRafael J. Wysocki * latency and target residency, because that is the case for 161718734958SRafael J. Wysocki * C1 in the majority of the static C-states tables above. 161818734958SRafael J. Wysocki * For the other types of C-states, however, set the target 161918734958SRafael J. Wysocki * residency to 3 times the exit latency which should lead to 162018734958SRafael J. Wysocki * a reasonable balance between energy-efficiency and 162118734958SRafael J. Wysocki * performance in the majority of interesting cases. 162218734958SRafael J. Wysocki */ 162318734958SRafael J. Wysocki state->target_residency = cx->latency; 162418734958SRafael J. Wysocki if (cx->type > ACPI_STATE_C1) 162518734958SRafael J. Wysocki state->target_residency *= 3; 162618734958SRafael J. Wysocki 162718734958SRafael J. Wysocki state->flags = MWAIT2flg(cx->address); 162818734958SRafael J. Wysocki if (cx->type > ACPI_STATE_C2) 162918734958SRafael J. Wysocki state->flags |= CPUIDLE_FLAG_TLB_FLUSHED; 163018734958SRafael J. Wysocki 16314dcb78eeSRafael J. Wysocki if (disabled_states_mask & BIT(cstate)) 16324dcb78eeSRafael J. Wysocki state->flags |= CPUIDLE_FLAG_OFF; 16334dcb78eeSRafael J. Wysocki 16346e1d2bc6SPeter Zijlstra if (intel_idle_state_needs_timer_stop(state)) 16356e1d2bc6SPeter Zijlstra state->flags |= CPUIDLE_FLAG_TIMER_STOP; 16366e1d2bc6SPeter Zijlstra 163718734958SRafael J. Wysocki state->enter = intel_idle; 163818734958SRafael J. Wysocki state->enter_s2idle = intel_idle_s2idle; 163918734958SRafael J. Wysocki } 164018734958SRafael J. Wysocki } 1641bff8e60aSRafael J. Wysocki 1642095928aeSRafael J. Wysocki static bool __init intel_idle_off_by_default(u32 mwait_hint) 1643bff8e60aSRafael J. Wysocki { 1644bff8e60aSRafael J. Wysocki int cstate, limit; 1645bff8e60aSRafael J. Wysocki 1646bff8e60aSRafael J. Wysocki /* 1647bff8e60aSRafael J. Wysocki * If there are no _CST C-states, do not disable any C-states by 1648bff8e60aSRafael J. Wysocki * default. 1649bff8e60aSRafael J. Wysocki */ 1650bff8e60aSRafael J. Wysocki if (!acpi_state_table.count) 1651bff8e60aSRafael J. Wysocki return false; 1652bff8e60aSRafael J. Wysocki 1653bff8e60aSRafael J. Wysocki limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count); 1654bff8e60aSRafael J. Wysocki /* 1655bff8e60aSRafael J. Wysocki * If limit > 0, intel_idle_cst_usable() has returned 'true', so all of 1656bff8e60aSRafael J. Wysocki * the interesting states are ACPI_CSTATE_FFH. 1657bff8e60aSRafael J. Wysocki */ 1658bff8e60aSRafael J. Wysocki for (cstate = 1; cstate < limit; cstate++) { 1659bff8e60aSRafael J. Wysocki if (acpi_state_table.states[cstate].address == mwait_hint) 1660bff8e60aSRafael J. Wysocki return false; 1661bff8e60aSRafael J. Wysocki } 1662bff8e60aSRafael J. Wysocki return true; 1663bff8e60aSRafael J. Wysocki } 166418734958SRafael J. Wysocki #else /* !CONFIG_ACPI_PROCESSOR_CSTATE */ 16653a5be9b8SRafael J. Wysocki #define force_use_acpi (false) 16663a5be9b8SRafael J. Wysocki 166718734958SRafael J. Wysocki static inline bool intel_idle_acpi_cst_extract(void) { return false; } 166818734958SRafael J. Wysocki static inline void intel_idle_init_cstates_acpi(struct cpuidle_driver *drv) { } 1669bff8e60aSRafael J. Wysocki static inline bool intel_idle_off_by_default(u32 mwait_hint) { return false; } 167018734958SRafael J. Wysocki #endif /* !CONFIG_ACPI_PROCESSOR_CSTATE */ 167118734958SRafael J. Wysocki 16726eacb15fSRafael J. Wysocki /** 16736eacb15fSRafael J. Wysocki * ivt_idle_state_table_update - Tune the idle states table for Ivy Town. 16740138d8f0SLen Brown * 16756eacb15fSRafael J. Wysocki * Tune IVT multi-socket targets. 16766eacb15fSRafael J. Wysocki * Assumption: num_sockets == (max_package_num + 1). 16770138d8f0SLen Brown */ 1678095928aeSRafael J. Wysocki static void __init ivt_idle_state_table_update(void) 16790138d8f0SLen Brown { 16800138d8f0SLen Brown /* IVT uses a different table for 1-2, 3-4, and > 4 sockets */ 16810138d8f0SLen Brown int cpu, package_num, num_sockets = 1; 16820138d8f0SLen Brown 16830138d8f0SLen Brown for_each_online_cpu(cpu) { 16840138d8f0SLen Brown package_num = topology_physical_package_id(cpu); 16850138d8f0SLen Brown if (package_num + 1 > num_sockets) { 16860138d8f0SLen Brown num_sockets = package_num + 1; 16870138d8f0SLen Brown 1688d27dca42SChristoph Jaeger if (num_sockets > 4) { 16890138d8f0SLen Brown cpuidle_state_table = ivt_cstates_8s; 16900138d8f0SLen Brown return; 16910138d8f0SLen Brown } 16920138d8f0SLen Brown } 1693d27dca42SChristoph Jaeger } 16940138d8f0SLen Brown 16950138d8f0SLen Brown if (num_sockets > 2) 16960138d8f0SLen Brown cpuidle_state_table = ivt_cstates_4s; 1697d70e28f5SLen Brown 16980138d8f0SLen Brown /* else, 1 and 2 socket systems use default ivt_cstates */ 16990138d8f0SLen Brown } 17005dcef694SLen Brown 170186e9466aSRafael J. Wysocki /** 170286e9466aSRafael J. Wysocki * irtl_2_usec - IRTL to microseconds conversion. 170386e9466aSRafael J. Wysocki * @irtl: IRTL MSR value. 170486e9466aSRafael J. Wysocki * 170586e9466aSRafael J. Wysocki * Translate the IRTL (Interrupt Response Time Limit) MSR value to microseconds. 17065dcef694SLen Brown */ 170786e9466aSRafael J. Wysocki static unsigned long long __init irtl_2_usec(unsigned long long irtl) 170886e9466aSRafael J. Wysocki { 1709095928aeSRafael J. Wysocki static const unsigned int irtl_ns_units[] __initconst = { 1710095928aeSRafael J. Wysocki 1, 32, 1024, 32768, 1048576, 33554432, 0, 0 1711095928aeSRafael J. Wysocki }; 17125dcef694SLen Brown unsigned long long ns; 17135dcef694SLen Brown 17143451ab3eSJan Beulich if (!irtl) 17153451ab3eSJan Beulich return 0; 17163451ab3eSJan Beulich 1717bef45096SJan Beulich ns = irtl_ns_units[(irtl >> 10) & 0x7]; 17185dcef694SLen Brown 171986e9466aSRafael J. Wysocki return div_u64((irtl & 0x3FF) * ns, NSEC_PER_USEC); 17205dcef694SLen Brown } 172186e9466aSRafael J. Wysocki 17226eacb15fSRafael J. Wysocki /** 17236eacb15fSRafael J. Wysocki * bxt_idle_state_table_update - Fix up the Broxton idle states table. 17245dcef694SLen Brown * 17256eacb15fSRafael J. Wysocki * On BXT, trust the IRTL (Interrupt Response Time Limit) MSR to show the 17266eacb15fSRafael J. Wysocki * definitive maximum latency and use the same value for target_residency. 17275dcef694SLen Brown */ 1728095928aeSRafael J. Wysocki static void __init bxt_idle_state_table_update(void) 17295dcef694SLen Brown { 17305dcef694SLen Brown unsigned long long msr; 17313451ab3eSJan Beulich unsigned int usec; 17325dcef694SLen Brown 17335dcef694SLen Brown rdmsrl(MSR_PKGC6_IRTL, msr); 17343451ab3eSJan Beulich usec = irtl_2_usec(msr); 17353451ab3eSJan Beulich if (usec) { 17365dcef694SLen Brown bxt_cstates[2].exit_latency = usec; 17375dcef694SLen Brown bxt_cstates[2].target_residency = usec; 17385dcef694SLen Brown } 17395dcef694SLen Brown 17405dcef694SLen Brown rdmsrl(MSR_PKGC7_IRTL, msr); 17413451ab3eSJan Beulich usec = irtl_2_usec(msr); 17423451ab3eSJan Beulich if (usec) { 17435dcef694SLen Brown bxt_cstates[3].exit_latency = usec; 17445dcef694SLen Brown bxt_cstates[3].target_residency = usec; 17455dcef694SLen Brown } 17465dcef694SLen Brown 17475dcef694SLen Brown rdmsrl(MSR_PKGC8_IRTL, msr); 17483451ab3eSJan Beulich usec = irtl_2_usec(msr); 17493451ab3eSJan Beulich if (usec) { 17505dcef694SLen Brown bxt_cstates[4].exit_latency = usec; 17515dcef694SLen Brown bxt_cstates[4].target_residency = usec; 17525dcef694SLen Brown } 17535dcef694SLen Brown 17545dcef694SLen Brown rdmsrl(MSR_PKGC9_IRTL, msr); 17553451ab3eSJan Beulich usec = irtl_2_usec(msr); 17563451ab3eSJan Beulich if (usec) { 17575dcef694SLen Brown bxt_cstates[5].exit_latency = usec; 17585dcef694SLen Brown bxt_cstates[5].target_residency = usec; 17595dcef694SLen Brown } 17605dcef694SLen Brown 17615dcef694SLen Brown rdmsrl(MSR_PKGC10_IRTL, msr); 17623451ab3eSJan Beulich usec = irtl_2_usec(msr); 17633451ab3eSJan Beulich if (usec) { 17645dcef694SLen Brown bxt_cstates[6].exit_latency = usec; 17655dcef694SLen Brown bxt_cstates[6].target_residency = usec; 17665dcef694SLen Brown } 17675dcef694SLen Brown 17685dcef694SLen Brown } 17696eacb15fSRafael J. Wysocki 17706eacb15fSRafael J. Wysocki /** 17716eacb15fSRafael J. Wysocki * sklh_idle_state_table_update - Fix up the Sky Lake idle states table. 1772d70e28f5SLen Brown * 17736eacb15fSRafael J. Wysocki * On SKL-H (model 0x5e) skip C8 and C9 if C10 is enabled and SGX disabled. 1774d70e28f5SLen Brown */ 1775095928aeSRafael J. Wysocki static void __init sklh_idle_state_table_update(void) 1776d70e28f5SLen Brown { 1777d70e28f5SLen Brown unsigned long long msr; 1778d70e28f5SLen Brown unsigned int eax, ebx, ecx, edx; 1779d70e28f5SLen Brown 1780d70e28f5SLen Brown 1781d70e28f5SLen Brown /* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */ 1782d70e28f5SLen Brown if (max_cstate <= 7) 17830138d8f0SLen Brown return; 1784d70e28f5SLen Brown 1785d70e28f5SLen Brown /* if PC10 not present in CPUID.MWAIT.EDX */ 1786d70e28f5SLen Brown if ((mwait_substates & (0xF << 28)) == 0) 1787d70e28f5SLen Brown return; 1788d70e28f5SLen Brown 17896cfb2374SLen Brown rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr); 1790d70e28f5SLen Brown 1791d70e28f5SLen Brown /* PC10 is not enabled in PKG C-state limit */ 1792d70e28f5SLen Brown if ((msr & 0xF) != 8) 1793d70e28f5SLen Brown return; 1794d70e28f5SLen Brown 1795d70e28f5SLen Brown ecx = 0; 1796d70e28f5SLen Brown cpuid(7, &eax, &ebx, &ecx, &edx); 1797d70e28f5SLen Brown 1798d70e28f5SLen Brown /* if SGX is present */ 1799d70e28f5SLen Brown if (ebx & (1 << 2)) { 1800d70e28f5SLen Brown 180132ad73dbSSean Christopherson rdmsrl(MSR_IA32_FEAT_CTL, msr); 1802d70e28f5SLen Brown 1803d70e28f5SLen Brown /* if SGX is enabled */ 1804d70e28f5SLen Brown if (msr & (1 << 18)) 1805d70e28f5SLen Brown return; 1806d70e28f5SLen Brown } 1807d70e28f5SLen Brown 1808ba1e78a1SRafael J. Wysocki skl_cstates[5].flags |= CPUIDLE_FLAG_UNUSABLE; /* C8-SKL */ 1809ba1e78a1SRafael J. Wysocki skl_cstates[6].flags |= CPUIDLE_FLAG_UNUSABLE; /* C9-SKL */ 1810d70e28f5SLen Brown } 1811d70e28f5SLen Brown 181264233338SChen Yu /** 181364233338SChen Yu * skx_idle_state_table_update - Adjust the Sky Lake/Cascade Lake 181464233338SChen Yu * idle states table. 181564233338SChen Yu */ 181664233338SChen Yu static void __init skx_idle_state_table_update(void) 181764233338SChen Yu { 181864233338SChen Yu unsigned long long msr; 181964233338SChen Yu 182064233338SChen Yu rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr); 182164233338SChen Yu 182264233338SChen Yu /* 182364233338SChen Yu * 000b: C0/C1 (no package C-state support) 182464233338SChen Yu * 001b: C2 182564233338SChen Yu * 010b: C6 (non-retention) 182664233338SChen Yu * 011b: C6 (retention) 182764233338SChen Yu * 111b: No Package C state limits. 182864233338SChen Yu */ 182964233338SChen Yu if ((msr & 0x7) < 2) { 183064233338SChen Yu /* 183164233338SChen Yu * Uses the CC6 + PC0 latency and 3 times of 183264233338SChen Yu * latency for target_residency if the PC6 183364233338SChen Yu * is disabled in BIOS. This is consistent 183464233338SChen Yu * with how intel_idle driver uses _CST 183564233338SChen Yu * to set the target_residency. 183664233338SChen Yu */ 183764233338SChen Yu skx_cstates[2].exit_latency = 92; 183864233338SChen Yu skx_cstates[2].target_residency = 276; 183964233338SChen Yu } 184064233338SChen Yu } 184164233338SChen Yu 1842da0e58c0SArtem Bityutskiy /** 1843d1cf8bbfSZhang Rui * adl_idle_state_table_update - Adjust AlderLake idle states table. 1844d1cf8bbfSZhang Rui */ 1845d1cf8bbfSZhang Rui static void __init adl_idle_state_table_update(void) 1846d1cf8bbfSZhang Rui { 1847d1cf8bbfSZhang Rui /* Check if user prefers C1 over C1E. */ 1848d1cf8bbfSZhang Rui if (preferred_states_mask & BIT(1) && !(preferred_states_mask & BIT(2))) { 1849d1cf8bbfSZhang Rui cpuidle_state_table[0].flags &= ~CPUIDLE_FLAG_UNUSABLE; 1850d1cf8bbfSZhang Rui cpuidle_state_table[1].flags |= CPUIDLE_FLAG_UNUSABLE; 1851d1cf8bbfSZhang Rui 1852d1cf8bbfSZhang Rui /* Disable C1E by clearing the "C1E promotion" bit. */ 1853d1cf8bbfSZhang Rui c1e_promotion = C1E_PROMOTION_DISABLE; 1854d1cf8bbfSZhang Rui return; 1855d1cf8bbfSZhang Rui } 1856d1cf8bbfSZhang Rui 1857d1cf8bbfSZhang Rui /* Make sure C1E is enabled by default */ 1858d1cf8bbfSZhang Rui c1e_promotion = C1E_PROMOTION_ENABLE; 1859d1cf8bbfSZhang Rui } 1860d1cf8bbfSZhang Rui 1861d1cf8bbfSZhang Rui /** 1862da0e58c0SArtem Bityutskiy * spr_idle_state_table_update - Adjust Sapphire Rapids idle states table. 1863da0e58c0SArtem Bityutskiy */ 1864da0e58c0SArtem Bityutskiy static void __init spr_idle_state_table_update(void) 1865da0e58c0SArtem Bityutskiy { 18663a9cf77bSArtem Bityutskiy unsigned long long msr; 18673a9cf77bSArtem Bityutskiy 18683a9cf77bSArtem Bityutskiy /* 18693a9cf77bSArtem Bityutskiy * By default, the C6 state assumes the worst-case scenario of package 18703a9cf77bSArtem Bityutskiy * C6. However, if PC6 is disabled, we update the numbers to match 18713a9cf77bSArtem Bityutskiy * core C6. 18723a9cf77bSArtem Bityutskiy */ 18733a9cf77bSArtem Bityutskiy rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr); 18743a9cf77bSArtem Bityutskiy 18753a9cf77bSArtem Bityutskiy /* Limit value 2 and above allow for PC6. */ 18763a9cf77bSArtem Bityutskiy if ((msr & 0x7) < 2) { 18773a9cf77bSArtem Bityutskiy spr_cstates[2].exit_latency = 190; 18783a9cf77bSArtem Bityutskiy spr_cstates[2].target_residency = 600; 18793a9cf77bSArtem Bityutskiy } 1880da0e58c0SArtem Bityutskiy } 1881da0e58c0SArtem Bityutskiy 18821aefbd7aSRafael J. Wysocki static bool __init intel_idle_verify_cstate(unsigned int mwait_hint) 18831aefbd7aSRafael J. Wysocki { 18841aefbd7aSRafael J. Wysocki unsigned int mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint) + 1; 18851aefbd7aSRafael J. Wysocki unsigned int num_substates = (mwait_substates >> mwait_cstate * 4) & 18861aefbd7aSRafael J. Wysocki MWAIT_SUBSTATE_MASK; 18871aefbd7aSRafael J. Wysocki 18881aefbd7aSRafael J. Wysocki /* Ignore the C-state if there are NO sub-states in CPUID for it. */ 18891aefbd7aSRafael J. Wysocki if (num_substates == 0) 18901aefbd7aSRafael J. Wysocki return false; 18911aefbd7aSRafael J. Wysocki 18921aefbd7aSRafael J. Wysocki if (mwait_cstate > 2 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) 18931aefbd7aSRafael J. Wysocki mark_tsc_unstable("TSC halts in idle states deeper than C2"); 18941aefbd7aSRafael J. Wysocki 18951aefbd7aSRafael J. Wysocki return true; 18961aefbd7aSRafael J. Wysocki } 18971aefbd7aSRafael J. Wysocki 18984622ba92SArjan van de Ven static void state_update_enter_method(struct cpuidle_state *state, int cstate) 18994622ba92SArjan van de Ven { 19002f3d08f0SArjan van de Ven if (state->enter == intel_idle_hlt) { 19012f3d08f0SArjan van de Ven if (force_irq_on) { 19022f3d08f0SArjan van de Ven pr_info("forced intel_idle_irq for state %d\n", cstate); 19032f3d08f0SArjan van de Ven state->enter = intel_idle_hlt_irq_on; 19042f3d08f0SArjan van de Ven } 19052f3d08f0SArjan van de Ven return; 19062f3d08f0SArjan van de Ven } 19072f3d08f0SArjan van de Ven if (state->enter == intel_idle_hlt_irq_on) 19082f3d08f0SArjan van de Ven return; /* no update scenarios */ 19092f3d08f0SArjan van de Ven 19104622ba92SArjan van de Ven if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) { 19114622ba92SArjan van de Ven /* 19124622ba92SArjan van de Ven * Combining with XSTATE with IBRS or IRQ_ENABLE flags 19134622ba92SArjan van de Ven * is not currently supported but this driver. 19144622ba92SArjan van de Ven */ 19154622ba92SArjan van de Ven WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IBRS); 19164622ba92SArjan van de Ven WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE); 19174622ba92SArjan van de Ven state->enter = intel_idle_xstate; 19187826c069SArjan van de Ven return; 19197826c069SArjan van de Ven } 19207826c069SArjan van de Ven 19217826c069SArjan van de Ven if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) && 19224622ba92SArjan van de Ven state->flags & CPUIDLE_FLAG_IBRS) { 19234622ba92SArjan van de Ven /* 19244622ba92SArjan van de Ven * IBRS mitigation requires that C-states are entered 19254622ba92SArjan van de Ven * with interrupts disabled. 19264622ba92SArjan van de Ven */ 19274622ba92SArjan van de Ven WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE); 19284622ba92SArjan van de Ven state->enter = intel_idle_ibrs; 19297826c069SArjan van de Ven return; 19307826c069SArjan van de Ven } 19317826c069SArjan van de Ven 19327826c069SArjan van de Ven if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE) { 19334622ba92SArjan van de Ven state->enter = intel_idle_irq; 19347826c069SArjan van de Ven return; 19357826c069SArjan van de Ven } 19367826c069SArjan van de Ven 19377826c069SArjan van de Ven if (force_irq_on) { 19384622ba92SArjan van de Ven pr_info("forced intel_idle_irq for state %d\n", cstate); 19394622ba92SArjan van de Ven state->enter = intel_idle_irq; 19404622ba92SArjan van de Ven } 19414622ba92SArjan van de Ven } 19424622ba92SArjan van de Ven 19432f3d08f0SArjan van de Ven /* 19442f3d08f0SArjan van de Ven * For mwait based states, we want to verify the cpuid data to see if the state 19452f3d08f0SArjan van de Ven * is actually supported by this specific CPU. 19462f3d08f0SArjan van de Ven * For non-mwait based states, this check should be skipped. 19472f3d08f0SArjan van de Ven */ 19482f3d08f0SArjan van de Ven static bool should_verify_mwait(struct cpuidle_state *state) 19492f3d08f0SArjan van de Ven { 19502f3d08f0SArjan van de Ven if (state->enter == intel_idle_hlt) 19512f3d08f0SArjan van de Ven return false; 19522f3d08f0SArjan van de Ven if (state->enter == intel_idle_hlt_irq_on) 19532f3d08f0SArjan van de Ven return false; 19542f3d08f0SArjan van de Ven 19552f3d08f0SArjan van de Ven return true; 19562f3d08f0SArjan van de Ven } 19572f3d08f0SArjan van de Ven 1958095928aeSRafael J. Wysocki static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv) 1959d70e28f5SLen Brown { 19603d3a1ae9SRafael J. Wysocki int cstate; 1961d70e28f5SLen Brown 19623d3a1ae9SRafael J. Wysocki switch (boot_cpu_data.x86_model) { 1963db73c5a8SDave Hansen case INTEL_FAM6_IVYBRIDGE_X: 1964d70e28f5SLen Brown ivt_idle_state_table_update(); 1965d70e28f5SLen Brown break; 1966db73c5a8SDave Hansen case INTEL_FAM6_ATOM_GOLDMONT: 1967f2c4db1bSPeter Zijlstra case INTEL_FAM6_ATOM_GOLDMONT_PLUS: 19685dcef694SLen Brown bxt_idle_state_table_update(); 19695dcef694SLen Brown break; 1970c66f78a6SPeter Zijlstra case INTEL_FAM6_SKYLAKE: 1971d70e28f5SLen Brown sklh_idle_state_table_update(); 1972d70e28f5SLen Brown break; 197364233338SChen Yu case INTEL_FAM6_SKYLAKE_X: 197464233338SChen Yu skx_idle_state_table_update(); 197564233338SChen Yu break; 1976da0e58c0SArtem Bityutskiy case INTEL_FAM6_SAPPHIRERAPIDS_X: 197774528edfSArtem Bityutskiy case INTEL_FAM6_EMERALDRAPIDS_X: 1978da0e58c0SArtem Bityutskiy spr_idle_state_table_update(); 1979da0e58c0SArtem Bityutskiy break; 1980d1cf8bbfSZhang Rui case INTEL_FAM6_ALDERLAKE: 1981d1cf8bbfSZhang Rui case INTEL_FAM6_ALDERLAKE_L: 198265c0c236SZhang Rui case INTEL_FAM6_ALDERLAKE_N: 1983d1cf8bbfSZhang Rui adl_idle_state_table_update(); 1984d1cf8bbfSZhang Rui break; 1985d70e28f5SLen Brown } 198646bcfad7SDeepthi Dharwar 1987e022e7ebSLen Brown for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { 19881abffbd8SArtem Bityutskiy struct cpuidle_state *state; 19899f3d6dafSRafael J. Wysocki unsigned int mwait_hint; 199046bcfad7SDeepthi Dharwar 199118734958SRafael J. Wysocki if (intel_idle_max_cstate_reached(cstate)) 199218734958SRafael J. Wysocki break; 199318734958SRafael J. Wysocki 19949f3d6dafSRafael J. Wysocki if (!cpuidle_state_table[cstate].enter && 19959f3d6dafSRafael J. Wysocki !cpuidle_state_table[cstate].enter_s2idle) 1996e022e7ebSLen Brown break; 1997e022e7ebSLen Brown 19989f3d6dafSRafael J. Wysocki /* If marked as unusable, skip this state. */ 1999ba1e78a1SRafael J. Wysocki if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_UNUSABLE) { 2000654d08a4SJoe Perches pr_debug("state %s is disabled\n", 2001d70e28f5SLen Brown cpuidle_state_table[cstate].name); 2002d70e28f5SLen Brown continue; 2003d70e28f5SLen Brown } 2004d70e28f5SLen Brown 20059f3d6dafSRafael J. Wysocki mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags); 20062f3d08f0SArjan van de Ven if (should_verify_mwait(&cpuidle_state_table[cstate]) && !intel_idle_verify_cstate(mwait_hint)) 20079f3d6dafSRafael J. Wysocki continue; 2008d70e28f5SLen Brown 20099f3d6dafSRafael J. Wysocki /* Structure copy. */ 2010bff8e60aSRafael J. Wysocki drv->states[drv->state_count] = cpuidle_state_table[cstate]; 20111abffbd8SArtem Bityutskiy state = &drv->states[drv->state_count]; 2012bff8e60aSRafael J. Wysocki 20134622ba92SArjan van de Ven state_update_enter_method(state, cstate); 20144622ba92SArjan van de Ven 201532d4fd57SPeter Zijlstra 20164dcb78eeSRafael J. Wysocki if ((disabled_states_mask & BIT(drv->state_count)) || 20174dcb78eeSRafael J. Wysocki ((icpu->use_acpi || force_use_acpi) && 20183a5be9b8SRafael J. Wysocki intel_idle_off_by_default(mwait_hint) && 20191abffbd8SArtem Bityutskiy !(state->flags & CPUIDLE_FLAG_ALWAYS_ENABLE))) 20201abffbd8SArtem Bityutskiy state->flags |= CPUIDLE_FLAG_OFF; 2021bff8e60aSRafael J. Wysocki 20221abffbd8SArtem Bityutskiy if (intel_idle_state_needs_timer_stop(state)) 20231abffbd8SArtem Bityutskiy state->flags |= CPUIDLE_FLAG_TIMER_STOP; 20246e1d2bc6SPeter Zijlstra 2025bff8e60aSRafael J. Wysocki drv->state_count++; 202646bcfad7SDeepthi Dharwar } 202746bcfad7SDeepthi Dharwar 20288c058d53SLen Brown if (icpu->byt_auto_demotion_disable_flag) { 20298c058d53SLen Brown wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0); 20308c058d53SLen Brown wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0); 20318c058d53SLen Brown } 203246bcfad7SDeepthi Dharwar } 203346bcfad7SDeepthi Dharwar 20346eacb15fSRafael J. Wysocki /** 20356eacb15fSRafael J. Wysocki * intel_idle_cpuidle_driver_init - Create the list of available idle states. 20366eacb15fSRafael J. Wysocki * @drv: cpuidle driver structure to initialize. 203718734958SRafael J. Wysocki */ 20383d3a1ae9SRafael J. Wysocki static void __init intel_idle_cpuidle_driver_init(struct cpuidle_driver *drv) 203918734958SRafael J. Wysocki { 204018734958SRafael J. Wysocki cpuidle_poll_state_init(drv); 20414dcb78eeSRafael J. Wysocki 20424dcb78eeSRafael J. Wysocki if (disabled_states_mask & BIT(0)) 20434dcb78eeSRafael J. Wysocki drv->states[0].flags |= CPUIDLE_FLAG_OFF; 20444dcb78eeSRafael J. Wysocki 204518734958SRafael J. Wysocki drv->state_count = 1; 204618734958SRafael J. Wysocki 204718734958SRafael J. Wysocki if (icpu) 204818734958SRafael J. Wysocki intel_idle_init_cstates_icpu(drv); 204918734958SRafael J. Wysocki else 205018734958SRafael J. Wysocki intel_idle_init_cstates_acpi(drv); 205118734958SRafael J. Wysocki } 205246bcfad7SDeepthi Dharwar 20531aefbd7aSRafael J. Wysocki static void auto_demotion_disable(void) 20541aefbd7aSRafael J. Wysocki { 20551aefbd7aSRafael J. Wysocki unsigned long long msr_bits; 20561aefbd7aSRafael J. Wysocki 20571aefbd7aSRafael J. Wysocki rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits); 20587f843dd7SRafael J. Wysocki msr_bits &= ~auto_demotion_disable_flags; 20591aefbd7aSRafael J. Wysocki wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits); 20601aefbd7aSRafael J. Wysocki } 20611aefbd7aSRafael J. Wysocki 2062da0e58c0SArtem Bityutskiy static void c1e_promotion_enable(void) 2063da0e58c0SArtem Bityutskiy { 2064da0e58c0SArtem Bityutskiy unsigned long long msr_bits; 2065da0e58c0SArtem Bityutskiy 2066da0e58c0SArtem Bityutskiy rdmsrl(MSR_IA32_POWER_CTL, msr_bits); 2067da0e58c0SArtem Bityutskiy msr_bits |= 0x2; 2068da0e58c0SArtem Bityutskiy wrmsrl(MSR_IA32_POWER_CTL, msr_bits); 2069da0e58c0SArtem Bityutskiy } 2070da0e58c0SArtem Bityutskiy 20711aefbd7aSRafael J. Wysocki static void c1e_promotion_disable(void) 20721aefbd7aSRafael J. Wysocki { 20731aefbd7aSRafael J. Wysocki unsigned long long msr_bits; 20741aefbd7aSRafael J. Wysocki 20751aefbd7aSRafael J. Wysocki rdmsrl(MSR_IA32_POWER_CTL, msr_bits); 20761aefbd7aSRafael J. Wysocki msr_bits &= ~0x2; 20771aefbd7aSRafael J. Wysocki wrmsrl(MSR_IA32_POWER_CTL, msr_bits); 20781aefbd7aSRafael J. Wysocki } 20791aefbd7aSRafael J. Wysocki 20806eacb15fSRafael J. Wysocki /** 20816eacb15fSRafael J. Wysocki * intel_idle_cpu_init - Register the target CPU with the cpuidle core. 20826eacb15fSRafael J. Wysocki * @cpu: CPU to initialize. 20836eacb15fSRafael J. Wysocki * 20846eacb15fSRafael J. Wysocki * Register a cpuidle device object for @cpu and update its MSRs in accordance 20856eacb15fSRafael J. Wysocki * with the processor model flags. 208626717172SLen Brown */ 2087fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_init(unsigned int cpu) 208826717172SLen Brown { 208926717172SLen Brown struct cpuidle_device *dev; 209026717172SLen Brown 209165b7f839SThomas Renninger dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu); 209265b7f839SThomas Renninger dev->cpu = cpu; 209326717172SLen Brown 209426717172SLen Brown if (cpuidle_register_device(dev)) { 2095654d08a4SJoe Perches pr_debug("cpuidle_register_device %d failed!\n", cpu); 209626717172SLen Brown return -EIO; 209726717172SLen Brown } 209865b7f839SThomas Renninger 20997f843dd7SRafael J. Wysocki if (auto_demotion_disable_flags) 2100fb1013a0SSebastian Andrzej Siewior auto_demotion_disable(); 210126717172SLen Brown 210239c184a6SArtem Bityutskiy if (c1e_promotion == C1E_PROMOTION_ENABLE) 210339c184a6SArtem Bityutskiy c1e_promotion_enable(); 210439c184a6SArtem Bityutskiy else if (c1e_promotion == C1E_PROMOTION_DISABLE) 2105fb1013a0SSebastian Andrzej Siewior c1e_promotion_disable(); 2106fb1013a0SSebastian Andrzej Siewior 2107fb1013a0SSebastian Andrzej Siewior return 0; 2108fb1013a0SSebastian Andrzej Siewior } 2109fb1013a0SSebastian Andrzej Siewior 2110fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_online(unsigned int cpu) 2111fb1013a0SSebastian Andrzej Siewior { 2112fb1013a0SSebastian Andrzej Siewior struct cpuidle_device *dev; 2113fb1013a0SSebastian Andrzej Siewior 2114dab20177SRafael J. Wysocki if (!boot_cpu_has(X86_FEATURE_ARAT)) 2115cbd2c4c2SRafael J. Wysocki tick_broadcast_enable(); 2116fb1013a0SSebastian Andrzej Siewior 2117fb1013a0SSebastian Andrzej Siewior /* 2118fb1013a0SSebastian Andrzej Siewior * Some systems can hotplug a cpu at runtime after 2119fb1013a0SSebastian Andrzej Siewior * the kernel has booted, we have to initialize the 2120fb1013a0SSebastian Andrzej Siewior * driver in this case 2121fb1013a0SSebastian Andrzej Siewior */ 2122fb1013a0SSebastian Andrzej Siewior dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu); 2123fb1013a0SSebastian Andrzej Siewior if (!dev->registered) 2124fb1013a0SSebastian Andrzej Siewior return intel_idle_cpu_init(cpu); 2125dbf87ab8SBartlomiej Zolnierkiewicz 212626717172SLen Brown return 0; 212726717172SLen Brown } 212826717172SLen Brown 21290755a9bdSRafael J. Wysocki /** 21300755a9bdSRafael J. Wysocki * intel_idle_cpuidle_devices_uninit - Unregister all cpuidle devices. 21310755a9bdSRafael J. Wysocki */ 21320755a9bdSRafael J. Wysocki static void __init intel_idle_cpuidle_devices_uninit(void) 21330755a9bdSRafael J. Wysocki { 21340755a9bdSRafael J. Wysocki int i; 21350755a9bdSRafael J. Wysocki 21360755a9bdSRafael J. Wysocki for_each_online_cpu(i) 21370755a9bdSRafael J. Wysocki cpuidle_unregister_device(per_cpu_ptr(intel_idle_cpuidle_devices, i)); 21380755a9bdSRafael J. Wysocki } 21390755a9bdSRafael J. Wysocki 2140*0fac214bSArjan van de Ven /* 2141*0fac214bSArjan van de Ven * Match up the latency and break even point of the bare metal (cpu based) 2142*0fac214bSArjan van de Ven * states with the deepest VM available state. 2143*0fac214bSArjan van de Ven * 2144*0fac214bSArjan van de Ven * We only want to do this for the deepest state, the ones that has 2145*0fac214bSArjan van de Ven * the TLB_FLUSHED flag set on the . 2146*0fac214bSArjan van de Ven * 2147*0fac214bSArjan van de Ven * All our short idle states are dominated by vmexit/vmenter latencies, 2148*0fac214bSArjan van de Ven * not the underlying hardware latencies so we keep our values for these. 2149*0fac214bSArjan van de Ven */ 2150*0fac214bSArjan van de Ven static void matchup_vm_state_with_baremetal(void) 2151*0fac214bSArjan van de Ven { 2152*0fac214bSArjan van de Ven int cstate; 2153*0fac214bSArjan van de Ven 2154*0fac214bSArjan van de Ven for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { 2155*0fac214bSArjan van de Ven int matching_cstate; 2156*0fac214bSArjan van de Ven 2157*0fac214bSArjan van de Ven if (intel_idle_max_cstate_reached(cstate)) 2158*0fac214bSArjan van de Ven break; 2159*0fac214bSArjan van de Ven 2160*0fac214bSArjan van de Ven if (!cpuidle_state_table[cstate].enter) 2161*0fac214bSArjan van de Ven break; 2162*0fac214bSArjan van de Ven 2163*0fac214bSArjan van de Ven if (!(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_TLB_FLUSHED)) 2164*0fac214bSArjan van de Ven continue; 2165*0fac214bSArjan van de Ven 2166*0fac214bSArjan van de Ven for (matching_cstate = 0; matching_cstate < CPUIDLE_STATE_MAX; ++matching_cstate) { 2167*0fac214bSArjan van de Ven if (!icpu->state_table[matching_cstate].enter) 2168*0fac214bSArjan van de Ven break; 2169*0fac214bSArjan van de Ven if (icpu->state_table[matching_cstate].exit_latency > cpuidle_state_table[cstate].exit_latency) { 2170*0fac214bSArjan van de Ven cpuidle_state_table[cstate].exit_latency = icpu->state_table[matching_cstate].exit_latency; 2171*0fac214bSArjan van de Ven cpuidle_state_table[cstate].target_residency = icpu->state_table[matching_cstate].target_residency; 2172*0fac214bSArjan van de Ven } 2173*0fac214bSArjan van de Ven } 2174*0fac214bSArjan van de Ven 2175*0fac214bSArjan van de Ven } 2176*0fac214bSArjan van de Ven } 2177*0fac214bSArjan van de Ven 2178*0fac214bSArjan van de Ven 21792f3d08f0SArjan van de Ven static int __init intel_idle_vminit(const struct x86_cpu_id *id) 21802f3d08f0SArjan van de Ven { 21812f3d08f0SArjan van de Ven int retval; 21822f3d08f0SArjan van de Ven 21832f3d08f0SArjan van de Ven cpuidle_state_table = vmguest_cstates; 21842f3d08f0SArjan van de Ven 21852f3d08f0SArjan van de Ven icpu = (const struct idle_cpu *)id->driver_data; 21862f3d08f0SArjan van de Ven 21872f3d08f0SArjan van de Ven pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n", 21882f3d08f0SArjan van de Ven boot_cpu_data.x86_model); 21892f3d08f0SArjan van de Ven 21902f3d08f0SArjan van de Ven intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device); 21912f3d08f0SArjan van de Ven if (!intel_idle_cpuidle_devices) 21922f3d08f0SArjan van de Ven return -ENOMEM; 21932f3d08f0SArjan van de Ven 2194*0fac214bSArjan van de Ven /* 2195*0fac214bSArjan van de Ven * We don't know exactly what the host will do when we go idle, but as a worst estimate 2196*0fac214bSArjan van de Ven * we can assume that the exit latency of the deepest host state will be hit for our 2197*0fac214bSArjan van de Ven * deep (long duration) guest idle state. 2198*0fac214bSArjan van de Ven * The same logic applies to the break even point for the long duration guest idle state. 2199*0fac214bSArjan van de Ven * So lets copy these two properties from the table we found for the host CPU type. 2200*0fac214bSArjan van de Ven */ 2201*0fac214bSArjan van de Ven matchup_vm_state_with_baremetal(); 2202*0fac214bSArjan van de Ven 22032f3d08f0SArjan van de Ven intel_idle_cpuidle_driver_init(&intel_idle_driver); 22042f3d08f0SArjan van de Ven 22052f3d08f0SArjan van de Ven retval = cpuidle_register_driver(&intel_idle_driver); 22062f3d08f0SArjan van de Ven if (retval) { 22072f3d08f0SArjan van de Ven struct cpuidle_driver *drv = cpuidle_get_driver(); 22082f3d08f0SArjan van de Ven printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"), 22092f3d08f0SArjan van de Ven drv ? drv->name : "none"); 22102f3d08f0SArjan van de Ven goto init_driver_fail; 22112f3d08f0SArjan van de Ven } 22122f3d08f0SArjan van de Ven 22132f3d08f0SArjan van de Ven retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online", 22142f3d08f0SArjan van de Ven intel_idle_cpu_online, NULL); 22152f3d08f0SArjan van de Ven if (retval < 0) 22162f3d08f0SArjan van de Ven goto hp_setup_fail; 22172f3d08f0SArjan van de Ven 22182f3d08f0SArjan van de Ven return 0; 22192f3d08f0SArjan van de Ven hp_setup_fail: 22202f3d08f0SArjan van de Ven intel_idle_cpuidle_devices_uninit(); 22212f3d08f0SArjan van de Ven cpuidle_unregister_driver(&intel_idle_driver); 22222f3d08f0SArjan van de Ven init_driver_fail: 22232f3d08f0SArjan van de Ven free_percpu(intel_idle_cpuidle_devices); 22242f3d08f0SArjan van de Ven return retval; 22252f3d08f0SArjan van de Ven } 22262f3d08f0SArjan van de Ven 222726717172SLen Brown static int __init intel_idle_init(void) 222826717172SLen Brown { 2229a6c86e33SRafael J. Wysocki const struct x86_cpu_id *id; 2230a6c86e33SRafael J. Wysocki unsigned int eax, ebx, ecx; 2231fb1013a0SSebastian Andrzej Siewior int retval; 223226717172SLen Brown 2233d1896049SThomas Renninger /* Do not load intel_idle at all for now if idle= is passed */ 2234d1896049SThomas Renninger if (boot_option_idle_override != IDLE_NO_OVERRIDE) 2235d1896049SThomas Renninger return -ENODEV; 2236d1896049SThomas Renninger 2237a6c86e33SRafael J. Wysocki if (max_cstate == 0) { 2238a6c86e33SRafael J. Wysocki pr_debug("disabled\n"); 2239a6c86e33SRafael J. Wysocki return -EPERM; 2240a6c86e33SRafael J. Wysocki } 2241a6c86e33SRafael J. Wysocki 2242a6c86e33SRafael J. Wysocki id = x86_match_cpu(intel_idle_ids); 2243a6c86e33SRafael J. Wysocki if (id) { 2244a6c86e33SRafael J. Wysocki if (!boot_cpu_has(X86_FEATURE_MWAIT)) { 22452f3d08f0SArjan van de Ven if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) 22462f3d08f0SArjan van de Ven return intel_idle_vminit(id); 2247a6c86e33SRafael J. Wysocki pr_debug("Please enable MWAIT in BIOS SETUP\n"); 2248a6c86e33SRafael J. Wysocki return -ENODEV; 2249a6c86e33SRafael J. Wysocki } 2250a6c86e33SRafael J. Wysocki } else { 2251a6c86e33SRafael J. Wysocki id = x86_match_cpu(intel_mwait_ids); 2252a6c86e33SRafael J. Wysocki if (!id) 2253a6c86e33SRafael J. Wysocki return -ENODEV; 2254a6c86e33SRafael J. Wysocki } 2255a6c86e33SRafael J. Wysocki 2256a6c86e33SRafael J. Wysocki if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) 2257a6c86e33SRafael J. Wysocki return -ENODEV; 2258a6c86e33SRafael J. Wysocki 2259a6c86e33SRafael J. Wysocki cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates); 2260a6c86e33SRafael J. Wysocki 2261a6c86e33SRafael J. Wysocki if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) || 2262a6c86e33SRafael J. Wysocki !(ecx & CPUID5_ECX_INTERRUPT_BREAK) || 2263a6c86e33SRafael J. Wysocki !mwait_substates) 2264a6c86e33SRafael J. Wysocki return -ENODEV; 2265a6c86e33SRafael J. Wysocki 2266a6c86e33SRafael J. Wysocki pr_debug("MWAIT substates: 0x%x\n", mwait_substates); 2267a6c86e33SRafael J. Wysocki 2268a6c86e33SRafael J. Wysocki icpu = (const struct idle_cpu *)id->driver_data; 2269a6c86e33SRafael J. Wysocki if (icpu) { 2270a6c86e33SRafael J. Wysocki cpuidle_state_table = icpu->state_table; 22717f843dd7SRafael J. Wysocki auto_demotion_disable_flags = icpu->auto_demotion_disable_flags; 227239c184a6SArtem Bityutskiy if (icpu->disable_promotion_to_c1e) 227339c184a6SArtem Bityutskiy c1e_promotion = C1E_PROMOTION_DISABLE; 22743a5be9b8SRafael J. Wysocki if (icpu->use_acpi || force_use_acpi) 2275a6c86e33SRafael J. Wysocki intel_idle_acpi_cst_extract(); 2276a6c86e33SRafael J. Wysocki } else if (!intel_idle_acpi_cst_extract()) { 2277a6c86e33SRafael J. Wysocki return -ENODEV; 2278a6c86e33SRafael J. Wysocki } 2279a6c86e33SRafael J. Wysocki 2280a6c86e33SRafael J. Wysocki pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n", 2281a6c86e33SRafael J. Wysocki boot_cpu_data.x86_model); 228226717172SLen Brown 2283e9df69ccSRichard Cochran intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device); 2284533da74aSRafael J. Wysocki if (!intel_idle_cpuidle_devices) 2285e9df69ccSRichard Cochran return -ENOMEM; 2286e9df69ccSRichard Cochran 22873d3a1ae9SRafael J. Wysocki intel_idle_cpuidle_driver_init(&intel_idle_driver); 22883d3a1ae9SRafael J. Wysocki 228926717172SLen Brown retval = cpuidle_register_driver(&intel_idle_driver); 229026717172SLen Brown if (retval) { 22913735d524SKonrad Rzeszutek Wilk struct cpuidle_driver *drv = cpuidle_get_driver(); 2292654d08a4SJoe Perches printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"), 22933735d524SKonrad Rzeszutek Wilk drv ? drv->name : "none"); 2294fb1013a0SSebastian Andrzej Siewior goto init_driver_fail; 229526717172SLen Brown } 229626717172SLen Brown 2297fb1013a0SSebastian Andrzej Siewior retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online", 2298fb1013a0SSebastian Andrzej Siewior intel_idle_cpu_online, NULL); 2299fb1013a0SSebastian Andrzej Siewior if (retval < 0) 2300fb1013a0SSebastian Andrzej Siewior goto hp_setup_fail; 230126717172SLen Brown 230240ab82e0SRafael J. Wysocki pr_debug("Local APIC timer is reliable in %s\n", 2303dab20177SRafael J. Wysocki boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1"); 23042259a819SRichard Cochran 230526717172SLen Brown return 0; 2306fb1013a0SSebastian Andrzej Siewior 2307fb1013a0SSebastian Andrzej Siewior hp_setup_fail: 2308fb1013a0SSebastian Andrzej Siewior intel_idle_cpuidle_devices_uninit(); 2309fb1013a0SSebastian Andrzej Siewior cpuidle_unregister_driver(&intel_idle_driver); 2310fb1013a0SSebastian Andrzej Siewior init_driver_fail: 2311fb1013a0SSebastian Andrzej Siewior free_percpu(intel_idle_cpuidle_devices); 2312fb1013a0SSebastian Andrzej Siewior return retval; 2313fb1013a0SSebastian Andrzej Siewior 231426717172SLen Brown } 231502c4fae9SPaul Gortmaker device_initcall(intel_idle_init); 231626717172SLen Brown 231702c4fae9SPaul Gortmaker /* 231802c4fae9SPaul Gortmaker * We are not really modular, but we used to support that. Meaning we also 231902c4fae9SPaul Gortmaker * support "intel_idle.max_cstate=..." at boot and also a read-only export of 232002c4fae9SPaul Gortmaker * it at /sys/module/intel_idle/parameters/max_cstate -- so using module_param 232102c4fae9SPaul Gortmaker * is the easiest way (currently) to continue doing that. 232202c4fae9SPaul Gortmaker */ 232326717172SLen Brown module_param(max_cstate, int, 0444); 23244dcb78eeSRafael J. Wysocki /* 23254dcb78eeSRafael J. Wysocki * The positions of the bits that are set in this number are the indices of the 23264dcb78eeSRafael J. Wysocki * idle states to be disabled by default (as reflected by the names of the 23274dcb78eeSRafael J. Wysocki * corresponding idle state directories in sysfs, "state0", "state1" ... 23284dcb78eeSRafael J. Wysocki * "state<i>" ..., where <i> is the index of the given state). 23294dcb78eeSRafael J. Wysocki */ 23304dcb78eeSRafael J. Wysocki module_param_named(states_off, disabled_states_mask, uint, 0444); 23314dcb78eeSRafael J. Wysocki MODULE_PARM_DESC(states_off, "Mask of disabled idle states"); 2332da0e58c0SArtem Bityutskiy /* 2333da0e58c0SArtem Bityutskiy * Some platforms come with mutually exclusive C-states, so that if one is 2334da0e58c0SArtem Bityutskiy * enabled, the other C-states must not be used. Example: C1 and C1E on 2335da0e58c0SArtem Bityutskiy * Sapphire Rapids platform. This parameter allows for selecting the 2336da0e58c0SArtem Bityutskiy * preferred C-states among the groups of mutually exclusive C-states - the 2337da0e58c0SArtem Bityutskiy * selected C-states will be registered, the other C-states from the mutually 2338da0e58c0SArtem Bityutskiy * exclusive group won't be registered. If the platform has no mutually 2339da0e58c0SArtem Bityutskiy * exclusive C-states, this parameter has no effect. 2340da0e58c0SArtem Bityutskiy */ 2341da0e58c0SArtem Bityutskiy module_param_named(preferred_cstates, preferred_states_mask, uint, 0444); 2342da0e58c0SArtem Bityutskiy MODULE_PARM_DESC(preferred_cstates, "Mask of preferred idle states"); 23434152379aSArtem Bityutskiy /* 23444152379aSArtem Bityutskiy * Debugging option that forces the driver to enter all C-states with 23454152379aSArtem Bityutskiy * interrupts enabled. Does not apply to C-states with 23464152379aSArtem Bityutskiy * 'CPUIDLE_FLAG_INIT_XSTATE' and 'CPUIDLE_FLAG_IBRS' flags. 23474152379aSArtem Bityutskiy */ 23484152379aSArtem Bityutskiy module_param(force_irq_on, bool, 0444); 2349