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 * 5fab04b22SLen Brown * Copyright (c) 2013, Intel Corporation. 626717172SLen Brown * Len Brown <len.brown@intel.com> 726717172SLen Brown */ 826717172SLen Brown 926717172SLen Brown /* 1026717172SLen Brown * intel_idle is a cpuidle driver that loads on specific Intel processors 1126717172SLen Brown * in lieu of the legacy ACPI processor_idle driver. The intent is to 1226717172SLen Brown * make Linux more efficient on these processors, as intel_idle knows 1326717172SLen Brown * more than ACPI, as well as make Linux more immune to ACPI BIOS bugs. 1426717172SLen Brown */ 1526717172SLen Brown 1626717172SLen Brown /* 1726717172SLen Brown * Design Assumptions 1826717172SLen Brown * 1926717172SLen Brown * All CPUs have same idle states as boot CPU 2026717172SLen Brown * 2126717172SLen Brown * Chipset BM_STS (bus master status) bit is a NOP 2226717172SLen Brown * for preventing entry into deep C-stats 2326717172SLen Brown */ 2426717172SLen Brown 2526717172SLen Brown /* 2626717172SLen Brown * Known limitations 2726717172SLen Brown * 2826717172SLen Brown * The driver currently initializes for_each_online_cpu() upon modprobe. 2926717172SLen Brown * It it unaware of subsequent processors hot-added to the system. 3026717172SLen Brown * This means that if you boot with maxcpus=n and later online 3126717172SLen Brown * processors above n, those processors will use C1 only. 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 */ 4026717172SLen Brown #define DEBUG 4126717172SLen Brown 42654d08a4SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 43654d08a4SJoe Perches 4426717172SLen Brown #include <linux/kernel.h> 4526717172SLen Brown #include <linux/cpuidle.h> 4676962caaSThomas Gleixner #include <linux/tick.h> 4726717172SLen Brown #include <trace/events/power.h> 4826717172SLen Brown #include <linux/sched.h> 492a2d31c8SShaohua Li #include <linux/notifier.h> 502a2d31c8SShaohua Li #include <linux/cpu.h> 5102c4fae9SPaul Gortmaker #include <linux/moduleparam.h> 52b66b8b9aSAndi Kleen #include <asm/cpu_device_id.h> 53db73c5a8SDave Hansen #include <asm/intel-family.h> 54bc83ccccSH. Peter Anvin #include <asm/mwait.h> 5514796fcaSLen Brown #include <asm/msr.h> 5626717172SLen Brown 57d70e28f5SLen Brown #define INTEL_IDLE_VERSION "0.4.1" 5826717172SLen Brown 5926717172SLen Brown static struct cpuidle_driver intel_idle_driver = { 6026717172SLen Brown .name = "intel_idle", 6126717172SLen Brown .owner = THIS_MODULE, 6226717172SLen Brown }; 6326717172SLen Brown /* intel_idle.max_cstate=0 disables driver */ 64137ecc77SLen Brown static int max_cstate = CPUIDLE_STATE_MAX - 1; 6526717172SLen Brown 66c4236282SLen Brown static unsigned int mwait_substates; 6726717172SLen Brown 682a2d31c8SShaohua Li #define LAPIC_TIMER_ALWAYS_RELIABLE 0xFFFFFFFF 6926717172SLen Brown /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ 70d13780d4SLen Brown static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */ 7126717172SLen Brown 72b66b8b9aSAndi Kleen struct idle_cpu { 73b66b8b9aSAndi Kleen struct cpuidle_state *state_table; 7426717172SLen Brown 7526717172SLen Brown /* 7614796fcaSLen Brown * Hardware C-state auto-demotion may not always be optimal. 7714796fcaSLen Brown * Indicate which enable bits to clear here. 7814796fcaSLen Brown */ 79b66b8b9aSAndi Kleen unsigned long auto_demotion_disable_flags; 808c058d53SLen Brown bool byt_auto_demotion_disable_flag; 8132e95180SLen Brown bool disable_promotion_to_c1e; 82b66b8b9aSAndi Kleen }; 83b66b8b9aSAndi Kleen 84b66b8b9aSAndi Kleen static const struct idle_cpu *icpu; 85b66b8b9aSAndi Kleen static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; 86b66b8b9aSAndi Kleen static int intel_idle(struct cpuidle_device *dev, 87b66b8b9aSAndi Kleen struct cpuidle_driver *drv, int index); 8828ba086eSRafael J. Wysocki static void intel_idle_s2idle(struct cpuidle_device *dev, 895fe2e527SRafael J. Wysocki struct cpuidle_driver *drv, int index); 90b66b8b9aSAndi Kleen static struct cpuidle_state *cpuidle_state_table; 9114796fcaSLen Brown 9214796fcaSLen Brown /* 93956d033fSLen Brown * Set this flag for states where the HW flushes the TLB for us 94956d033fSLen Brown * and so we don't need cross-calls to keep it consistent. 95956d033fSLen Brown * If this flag is set, SW flushes the TLB, so even if the 96956d033fSLen Brown * HW doesn't do the flushing, this flag is safe to use. 97956d033fSLen Brown */ 98956d033fSLen Brown #define CPUIDLE_FLAG_TLB_FLUSHED 0x10000 99956d033fSLen Brown 100956d033fSLen Brown /* 101b1beab48SLen Brown * MWAIT takes an 8-bit "hint" in EAX "suggesting" 102b1beab48SLen Brown * the C-state (top nibble) and sub-state (bottom nibble) 103b1beab48SLen Brown * 0x00 means "MWAIT(C1)", 0x10 means "MWAIT(C2)" etc. 104b1beab48SLen Brown * 105b1beab48SLen Brown * We store the hint at the top of our "flags" for each state. 106b1beab48SLen Brown */ 107b1beab48SLen Brown #define flg2MWAIT(flags) (((flags) >> 24) & 0xFF) 108b1beab48SLen Brown #define MWAIT2flg(eax) ((eax & 0xFF) << 24) 109b1beab48SLen Brown 110b1beab48SLen Brown /* 11126717172SLen Brown * States are indexed by the cstate number, 11226717172SLen Brown * which is also the index into the MWAIT hint array. 11326717172SLen Brown * Thus C0 is a dummy. 11426717172SLen Brown */ 115ba0dc81eSJiang Liu static struct cpuidle_state nehalem_cstates[] = { 116e022e7ebSLen Brown { 117de09cdd0SLen Brown .name = "C1", 11826717172SLen Brown .desc = "MWAIT 0x00", 119b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 12026717172SLen Brown .exit_latency = 3, 12126717172SLen Brown .target_residency = 6, 1225fe2e527SRafael J. Wysocki .enter = &intel_idle, 12328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 124e022e7ebSLen Brown { 125de09cdd0SLen Brown .name = "C1E", 12632e95180SLen Brown .desc = "MWAIT 0x01", 127b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x01), 12832e95180SLen Brown .exit_latency = 10, 12932e95180SLen Brown .target_residency = 20, 1305fe2e527SRafael J. Wysocki .enter = &intel_idle, 13128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 13232e95180SLen Brown { 133de09cdd0SLen Brown .name = "C3", 13426717172SLen Brown .desc = "MWAIT 0x10", 135b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 13626717172SLen Brown .exit_latency = 20, 13726717172SLen Brown .target_residency = 80, 1385fe2e527SRafael J. Wysocki .enter = &intel_idle, 13928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 140e022e7ebSLen Brown { 141de09cdd0SLen Brown .name = "C6", 14226717172SLen Brown .desc = "MWAIT 0x20", 143b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 14426717172SLen Brown .exit_latency = 200, 14526717172SLen Brown .target_residency = 800, 1465fe2e527SRafael J. Wysocki .enter = &intel_idle, 14728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 148e022e7ebSLen Brown { 149e022e7ebSLen Brown .enter = NULL } 15026717172SLen Brown }; 15126717172SLen Brown 152ba0dc81eSJiang Liu static struct cpuidle_state snb_cstates[] = { 153e022e7ebSLen Brown { 154de09cdd0SLen Brown .name = "C1", 155d13780d4SLen Brown .desc = "MWAIT 0x00", 156b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 15732e95180SLen Brown .exit_latency = 2, 15832e95180SLen Brown .target_residency = 2, 1595fe2e527SRafael J. Wysocki .enter = &intel_idle, 16028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 16132e95180SLen Brown { 162de09cdd0SLen Brown .name = "C1E", 16332e95180SLen Brown .desc = "MWAIT 0x01", 164b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x01), 16532e95180SLen Brown .exit_latency = 10, 16632e95180SLen Brown .target_residency = 20, 1675fe2e527SRafael J. Wysocki .enter = &intel_idle, 16828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 169e022e7ebSLen Brown { 170de09cdd0SLen Brown .name = "C3", 171d13780d4SLen Brown .desc = "MWAIT 0x10", 172b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 173d13780d4SLen Brown .exit_latency = 80, 174ddbd550dSLen Brown .target_residency = 211, 1755fe2e527SRafael J. Wysocki .enter = &intel_idle, 17628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 177e022e7ebSLen Brown { 178de09cdd0SLen Brown .name = "C6", 179d13780d4SLen Brown .desc = "MWAIT 0x20", 180b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 181d13780d4SLen Brown .exit_latency = 104, 182ddbd550dSLen Brown .target_residency = 345, 1835fe2e527SRafael J. Wysocki .enter = &intel_idle, 18428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 185e022e7ebSLen Brown { 186de09cdd0SLen Brown .name = "C7", 187d13780d4SLen Brown .desc = "MWAIT 0x30", 188b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 189d13780d4SLen Brown .exit_latency = 109, 190ddbd550dSLen Brown .target_residency = 345, 1915fe2e527SRafael J. Wysocki .enter = &intel_idle, 19228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 193e022e7ebSLen Brown { 194e022e7ebSLen Brown .enter = NULL } 195d13780d4SLen Brown }; 196d13780d4SLen Brown 197718987d6SLen Brown static struct cpuidle_state byt_cstates[] = { 198718987d6SLen Brown { 199de09cdd0SLen Brown .name = "C1", 200718987d6SLen Brown .desc = "MWAIT 0x00", 201b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 202718987d6SLen Brown .exit_latency = 1, 203718987d6SLen Brown .target_residency = 1, 2045fe2e527SRafael J. Wysocki .enter = &intel_idle, 20528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 206718987d6SLen Brown { 207de09cdd0SLen Brown .name = "C6N", 208718987d6SLen Brown .desc = "MWAIT 0x58", 209b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, 210d7ef7671SLen Brown .exit_latency = 300, 211718987d6SLen Brown .target_residency = 275, 2125fe2e527SRafael J. Wysocki .enter = &intel_idle, 21328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 214718987d6SLen Brown { 215de09cdd0SLen Brown .name = "C6S", 216718987d6SLen Brown .desc = "MWAIT 0x52", 217b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 218d7ef7671SLen Brown .exit_latency = 500, 219718987d6SLen Brown .target_residency = 560, 2205fe2e527SRafael J. Wysocki .enter = &intel_idle, 22128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 222718987d6SLen Brown { 223de09cdd0SLen Brown .name = "C7", 224718987d6SLen Brown .desc = "MWAIT 0x60", 225b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 226718987d6SLen Brown .exit_latency = 1200, 227d7ef7671SLen Brown .target_residency = 4000, 2285fe2e527SRafael J. Wysocki .enter = &intel_idle, 22928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 230718987d6SLen Brown { 231de09cdd0SLen Brown .name = "C7S", 232718987d6SLen Brown .desc = "MWAIT 0x64", 233b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, 234718987d6SLen Brown .exit_latency = 10000, 235718987d6SLen Brown .target_residency = 20000, 2365fe2e527SRafael J. Wysocki .enter = &intel_idle, 23728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 238718987d6SLen Brown { 239718987d6SLen Brown .enter = NULL } 240718987d6SLen Brown }; 241718987d6SLen Brown 242cab07a56SLen Brown static struct cpuidle_state cht_cstates[] = { 243cab07a56SLen Brown { 244de09cdd0SLen Brown .name = "C1", 245cab07a56SLen Brown .desc = "MWAIT 0x00", 246cab07a56SLen Brown .flags = MWAIT2flg(0x00), 247cab07a56SLen Brown .exit_latency = 1, 248cab07a56SLen Brown .target_residency = 1, 249cab07a56SLen Brown .enter = &intel_idle, 25028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 251cab07a56SLen Brown { 252de09cdd0SLen Brown .name = "C6N", 253cab07a56SLen Brown .desc = "MWAIT 0x58", 254cab07a56SLen Brown .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TLB_FLUSHED, 255cab07a56SLen Brown .exit_latency = 80, 256cab07a56SLen Brown .target_residency = 275, 257cab07a56SLen Brown .enter = &intel_idle, 25828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 259cab07a56SLen Brown { 260de09cdd0SLen Brown .name = "C6S", 261cab07a56SLen Brown .desc = "MWAIT 0x52", 262cab07a56SLen Brown .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 263cab07a56SLen Brown .exit_latency = 200, 264cab07a56SLen Brown .target_residency = 560, 265cab07a56SLen Brown .enter = &intel_idle, 26628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 267cab07a56SLen Brown { 268de09cdd0SLen Brown .name = "C7", 269cab07a56SLen Brown .desc = "MWAIT 0x60", 270cab07a56SLen Brown .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 271cab07a56SLen Brown .exit_latency = 1200, 272cab07a56SLen Brown .target_residency = 4000, 273cab07a56SLen Brown .enter = &intel_idle, 27428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 275cab07a56SLen Brown { 276de09cdd0SLen Brown .name = "C7S", 277cab07a56SLen Brown .desc = "MWAIT 0x64", 278cab07a56SLen Brown .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, 279cab07a56SLen Brown .exit_latency = 10000, 280cab07a56SLen Brown .target_residency = 20000, 281cab07a56SLen Brown .enter = &intel_idle, 28228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 283cab07a56SLen Brown { 284cab07a56SLen Brown .enter = NULL } 285cab07a56SLen Brown }; 286cab07a56SLen Brown 287ba0dc81eSJiang Liu static struct cpuidle_state ivb_cstates[] = { 288e022e7ebSLen Brown { 289de09cdd0SLen Brown .name = "C1", 2906edab08cSLen Brown .desc = "MWAIT 0x00", 291b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 2926edab08cSLen Brown .exit_latency = 1, 2936edab08cSLen Brown .target_residency = 1, 2945fe2e527SRafael J. Wysocki .enter = &intel_idle, 29528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 296e022e7ebSLen Brown { 297de09cdd0SLen Brown .name = "C1E", 29832e95180SLen Brown .desc = "MWAIT 0x01", 299b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x01), 30032e95180SLen Brown .exit_latency = 10, 30132e95180SLen Brown .target_residency = 20, 3025fe2e527SRafael J. Wysocki .enter = &intel_idle, 30328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 30432e95180SLen Brown { 305de09cdd0SLen Brown .name = "C3", 3066edab08cSLen Brown .desc = "MWAIT 0x10", 307b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 3086edab08cSLen Brown .exit_latency = 59, 3096edab08cSLen Brown .target_residency = 156, 3105fe2e527SRafael J. Wysocki .enter = &intel_idle, 31128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 312e022e7ebSLen Brown { 313de09cdd0SLen Brown .name = "C6", 3146edab08cSLen Brown .desc = "MWAIT 0x20", 315b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 3166edab08cSLen Brown .exit_latency = 80, 3176edab08cSLen Brown .target_residency = 300, 3185fe2e527SRafael J. Wysocki .enter = &intel_idle, 31928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 320e022e7ebSLen Brown { 321de09cdd0SLen Brown .name = "C7", 3226edab08cSLen Brown .desc = "MWAIT 0x30", 323b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 3246edab08cSLen Brown .exit_latency = 87, 3256edab08cSLen Brown .target_residency = 300, 3265fe2e527SRafael J. Wysocki .enter = &intel_idle, 32728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 328e022e7ebSLen Brown { 329e022e7ebSLen Brown .enter = NULL } 3306edab08cSLen Brown }; 3316edab08cSLen Brown 3320138d8f0SLen Brown static struct cpuidle_state ivt_cstates[] = { 3330138d8f0SLen Brown { 334de09cdd0SLen Brown .name = "C1", 3350138d8f0SLen Brown .desc = "MWAIT 0x00", 336b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 3370138d8f0SLen Brown .exit_latency = 1, 3380138d8f0SLen Brown .target_residency = 1, 3395fe2e527SRafael J. Wysocki .enter = &intel_idle, 34028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 3410138d8f0SLen Brown { 342de09cdd0SLen Brown .name = "C1E", 3430138d8f0SLen Brown .desc = "MWAIT 0x01", 344b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x01), 3450138d8f0SLen Brown .exit_latency = 10, 3460138d8f0SLen Brown .target_residency = 80, 3475fe2e527SRafael J. Wysocki .enter = &intel_idle, 34828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 3490138d8f0SLen Brown { 350de09cdd0SLen Brown .name = "C3", 3510138d8f0SLen Brown .desc = "MWAIT 0x10", 352b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 3530138d8f0SLen Brown .exit_latency = 59, 3540138d8f0SLen Brown .target_residency = 156, 3555fe2e527SRafael J. Wysocki .enter = &intel_idle, 35628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 3570138d8f0SLen Brown { 358de09cdd0SLen Brown .name = "C6", 3590138d8f0SLen Brown .desc = "MWAIT 0x20", 360b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 3610138d8f0SLen Brown .exit_latency = 82, 3620138d8f0SLen Brown .target_residency = 300, 3635fe2e527SRafael J. Wysocki .enter = &intel_idle, 36428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 3650138d8f0SLen Brown { 3660138d8f0SLen Brown .enter = NULL } 3670138d8f0SLen Brown }; 3680138d8f0SLen Brown 3690138d8f0SLen Brown static struct cpuidle_state ivt_cstates_4s[] = { 3700138d8f0SLen Brown { 371de09cdd0SLen Brown .name = "C1", 3720138d8f0SLen Brown .desc = "MWAIT 0x00", 373b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 3740138d8f0SLen Brown .exit_latency = 1, 3750138d8f0SLen Brown .target_residency = 1, 3765fe2e527SRafael J. Wysocki .enter = &intel_idle, 37728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 3780138d8f0SLen Brown { 379de09cdd0SLen Brown .name = "C1E", 3800138d8f0SLen Brown .desc = "MWAIT 0x01", 381b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x01), 3820138d8f0SLen Brown .exit_latency = 10, 3830138d8f0SLen Brown .target_residency = 250, 3845fe2e527SRafael J. Wysocki .enter = &intel_idle, 38528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 3860138d8f0SLen Brown { 387de09cdd0SLen Brown .name = "C3", 3880138d8f0SLen Brown .desc = "MWAIT 0x10", 389b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 3900138d8f0SLen Brown .exit_latency = 59, 3910138d8f0SLen Brown .target_residency = 300, 3925fe2e527SRafael J. Wysocki .enter = &intel_idle, 39328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 3940138d8f0SLen Brown { 395de09cdd0SLen Brown .name = "C6", 3960138d8f0SLen Brown .desc = "MWAIT 0x20", 397b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 3980138d8f0SLen Brown .exit_latency = 84, 3990138d8f0SLen Brown .target_residency = 400, 4005fe2e527SRafael J. Wysocki .enter = &intel_idle, 40128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 4020138d8f0SLen Brown { 4030138d8f0SLen Brown .enter = NULL } 4040138d8f0SLen Brown }; 4050138d8f0SLen Brown 4060138d8f0SLen Brown static struct cpuidle_state ivt_cstates_8s[] = { 4070138d8f0SLen Brown { 408de09cdd0SLen Brown .name = "C1", 4090138d8f0SLen Brown .desc = "MWAIT 0x00", 410b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 4110138d8f0SLen Brown .exit_latency = 1, 4120138d8f0SLen Brown .target_residency = 1, 4135fe2e527SRafael J. Wysocki .enter = &intel_idle, 41428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 4150138d8f0SLen Brown { 416de09cdd0SLen Brown .name = "C1E", 4170138d8f0SLen Brown .desc = "MWAIT 0x01", 418b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x01), 4190138d8f0SLen Brown .exit_latency = 10, 4200138d8f0SLen Brown .target_residency = 500, 4215fe2e527SRafael J. Wysocki .enter = &intel_idle, 42228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 4230138d8f0SLen Brown { 424de09cdd0SLen Brown .name = "C3", 4250138d8f0SLen Brown .desc = "MWAIT 0x10", 426b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 4270138d8f0SLen Brown .exit_latency = 59, 4280138d8f0SLen Brown .target_residency = 600, 4295fe2e527SRafael J. Wysocki .enter = &intel_idle, 43028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 4310138d8f0SLen Brown { 432de09cdd0SLen Brown .name = "C6", 4330138d8f0SLen Brown .desc = "MWAIT 0x20", 434b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 4350138d8f0SLen Brown .exit_latency = 88, 4360138d8f0SLen Brown .target_residency = 700, 4375fe2e527SRafael J. Wysocki .enter = &intel_idle, 43828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 4390138d8f0SLen Brown { 4400138d8f0SLen Brown .enter = NULL } 4410138d8f0SLen Brown }; 4420138d8f0SLen Brown 443ba0dc81eSJiang Liu static struct cpuidle_state hsw_cstates[] = { 444e022e7ebSLen Brown { 445de09cdd0SLen Brown .name = "C1", 44685a4d2d4SLen Brown .desc = "MWAIT 0x00", 447b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 44885a4d2d4SLen Brown .exit_latency = 2, 44985a4d2d4SLen Brown .target_residency = 2, 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", 455b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x01), 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", 46285a4d2d4SLen Brown .desc = "MWAIT 0x10", 463b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 46485a4d2d4SLen Brown .exit_latency = 33, 46585a4d2d4SLen Brown .target_residency = 100, 4665fe2e527SRafael J. Wysocki .enter = &intel_idle, 46728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 468e022e7ebSLen Brown { 469de09cdd0SLen Brown .name = "C6", 47085a4d2d4SLen Brown .desc = "MWAIT 0x20", 471b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 47285a4d2d4SLen Brown .exit_latency = 133, 47385a4d2d4SLen Brown .target_residency = 400, 4745fe2e527SRafael J. Wysocki .enter = &intel_idle, 47528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 476e022e7ebSLen Brown { 477de09cdd0SLen Brown .name = "C7s", 47885a4d2d4SLen Brown .desc = "MWAIT 0x32", 479b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED, 48085a4d2d4SLen Brown .exit_latency = 166, 48185a4d2d4SLen Brown .target_residency = 500, 4825fe2e527SRafael J. Wysocki .enter = &intel_idle, 48328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 484e022e7ebSLen Brown { 485de09cdd0SLen Brown .name = "C8", 48686239cebSLen Brown .desc = "MWAIT 0x40", 487b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 48886239cebSLen Brown .exit_latency = 300, 48986239cebSLen Brown .target_residency = 900, 4905fe2e527SRafael J. Wysocki .enter = &intel_idle, 49128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 49286239cebSLen Brown { 493de09cdd0SLen Brown .name = "C9", 49486239cebSLen Brown .desc = "MWAIT 0x50", 495b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, 49686239cebSLen Brown .exit_latency = 600, 49786239cebSLen Brown .target_residency = 1800, 4985fe2e527SRafael J. Wysocki .enter = &intel_idle, 49928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 50086239cebSLen Brown { 501de09cdd0SLen Brown .name = "C10", 50286239cebSLen Brown .desc = "MWAIT 0x60", 503b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 50486239cebSLen Brown .exit_latency = 2600, 50586239cebSLen Brown .target_residency = 7700, 5065fe2e527SRafael J. Wysocki .enter = &intel_idle, 50728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 50886239cebSLen Brown { 509e022e7ebSLen Brown .enter = NULL } 51085a4d2d4SLen Brown }; 511a138b568SLen Brown static struct cpuidle_state bdw_cstates[] = { 512a138b568SLen Brown { 513de09cdd0SLen Brown .name = "C1", 514a138b568SLen Brown .desc = "MWAIT 0x00", 515b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 516a138b568SLen Brown .exit_latency = 2, 517a138b568SLen Brown .target_residency = 2, 5185fe2e527SRafael J. Wysocki .enter = &intel_idle, 51928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 520a138b568SLen Brown { 521de09cdd0SLen Brown .name = "C1E", 522a138b568SLen Brown .desc = "MWAIT 0x01", 523b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x01), 524a138b568SLen Brown .exit_latency = 10, 525a138b568SLen Brown .target_residency = 20, 5265fe2e527SRafael J. Wysocki .enter = &intel_idle, 52728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 528a138b568SLen Brown { 529de09cdd0SLen Brown .name = "C3", 530a138b568SLen Brown .desc = "MWAIT 0x10", 531b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 532a138b568SLen Brown .exit_latency = 40, 533a138b568SLen Brown .target_residency = 100, 5345fe2e527SRafael J. Wysocki .enter = &intel_idle, 53528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 536a138b568SLen Brown { 537de09cdd0SLen Brown .name = "C6", 538a138b568SLen Brown .desc = "MWAIT 0x20", 539b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 540a138b568SLen Brown .exit_latency = 133, 541a138b568SLen Brown .target_residency = 400, 5425fe2e527SRafael J. Wysocki .enter = &intel_idle, 54328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 544a138b568SLen Brown { 545de09cdd0SLen Brown .name = "C7s", 546a138b568SLen Brown .desc = "MWAIT 0x32", 547b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TLB_FLUSHED, 548a138b568SLen Brown .exit_latency = 166, 549a138b568SLen Brown .target_residency = 500, 5505fe2e527SRafael J. Wysocki .enter = &intel_idle, 55128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 552a138b568SLen Brown { 553de09cdd0SLen Brown .name = "C8", 554a138b568SLen Brown .desc = "MWAIT 0x40", 555b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 556a138b568SLen Brown .exit_latency = 300, 557a138b568SLen Brown .target_residency = 900, 5585fe2e527SRafael J. Wysocki .enter = &intel_idle, 55928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 560a138b568SLen Brown { 561de09cdd0SLen Brown .name = "C9", 562a138b568SLen Brown .desc = "MWAIT 0x50", 563b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, 564a138b568SLen Brown .exit_latency = 600, 565a138b568SLen Brown .target_residency = 1800, 5665fe2e527SRafael J. Wysocki .enter = &intel_idle, 56728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 568a138b568SLen Brown { 569de09cdd0SLen Brown .name = "C10", 570a138b568SLen Brown .desc = "MWAIT 0x60", 571b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 572a138b568SLen Brown .exit_latency = 2600, 573a138b568SLen Brown .target_residency = 7700, 5745fe2e527SRafael J. Wysocki .enter = &intel_idle, 57528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 576a138b568SLen Brown { 577a138b568SLen Brown .enter = NULL } 578a138b568SLen Brown }; 57985a4d2d4SLen Brown 580493f133fSLen Brown static struct cpuidle_state skl_cstates[] = { 581493f133fSLen Brown { 582de09cdd0SLen Brown .name = "C1", 583493f133fSLen Brown .desc = "MWAIT 0x00", 584493f133fSLen Brown .flags = MWAIT2flg(0x00), 585493f133fSLen Brown .exit_latency = 2, 586493f133fSLen Brown .target_residency = 2, 587493f133fSLen Brown .enter = &intel_idle, 58828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 589493f133fSLen Brown { 590de09cdd0SLen Brown .name = "C1E", 591493f133fSLen Brown .desc = "MWAIT 0x01", 592493f133fSLen Brown .flags = MWAIT2flg(0x01), 593493f133fSLen Brown .exit_latency = 10, 594493f133fSLen Brown .target_residency = 20, 595493f133fSLen Brown .enter = &intel_idle, 59628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 597493f133fSLen Brown { 598de09cdd0SLen Brown .name = "C3", 599493f133fSLen Brown .desc = "MWAIT 0x10", 600493f133fSLen Brown .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 601493f133fSLen Brown .exit_latency = 70, 602493f133fSLen Brown .target_residency = 100, 603493f133fSLen Brown .enter = &intel_idle, 60428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 605493f133fSLen Brown { 606de09cdd0SLen Brown .name = "C6", 607493f133fSLen Brown .desc = "MWAIT 0x20", 608493f133fSLen Brown .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 609135919a3SLen Brown .exit_latency = 85, 610493f133fSLen Brown .target_residency = 200, 611493f133fSLen Brown .enter = &intel_idle, 61228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 613493f133fSLen Brown { 614de09cdd0SLen Brown .name = "C7s", 615493f133fSLen Brown .desc = "MWAIT 0x33", 616493f133fSLen Brown .flags = MWAIT2flg(0x33) | CPUIDLE_FLAG_TLB_FLUSHED, 617493f133fSLen Brown .exit_latency = 124, 618493f133fSLen Brown .target_residency = 800, 619493f133fSLen Brown .enter = &intel_idle, 62028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 621493f133fSLen Brown { 622de09cdd0SLen Brown .name = "C8", 623493f133fSLen Brown .desc = "MWAIT 0x40", 624493f133fSLen Brown .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 625135919a3SLen Brown .exit_latency = 200, 626493f133fSLen Brown .target_residency = 800, 627493f133fSLen Brown .enter = &intel_idle, 62828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 629493f133fSLen Brown { 630de09cdd0SLen Brown .name = "C9", 631135919a3SLen Brown .desc = "MWAIT 0x50", 632135919a3SLen Brown .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, 633135919a3SLen Brown .exit_latency = 480, 634135919a3SLen Brown .target_residency = 5000, 635135919a3SLen Brown .enter = &intel_idle, 63628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 637135919a3SLen Brown { 638de09cdd0SLen Brown .name = "C10", 639493f133fSLen Brown .desc = "MWAIT 0x60", 640493f133fSLen Brown .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 641493f133fSLen Brown .exit_latency = 890, 642493f133fSLen Brown .target_residency = 5000, 643493f133fSLen Brown .enter = &intel_idle, 64428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 645493f133fSLen Brown { 646493f133fSLen Brown .enter = NULL } 647493f133fSLen Brown }; 648493f133fSLen Brown 649f9e71657SLen Brown static struct cpuidle_state skx_cstates[] = { 650f9e71657SLen Brown { 651de09cdd0SLen Brown .name = "C1", 652f9e71657SLen Brown .desc = "MWAIT 0x00", 653f9e71657SLen Brown .flags = MWAIT2flg(0x00), 654f9e71657SLen Brown .exit_latency = 2, 655f9e71657SLen Brown .target_residency = 2, 656f9e71657SLen Brown .enter = &intel_idle, 65728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 658f9e71657SLen Brown { 659de09cdd0SLen Brown .name = "C1E", 660f9e71657SLen Brown .desc = "MWAIT 0x01", 661f9e71657SLen Brown .flags = MWAIT2flg(0x01), 662f9e71657SLen Brown .exit_latency = 10, 663f9e71657SLen Brown .target_residency = 20, 664f9e71657SLen Brown .enter = &intel_idle, 66528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 666f9e71657SLen Brown { 667de09cdd0SLen Brown .name = "C6", 668f9e71657SLen Brown .desc = "MWAIT 0x20", 669f9e71657SLen Brown .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 670f9e71657SLen Brown .exit_latency = 133, 671f9e71657SLen Brown .target_residency = 600, 672f9e71657SLen Brown .enter = &intel_idle, 67328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 674f9e71657SLen Brown { 675f9e71657SLen Brown .enter = NULL } 676f9e71657SLen Brown }; 677f9e71657SLen Brown 678ba0dc81eSJiang Liu static struct cpuidle_state atom_cstates[] = { 679e022e7ebSLen Brown { 680de09cdd0SLen Brown .name = "C1E", 68126717172SLen Brown .desc = "MWAIT 0x00", 682b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 68332e95180SLen Brown .exit_latency = 10, 68432e95180SLen Brown .target_residency = 20, 6855fe2e527SRafael J. Wysocki .enter = &intel_idle, 68628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 687e022e7ebSLen Brown { 688de09cdd0SLen Brown .name = "C2", 68926717172SLen Brown .desc = "MWAIT 0x10", 690b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x10), 69126717172SLen Brown .exit_latency = 20, 69226717172SLen Brown .target_residency = 80, 6935fe2e527SRafael J. Wysocki .enter = &intel_idle, 69428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 695e022e7ebSLen Brown { 696de09cdd0SLen Brown .name = "C4", 69726717172SLen Brown .desc = "MWAIT 0x30", 698b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 69926717172SLen Brown .exit_latency = 100, 70026717172SLen Brown .target_residency = 400, 7015fe2e527SRafael J. Wysocki .enter = &intel_idle, 70228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 703e022e7ebSLen Brown { 704de09cdd0SLen Brown .name = "C6", 7057fcca7d9SLen Brown .desc = "MWAIT 0x52", 706b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 7077fcca7d9SLen Brown .exit_latency = 140, 7087fcca7d9SLen Brown .target_residency = 560, 7095fe2e527SRafael J. Wysocki .enter = &intel_idle, 71028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 711e022e7ebSLen Brown { 712e022e7ebSLen Brown .enter = NULL } 71326717172SLen Brown }; 7145e7ec268SAndy Shevchenko static struct cpuidle_state tangier_cstates[] = { 7155e7ec268SAndy Shevchenko { 716de09cdd0SLen Brown .name = "C1", 7175e7ec268SAndy Shevchenko .desc = "MWAIT 0x00", 7185e7ec268SAndy Shevchenko .flags = MWAIT2flg(0x00), 7195e7ec268SAndy Shevchenko .exit_latency = 1, 7205e7ec268SAndy Shevchenko .target_residency = 4, 7215e7ec268SAndy Shevchenko .enter = &intel_idle, 72228ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 7235e7ec268SAndy Shevchenko { 724de09cdd0SLen Brown .name = "C4", 7255e7ec268SAndy Shevchenko .desc = "MWAIT 0x30", 7265e7ec268SAndy Shevchenko .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED, 7275e7ec268SAndy Shevchenko .exit_latency = 100, 7285e7ec268SAndy Shevchenko .target_residency = 400, 7295e7ec268SAndy Shevchenko .enter = &intel_idle, 73028ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 7315e7ec268SAndy Shevchenko { 732de09cdd0SLen Brown .name = "C6", 7335e7ec268SAndy Shevchenko .desc = "MWAIT 0x52", 7345e7ec268SAndy Shevchenko .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED, 7355e7ec268SAndy Shevchenko .exit_latency = 140, 7365e7ec268SAndy Shevchenko .target_residency = 560, 7375e7ec268SAndy Shevchenko .enter = &intel_idle, 73828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 7395e7ec268SAndy Shevchenko { 740de09cdd0SLen Brown .name = "C7", 7415e7ec268SAndy Shevchenko .desc = "MWAIT 0x60", 7425e7ec268SAndy Shevchenko .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 7435e7ec268SAndy Shevchenko .exit_latency = 1200, 7445e7ec268SAndy Shevchenko .target_residency = 4000, 7455e7ec268SAndy Shevchenko .enter = &intel_idle, 74628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 7475e7ec268SAndy Shevchenko { 748de09cdd0SLen Brown .name = "C9", 7495e7ec268SAndy Shevchenko .desc = "MWAIT 0x64", 7505e7ec268SAndy Shevchenko .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED, 7515e7ec268SAndy Shevchenko .exit_latency = 10000, 7525e7ec268SAndy Shevchenko .target_residency = 20000, 7535e7ec268SAndy Shevchenko .enter = &intel_idle, 75428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 7555e7ec268SAndy Shevchenko { 7565e7ec268SAndy Shevchenko .enter = NULL } 7575e7ec268SAndy Shevchenko }; 75888390996SJiang Liu static struct cpuidle_state avn_cstates[] = { 759fab04b22SLen Brown { 760de09cdd0SLen Brown .name = "C1", 761fab04b22SLen Brown .desc = "MWAIT 0x00", 762b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x00), 763fab04b22SLen Brown .exit_latency = 2, 764fab04b22SLen Brown .target_residency = 2, 7655fe2e527SRafael J. Wysocki .enter = &intel_idle, 76628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 767fab04b22SLen Brown { 768de09cdd0SLen Brown .name = "C6", 769fab04b22SLen Brown .desc = "MWAIT 0x51", 770b82b6ccaSDaniel Lezcano .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TLB_FLUSHED, 771fab04b22SLen Brown .exit_latency = 15, 772fab04b22SLen Brown .target_residency = 45, 7735fe2e527SRafael J. Wysocki .enter = &intel_idle, 77428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 77588390996SJiang Liu { 77688390996SJiang Liu .enter = NULL } 777fab04b22SLen Brown }; 778281baf7aSDasaratharaman Chandramouli static struct cpuidle_state knl_cstates[] = { 779281baf7aSDasaratharaman Chandramouli { 780de09cdd0SLen Brown .name = "C1", 781281baf7aSDasaratharaman Chandramouli .desc = "MWAIT 0x00", 782281baf7aSDasaratharaman Chandramouli .flags = MWAIT2flg(0x00), 783281baf7aSDasaratharaman Chandramouli .exit_latency = 1, 784281baf7aSDasaratharaman Chandramouli .target_residency = 2, 785281baf7aSDasaratharaman Chandramouli .enter = &intel_idle, 78628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle }, 787281baf7aSDasaratharaman Chandramouli { 788de09cdd0SLen Brown .name = "C6", 789281baf7aSDasaratharaman Chandramouli .desc = "MWAIT 0x10", 790281baf7aSDasaratharaman Chandramouli .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, 791281baf7aSDasaratharaman Chandramouli .exit_latency = 120, 792281baf7aSDasaratharaman Chandramouli .target_residency = 500, 793281baf7aSDasaratharaman Chandramouli .enter = &intel_idle, 79428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle }, 795281baf7aSDasaratharaman Chandramouli { 796281baf7aSDasaratharaman Chandramouli .enter = NULL } 797281baf7aSDasaratharaman Chandramouli }; 79826717172SLen Brown 7995dcef694SLen Brown static struct cpuidle_state bxt_cstates[] = { 8005dcef694SLen Brown { 801de09cdd0SLen Brown .name = "C1", 8025dcef694SLen Brown .desc = "MWAIT 0x00", 8035dcef694SLen Brown .flags = MWAIT2flg(0x00), 8045dcef694SLen Brown .exit_latency = 2, 8055dcef694SLen Brown .target_residency = 2, 8065dcef694SLen Brown .enter = &intel_idle, 80728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 8085dcef694SLen Brown { 809de09cdd0SLen Brown .name = "C1E", 8105dcef694SLen Brown .desc = "MWAIT 0x01", 8115dcef694SLen Brown .flags = MWAIT2flg(0x01), 8125dcef694SLen Brown .exit_latency = 10, 8135dcef694SLen Brown .target_residency = 20, 8145dcef694SLen Brown .enter = &intel_idle, 81528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 8165dcef694SLen Brown { 817de09cdd0SLen Brown .name = "C6", 8185dcef694SLen Brown .desc = "MWAIT 0x20", 8195dcef694SLen Brown .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 8205dcef694SLen Brown .exit_latency = 133, 8215dcef694SLen Brown .target_residency = 133, 8225dcef694SLen Brown .enter = &intel_idle, 82328ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 8245dcef694SLen Brown { 825de09cdd0SLen Brown .name = "C7s", 8265dcef694SLen Brown .desc = "MWAIT 0x31", 8275dcef694SLen Brown .flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED, 8285dcef694SLen Brown .exit_latency = 155, 8295dcef694SLen Brown .target_residency = 155, 8305dcef694SLen Brown .enter = &intel_idle, 83128ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 8325dcef694SLen Brown { 833de09cdd0SLen Brown .name = "C8", 8345dcef694SLen Brown .desc = "MWAIT 0x40", 8355dcef694SLen Brown .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED, 8365dcef694SLen Brown .exit_latency = 1000, 8375dcef694SLen Brown .target_residency = 1000, 8385dcef694SLen Brown .enter = &intel_idle, 83928ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 8405dcef694SLen Brown { 841de09cdd0SLen Brown .name = "C9", 8425dcef694SLen Brown .desc = "MWAIT 0x50", 8435dcef694SLen Brown .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED, 8445dcef694SLen Brown .exit_latency = 2000, 8455dcef694SLen Brown .target_residency = 2000, 8465dcef694SLen Brown .enter = &intel_idle, 84728ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 8485dcef694SLen Brown { 849de09cdd0SLen Brown .name = "C10", 8505dcef694SLen Brown .desc = "MWAIT 0x60", 8515dcef694SLen Brown .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED, 8525dcef694SLen Brown .exit_latency = 10000, 8535dcef694SLen Brown .target_residency = 10000, 8545dcef694SLen Brown .enter = &intel_idle, 85528ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 8565dcef694SLen Brown { 8575dcef694SLen Brown .enter = NULL } 8585dcef694SLen Brown }; 8595dcef694SLen Brown 8600080d65bSJacob Pan static struct cpuidle_state dnv_cstates[] = { 8610080d65bSJacob Pan { 862de09cdd0SLen Brown .name = "C1", 8630080d65bSJacob Pan .desc = "MWAIT 0x00", 8640080d65bSJacob Pan .flags = MWAIT2flg(0x00), 8650080d65bSJacob Pan .exit_latency = 2, 8660080d65bSJacob Pan .target_residency = 2, 8670080d65bSJacob Pan .enter = &intel_idle, 86828ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 8690080d65bSJacob Pan { 870de09cdd0SLen Brown .name = "C1E", 8710080d65bSJacob Pan .desc = "MWAIT 0x01", 8720080d65bSJacob Pan .flags = MWAIT2flg(0x01), 8730080d65bSJacob Pan .exit_latency = 10, 8740080d65bSJacob Pan .target_residency = 20, 8750080d65bSJacob Pan .enter = &intel_idle, 87628ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 8770080d65bSJacob Pan { 878de09cdd0SLen Brown .name = "C6", 8790080d65bSJacob Pan .desc = "MWAIT 0x20", 8800080d65bSJacob Pan .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED, 8810080d65bSJacob Pan .exit_latency = 50, 8820080d65bSJacob Pan .target_residency = 500, 8830080d65bSJacob Pan .enter = &intel_idle, 88428ba086eSRafael J. Wysocki .enter_s2idle = intel_idle_s2idle, }, 8850080d65bSJacob Pan { 8860080d65bSJacob Pan .enter = NULL } 8870080d65bSJacob Pan }; 8880080d65bSJacob Pan 88926717172SLen Brown /** 89026717172SLen Brown * intel_idle 89126717172SLen Brown * @dev: cpuidle_device 89246bcfad7SDeepthi Dharwar * @drv: cpuidle driver 893e978aa7dSDeepthi Dharwar * @index: index of cpuidle state 89426717172SLen Brown * 89563ff07beSYanmin Zhang * Must be called under local_irq_disable(). 89626717172SLen Brown */ 8976727ad9eSChris Metcalf static __cpuidle int intel_idle(struct cpuidle_device *dev, 89846bcfad7SDeepthi Dharwar struct cpuidle_driver *drv, int index) 89926717172SLen Brown { 90026717172SLen Brown unsigned long ecx = 1; /* break on interrupt flag */ 90146bcfad7SDeepthi Dharwar struct cpuidle_state *state = &drv->states[index]; 902b1beab48SLen Brown unsigned long eax = flg2MWAIT(state->flags); 90326717172SLen Brown unsigned int cstate; 9040563bb7bSJason Baron bool uninitialized_var(tick); 90567535736SAndy Lutomirski int cpu = smp_processor_id(); 90626717172SLen Brown 9076110a1f4SSuresh Siddha /* 90867535736SAndy Lutomirski * leave_mm() to avoid costly and often unnecessary wakeups 90967535736SAndy Lutomirski * for flushing the user TLB's associated with the active mm. 9106110a1f4SSuresh Siddha */ 91167535736SAndy Lutomirski if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED) 91267535736SAndy Lutomirski leave_mm(cpu); 9136110a1f4SSuresh Siddha 9140563bb7bSJason Baron if (!static_cpu_has(X86_FEATURE_ARAT)) { 9150563bb7bSJason Baron cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & 9160563bb7bSJason Baron MWAIT_CSTATE_MASK) + 1; 9170563bb7bSJason Baron tick = false; 9180563bb7bSJason Baron if (!(lapic_timer_reliable_states & (1 << (cstate)))) { 9190563bb7bSJason Baron tick = true; 920f6cee191SThomas Gleixner tick_broadcast_enter(); 9210563bb7bSJason Baron } 9220563bb7bSJason Baron } 92326717172SLen Brown 92416824255SPeter Zijlstra mwait_idle_with_hints(eax, ecx); 92526717172SLen Brown 9260563bb7bSJason Baron if (!static_cpu_has(X86_FEATURE_ARAT) && tick) 927f6cee191SThomas Gleixner tick_broadcast_exit(); 92826717172SLen Brown 929e978aa7dSDeepthi Dharwar return index; 93026717172SLen Brown } 93126717172SLen Brown 9325fe2e527SRafael J. Wysocki /** 93328ba086eSRafael J. Wysocki * intel_idle_s2idle - simplified "enter" callback routine for suspend-to-idle 9345fe2e527SRafael J. Wysocki * @dev: cpuidle_device 9355fe2e527SRafael J. Wysocki * @drv: cpuidle driver 9365fe2e527SRafael J. Wysocki * @index: state index 9375fe2e527SRafael J. Wysocki */ 93828ba086eSRafael J. Wysocki static void intel_idle_s2idle(struct cpuidle_device *dev, 9395fe2e527SRafael J. Wysocki struct cpuidle_driver *drv, int index) 9405fe2e527SRafael J. Wysocki { 9415fe2e527SRafael J. Wysocki unsigned long ecx = 1; /* break on interrupt flag */ 9425fe2e527SRafael J. Wysocki unsigned long eax = flg2MWAIT(drv->states[index].flags); 9435fe2e527SRafael J. Wysocki 9445fe2e527SRafael J. Wysocki mwait_idle_with_hints(eax, ecx); 9455fe2e527SRafael J. Wysocki } 9465fe2e527SRafael J. Wysocki 947fb1013a0SSebastian Andrzej Siewior static void __setup_broadcast_timer(bool on) 9482a2d31c8SShaohua Li { 94976962caaSThomas Gleixner if (on) 95076962caaSThomas Gleixner tick_broadcast_enable(); 95176962caaSThomas Gleixner else 95276962caaSThomas Gleixner tick_broadcast_disable(); 9532a2d31c8SShaohua Li } 9542a2d31c8SShaohua Li 955fb1013a0SSebastian Andrzej Siewior static void auto_demotion_disable(void) 95614796fcaSLen Brown { 95714796fcaSLen Brown unsigned long long msr_bits; 95814796fcaSLen Brown 9596cfb2374SLen Brown rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits); 960b66b8b9aSAndi Kleen msr_bits &= ~(icpu->auto_demotion_disable_flags); 9616cfb2374SLen Brown wrmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr_bits); 96214796fcaSLen Brown } 963fb1013a0SSebastian Andrzej Siewior static void c1e_promotion_disable(void) 96432e95180SLen Brown { 96532e95180SLen Brown unsigned long long msr_bits; 96632e95180SLen Brown 96732e95180SLen Brown rdmsrl(MSR_IA32_POWER_CTL, msr_bits); 96832e95180SLen Brown msr_bits &= ~0x2; 96932e95180SLen Brown wrmsrl(MSR_IA32_POWER_CTL, msr_bits); 97032e95180SLen Brown } 97114796fcaSLen Brown 972b66b8b9aSAndi Kleen static const struct idle_cpu idle_cpu_nehalem = { 973b66b8b9aSAndi Kleen .state_table = nehalem_cstates, 974b66b8b9aSAndi Kleen .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, 97532e95180SLen Brown .disable_promotion_to_c1e = true, 976b66b8b9aSAndi Kleen }; 977b66b8b9aSAndi Kleen 978b66b8b9aSAndi Kleen static const struct idle_cpu idle_cpu_atom = { 979b66b8b9aSAndi Kleen .state_table = atom_cstates, 980b66b8b9aSAndi Kleen }; 981b66b8b9aSAndi Kleen 9825e7ec268SAndy Shevchenko static const struct idle_cpu idle_cpu_tangier = { 9835e7ec268SAndy Shevchenko .state_table = tangier_cstates, 9845e7ec268SAndy Shevchenko }; 9855e7ec268SAndy Shevchenko 986b66b8b9aSAndi Kleen static const struct idle_cpu idle_cpu_lincroft = { 987b66b8b9aSAndi Kleen .state_table = atom_cstates, 988b66b8b9aSAndi Kleen .auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE, 989b66b8b9aSAndi Kleen }; 990b66b8b9aSAndi Kleen 991b66b8b9aSAndi Kleen static const struct idle_cpu idle_cpu_snb = { 992b66b8b9aSAndi Kleen .state_table = snb_cstates, 99332e95180SLen Brown .disable_promotion_to_c1e = true, 994b66b8b9aSAndi Kleen }; 995b66b8b9aSAndi Kleen 996718987d6SLen Brown static const struct idle_cpu idle_cpu_byt = { 997718987d6SLen Brown .state_table = byt_cstates, 998718987d6SLen Brown .disable_promotion_to_c1e = true, 9998c058d53SLen Brown .byt_auto_demotion_disable_flag = true, 1000718987d6SLen Brown }; 1001718987d6SLen Brown 1002cab07a56SLen Brown static const struct idle_cpu idle_cpu_cht = { 1003cab07a56SLen Brown .state_table = cht_cstates, 1004cab07a56SLen Brown .disable_promotion_to_c1e = true, 1005cab07a56SLen Brown .byt_auto_demotion_disable_flag = true, 1006cab07a56SLen Brown }; 1007cab07a56SLen Brown 10086edab08cSLen Brown static const struct idle_cpu idle_cpu_ivb = { 10096edab08cSLen Brown .state_table = ivb_cstates, 101032e95180SLen Brown .disable_promotion_to_c1e = true, 10116edab08cSLen Brown }; 10126edab08cSLen Brown 10130138d8f0SLen Brown static const struct idle_cpu idle_cpu_ivt = { 10140138d8f0SLen Brown .state_table = ivt_cstates, 10150138d8f0SLen Brown .disable_promotion_to_c1e = true, 10160138d8f0SLen Brown }; 10170138d8f0SLen Brown 101885a4d2d4SLen Brown static const struct idle_cpu idle_cpu_hsw = { 101985a4d2d4SLen Brown .state_table = hsw_cstates, 102032e95180SLen Brown .disable_promotion_to_c1e = true, 102185a4d2d4SLen Brown }; 102285a4d2d4SLen Brown 1023a138b568SLen Brown static const struct idle_cpu idle_cpu_bdw = { 1024a138b568SLen Brown .state_table = bdw_cstates, 1025a138b568SLen Brown .disable_promotion_to_c1e = true, 1026a138b568SLen Brown }; 1027a138b568SLen Brown 1028493f133fSLen Brown static const struct idle_cpu idle_cpu_skl = { 1029493f133fSLen Brown .state_table = skl_cstates, 1030493f133fSLen Brown .disable_promotion_to_c1e = true, 1031493f133fSLen Brown }; 1032493f133fSLen Brown 1033f9e71657SLen Brown static const struct idle_cpu idle_cpu_skx = { 1034f9e71657SLen Brown .state_table = skx_cstates, 1035f9e71657SLen Brown .disable_promotion_to_c1e = true, 1036f9e71657SLen Brown }; 1037493f133fSLen Brown 1038fab04b22SLen Brown static const struct idle_cpu idle_cpu_avn = { 1039fab04b22SLen Brown .state_table = avn_cstates, 1040fab04b22SLen Brown .disable_promotion_to_c1e = true, 1041fab04b22SLen Brown }; 1042fab04b22SLen Brown 1043281baf7aSDasaratharaman Chandramouli static const struct idle_cpu idle_cpu_knl = { 1044281baf7aSDasaratharaman Chandramouli .state_table = knl_cstates, 1045281baf7aSDasaratharaman Chandramouli }; 1046281baf7aSDasaratharaman Chandramouli 10475dcef694SLen Brown static const struct idle_cpu idle_cpu_bxt = { 10485dcef694SLen Brown .state_table = bxt_cstates, 10495dcef694SLen Brown .disable_promotion_to_c1e = true, 10505dcef694SLen Brown }; 10515dcef694SLen Brown 10520080d65bSJacob Pan static const struct idle_cpu idle_cpu_dnv = { 10530080d65bSJacob Pan .state_table = dnv_cstates, 10540080d65bSJacob Pan .disable_promotion_to_c1e = true, 10550080d65bSJacob Pan }; 10560080d65bSJacob Pan 1057d5cdc3c4SMathias Krause static const struct x86_cpu_id intel_idle_ids[] __initconst = { 1058a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(NEHALEM_EP, idle_cpu_nehalem), 1059a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(NEHALEM, idle_cpu_nehalem), 1060a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(NEHALEM_G, idle_cpu_nehalem), 1061a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(WESTMERE, idle_cpu_nehalem), 1062a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(WESTMERE_EP, idle_cpu_nehalem), 1063a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(NEHALEM_EX, idle_cpu_nehalem), 1064c05f3642SLinus Torvalds INTEL_CPU_FAM6(ATOM_BONNELL, idle_cpu_atom), 1065c05f3642SLinus Torvalds INTEL_CPU_FAM6(ATOM_BONNELL_MID, idle_cpu_lincroft), 1066a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(WESTMERE_EX, idle_cpu_nehalem), 1067a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(SANDYBRIDGE, idle_cpu_snb), 1068a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(SANDYBRIDGE_X, idle_cpu_snb), 1069c05f3642SLinus Torvalds INTEL_CPU_FAM6(ATOM_SALTWELL, idle_cpu_atom), 1070c05f3642SLinus Torvalds INTEL_CPU_FAM6(ATOM_SILVERMONT, idle_cpu_byt), 1071c05f3642SLinus Torvalds INTEL_CPU_FAM6(ATOM_SILVERMONT_MID, idle_cpu_tangier), 1072a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(ATOM_AIRMONT, idle_cpu_cht), 1073a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(IVYBRIDGE, idle_cpu_ivb), 1074a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(IVYBRIDGE_X, idle_cpu_ivt), 1075c66f78a6SPeter Zijlstra INTEL_CPU_FAM6(HASWELL, idle_cpu_hsw), 1076a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(HASWELL_X, idle_cpu_hsw), 1077af239c44SPeter Zijlstra INTEL_CPU_FAM6(HASWELL_L, idle_cpu_hsw), 10785e741407SPeter Zijlstra INTEL_CPU_FAM6(HASWELL_G, idle_cpu_hsw), 10795ebb34edSPeter Zijlstra INTEL_CPU_FAM6(ATOM_SILVERMONT_D, idle_cpu_avn), 1080c66f78a6SPeter Zijlstra INTEL_CPU_FAM6(BROADWELL, idle_cpu_bdw), 10815e741407SPeter Zijlstra INTEL_CPU_FAM6(BROADWELL_G, idle_cpu_bdw), 1082a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(BROADWELL_X, idle_cpu_bdw), 10835ebb34edSPeter Zijlstra INTEL_CPU_FAM6(BROADWELL_D, idle_cpu_bdw), 1084af239c44SPeter Zijlstra INTEL_CPU_FAM6(SKYLAKE_L, idle_cpu_skl), 1085c66f78a6SPeter Zijlstra INTEL_CPU_FAM6(SKYLAKE, idle_cpu_skl), 1086af239c44SPeter Zijlstra INTEL_CPU_FAM6(KABYLAKE_L, idle_cpu_skl), 1087c66f78a6SPeter Zijlstra INTEL_CPU_FAM6(KABYLAKE, idle_cpu_skl), 1088a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(SKYLAKE_X, idle_cpu_skx), 1089a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(XEON_PHI_KNL, idle_cpu_knl), 1090a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(XEON_PHI_KNM, idle_cpu_knl), 1091a4a008e5SAndy Shevchenko INTEL_CPU_FAM6(ATOM_GOLDMONT, idle_cpu_bxt), 1092c05f3642SLinus Torvalds INTEL_CPU_FAM6(ATOM_GOLDMONT_PLUS, idle_cpu_bxt), 10935ebb34edSPeter Zijlstra INTEL_CPU_FAM6(ATOM_GOLDMONT_D, idle_cpu_dnv), 10945ebb34edSPeter Zijlstra INTEL_CPU_FAM6(ATOM_TREMONT_D, idle_cpu_dnv), 1095b66b8b9aSAndi Kleen {} 1096b66b8b9aSAndi Kleen }; 1097b66b8b9aSAndi Kleen 109826717172SLen Brown /* 109926717172SLen Brown * intel_idle_probe() 110026717172SLen Brown */ 110100f3e755SBartlomiej Zolnierkiewicz static int __init intel_idle_probe(void) 110226717172SLen Brown { 1103c4236282SLen Brown unsigned int eax, ebx, ecx; 1104b66b8b9aSAndi Kleen const struct x86_cpu_id *id; 110526717172SLen Brown 110626717172SLen Brown if (max_cstate == 0) { 1107654d08a4SJoe Perches pr_debug("disabled\n"); 110826717172SLen Brown return -EPERM; 110926717172SLen Brown } 111026717172SLen Brown 1111b66b8b9aSAndi Kleen id = x86_match_cpu(intel_idle_ids); 1112b66b8b9aSAndi Kleen if (!id) { 1113b66b8b9aSAndi Kleen if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && 1114b66b8b9aSAndi Kleen boot_cpu_data.x86 == 6) 1115654d08a4SJoe Perches pr_debug("does not run on family %d model %d\n", 1116b66b8b9aSAndi Kleen boot_cpu_data.x86, boot_cpu_data.x86_model); 111726717172SLen Brown return -ENODEV; 1118b66b8b9aSAndi Kleen } 111926717172SLen Brown 1120a4c44753SLen Brown if (!boot_cpu_has(X86_FEATURE_MWAIT)) { 1121a4c44753SLen Brown pr_debug("Please enable MWAIT in BIOS SETUP\n"); 1122a4c44753SLen Brown return -ENODEV; 1123a4c44753SLen Brown } 1124a4c44753SLen Brown 112526717172SLen Brown if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) 112626717172SLen Brown return -ENODEV; 112726717172SLen Brown 1128c4236282SLen Brown cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates); 112926717172SLen Brown 113026717172SLen Brown if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) || 11315c2a9f06SThomas Renninger !(ecx & CPUID5_ECX_INTERRUPT_BREAK) || 11325c2a9f06SThomas Renninger !mwait_substates) 113326717172SLen Brown return -ENODEV; 113426717172SLen Brown 1135654d08a4SJoe Perches pr_debug("MWAIT substates: 0x%x\n", mwait_substates); 113626717172SLen Brown 1137b66b8b9aSAndi Kleen icpu = (const struct idle_cpu *)id->driver_data; 1138b66b8b9aSAndi Kleen cpuidle_state_table = icpu->state_table; 113926717172SLen Brown 1140654d08a4SJoe Perches pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n", 1141654d08a4SJoe Perches boot_cpu_data.x86_model); 114226717172SLen Brown 114326717172SLen Brown return 0; 114426717172SLen Brown } 114526717172SLen Brown 114626717172SLen Brown /* 114726717172SLen Brown * intel_idle_cpuidle_devices_uninit() 1148ca42489dSRichard Cochran * Unregisters the cpuidle devices. 114926717172SLen Brown */ 115026717172SLen Brown static void intel_idle_cpuidle_devices_uninit(void) 115126717172SLen Brown { 115226717172SLen Brown int i; 115326717172SLen Brown struct cpuidle_device *dev; 115426717172SLen Brown 115526717172SLen Brown for_each_online_cpu(i) { 115626717172SLen Brown dev = per_cpu_ptr(intel_idle_cpuidle_devices, i); 115726717172SLen Brown cpuidle_unregister_device(dev); 115826717172SLen Brown } 115926717172SLen Brown } 11600138d8f0SLen Brown 11610138d8f0SLen Brown /* 1162d70e28f5SLen Brown * ivt_idle_state_table_update(void) 11630138d8f0SLen Brown * 1164d70e28f5SLen Brown * Tune IVT multi-socket targets 11650138d8f0SLen Brown * Assumption: num_sockets == (max_package_num + 1) 11660138d8f0SLen Brown */ 1167d70e28f5SLen Brown static void ivt_idle_state_table_update(void) 11680138d8f0SLen Brown { 11690138d8f0SLen Brown /* IVT uses a different table for 1-2, 3-4, and > 4 sockets */ 11700138d8f0SLen Brown int cpu, package_num, num_sockets = 1; 11710138d8f0SLen Brown 11720138d8f0SLen Brown for_each_online_cpu(cpu) { 11730138d8f0SLen Brown package_num = topology_physical_package_id(cpu); 11740138d8f0SLen Brown if (package_num + 1 > num_sockets) { 11750138d8f0SLen Brown num_sockets = package_num + 1; 11760138d8f0SLen Brown 1177d27dca42SChristoph Jaeger if (num_sockets > 4) { 11780138d8f0SLen Brown cpuidle_state_table = ivt_cstates_8s; 11790138d8f0SLen Brown return; 11800138d8f0SLen Brown } 11810138d8f0SLen Brown } 1182d27dca42SChristoph Jaeger } 11830138d8f0SLen Brown 11840138d8f0SLen Brown if (num_sockets > 2) 11850138d8f0SLen Brown cpuidle_state_table = ivt_cstates_4s; 1186d70e28f5SLen Brown 11870138d8f0SLen Brown /* else, 1 and 2 socket systems use default ivt_cstates */ 11880138d8f0SLen Brown } 11895dcef694SLen Brown 11905dcef694SLen Brown /* 11915dcef694SLen Brown * Translate IRTL (Interrupt Response Time Limit) MSR to usec 11925dcef694SLen Brown */ 11935dcef694SLen Brown 11945dcef694SLen Brown static unsigned int irtl_ns_units[] = { 11955dcef694SLen Brown 1, 32, 1024, 32768, 1048576, 33554432, 0, 0 }; 11965dcef694SLen Brown 11975dcef694SLen Brown static unsigned long long irtl_2_usec(unsigned long long irtl) 11985dcef694SLen Brown { 11995dcef694SLen Brown unsigned long long ns; 12005dcef694SLen Brown 12013451ab3eSJan Beulich if (!irtl) 12023451ab3eSJan Beulich return 0; 12033451ab3eSJan Beulich 1204bef45096SJan Beulich ns = irtl_ns_units[(irtl >> 10) & 0x7]; 12055dcef694SLen Brown 12065dcef694SLen Brown return div64_u64((irtl & 0x3FF) * ns, 1000); 12075dcef694SLen Brown } 12085dcef694SLen Brown /* 12095dcef694SLen Brown * bxt_idle_state_table_update(void) 12105dcef694SLen Brown * 12115dcef694SLen Brown * On BXT, we trust the IRTL to show the definitive maximum latency 12125dcef694SLen Brown * We use the same value for target_residency. 12135dcef694SLen Brown */ 12145dcef694SLen Brown static void bxt_idle_state_table_update(void) 12155dcef694SLen Brown { 12165dcef694SLen Brown unsigned long long msr; 12173451ab3eSJan Beulich unsigned int usec; 12185dcef694SLen Brown 12195dcef694SLen Brown rdmsrl(MSR_PKGC6_IRTL, msr); 12203451ab3eSJan Beulich usec = irtl_2_usec(msr); 12213451ab3eSJan Beulich if (usec) { 12225dcef694SLen Brown bxt_cstates[2].exit_latency = usec; 12235dcef694SLen Brown bxt_cstates[2].target_residency = usec; 12245dcef694SLen Brown } 12255dcef694SLen Brown 12265dcef694SLen Brown rdmsrl(MSR_PKGC7_IRTL, msr); 12273451ab3eSJan Beulich usec = irtl_2_usec(msr); 12283451ab3eSJan Beulich if (usec) { 12295dcef694SLen Brown bxt_cstates[3].exit_latency = usec; 12305dcef694SLen Brown bxt_cstates[3].target_residency = usec; 12315dcef694SLen Brown } 12325dcef694SLen Brown 12335dcef694SLen Brown rdmsrl(MSR_PKGC8_IRTL, msr); 12343451ab3eSJan Beulich usec = irtl_2_usec(msr); 12353451ab3eSJan Beulich if (usec) { 12365dcef694SLen Brown bxt_cstates[4].exit_latency = usec; 12375dcef694SLen Brown bxt_cstates[4].target_residency = usec; 12385dcef694SLen Brown } 12395dcef694SLen Brown 12405dcef694SLen Brown rdmsrl(MSR_PKGC9_IRTL, msr); 12413451ab3eSJan Beulich usec = irtl_2_usec(msr); 12423451ab3eSJan Beulich if (usec) { 12435dcef694SLen Brown bxt_cstates[5].exit_latency = usec; 12445dcef694SLen Brown bxt_cstates[5].target_residency = usec; 12455dcef694SLen Brown } 12465dcef694SLen Brown 12475dcef694SLen Brown rdmsrl(MSR_PKGC10_IRTL, msr); 12483451ab3eSJan Beulich usec = irtl_2_usec(msr); 12493451ab3eSJan Beulich if (usec) { 12505dcef694SLen Brown bxt_cstates[6].exit_latency = usec; 12515dcef694SLen Brown bxt_cstates[6].target_residency = usec; 12525dcef694SLen Brown } 12535dcef694SLen Brown 12545dcef694SLen Brown } 1255d70e28f5SLen Brown /* 1256d70e28f5SLen Brown * sklh_idle_state_table_update(void) 1257d70e28f5SLen Brown * 1258d70e28f5SLen Brown * On SKL-H (model 0x5e) disable C8 and C9 if: 1259d70e28f5SLen Brown * C10 is enabled and SGX disabled 1260d70e28f5SLen Brown */ 1261d70e28f5SLen Brown static void sklh_idle_state_table_update(void) 1262d70e28f5SLen Brown { 1263d70e28f5SLen Brown unsigned long long msr; 1264d70e28f5SLen Brown unsigned int eax, ebx, ecx, edx; 1265d70e28f5SLen Brown 1266d70e28f5SLen Brown 1267d70e28f5SLen Brown /* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */ 1268d70e28f5SLen Brown if (max_cstate <= 7) 12690138d8f0SLen Brown return; 1270d70e28f5SLen Brown 1271d70e28f5SLen Brown /* if PC10 not present in CPUID.MWAIT.EDX */ 1272d70e28f5SLen Brown if ((mwait_substates & (0xF << 28)) == 0) 1273d70e28f5SLen Brown return; 1274d70e28f5SLen Brown 12756cfb2374SLen Brown rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, msr); 1276d70e28f5SLen Brown 1277d70e28f5SLen Brown /* PC10 is not enabled in PKG C-state limit */ 1278d70e28f5SLen Brown if ((msr & 0xF) != 8) 1279d70e28f5SLen Brown return; 1280d70e28f5SLen Brown 1281d70e28f5SLen Brown ecx = 0; 1282d70e28f5SLen Brown cpuid(7, &eax, &ebx, &ecx, &edx); 1283d70e28f5SLen Brown 1284d70e28f5SLen Brown /* if SGX is present */ 1285d70e28f5SLen Brown if (ebx & (1 << 2)) { 1286d70e28f5SLen Brown 1287d70e28f5SLen Brown rdmsrl(MSR_IA32_FEATURE_CONTROL, msr); 1288d70e28f5SLen Brown 1289d70e28f5SLen Brown /* if SGX is enabled */ 1290d70e28f5SLen Brown if (msr & (1 << 18)) 1291d70e28f5SLen Brown return; 1292d70e28f5SLen Brown } 1293d70e28f5SLen Brown 1294d70e28f5SLen Brown skl_cstates[5].disabled = 1; /* C8-SKL */ 1295d70e28f5SLen Brown skl_cstates[6].disabled = 1; /* C9-SKL */ 1296d70e28f5SLen Brown } 1297d70e28f5SLen Brown /* 1298d70e28f5SLen Brown * intel_idle_state_table_update() 1299d70e28f5SLen Brown * 1300d70e28f5SLen Brown * Update the default state_table for this CPU-id 1301d70e28f5SLen Brown */ 1302d70e28f5SLen Brown 1303d70e28f5SLen Brown static void intel_idle_state_table_update(void) 1304d70e28f5SLen Brown { 1305d70e28f5SLen Brown switch (boot_cpu_data.x86_model) { 1306d70e28f5SLen Brown 1307db73c5a8SDave Hansen case INTEL_FAM6_IVYBRIDGE_X: 1308d70e28f5SLen Brown ivt_idle_state_table_update(); 1309d70e28f5SLen Brown break; 1310db73c5a8SDave Hansen case INTEL_FAM6_ATOM_GOLDMONT: 1311f2c4db1bSPeter Zijlstra case INTEL_FAM6_ATOM_GOLDMONT_PLUS: 13125dcef694SLen Brown bxt_idle_state_table_update(); 13135dcef694SLen Brown break; 1314c66f78a6SPeter Zijlstra case INTEL_FAM6_SKYLAKE: 1315d70e28f5SLen Brown sklh_idle_state_table_update(); 1316d70e28f5SLen Brown break; 1317d70e28f5SLen Brown } 13180138d8f0SLen Brown } 13190138d8f0SLen Brown 132026717172SLen Brown /* 132146bcfad7SDeepthi Dharwar * intel_idle_cpuidle_driver_init() 132246bcfad7SDeepthi Dharwar * allocate, initialize cpuidle_states 132346bcfad7SDeepthi Dharwar */ 13245469c827SRichard Cochran static void __init intel_idle_cpuidle_driver_init(void) 132546bcfad7SDeepthi Dharwar { 132646bcfad7SDeepthi Dharwar int cstate; 132746bcfad7SDeepthi Dharwar struct cpuidle_driver *drv = &intel_idle_driver; 132846bcfad7SDeepthi Dharwar 13290138d8f0SLen Brown intel_idle_state_table_update(); 13300138d8f0SLen Brown 13311b39e3f8SRafael J. Wysocki cpuidle_poll_state_init(drv); 133246bcfad7SDeepthi Dharwar drv->state_count = 1; 133346bcfad7SDeepthi Dharwar 1334e022e7ebSLen Brown for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { 133524bfa950SLen Brown int num_substates, mwait_hint, mwait_cstate; 133646bcfad7SDeepthi Dharwar 13377dd0e0afSLen Brown if ((cpuidle_state_table[cstate].enter == NULL) && 133828ba086eSRafael J. Wysocki (cpuidle_state_table[cstate].enter_s2idle == NULL)) 1339e022e7ebSLen Brown break; 1340e022e7ebSLen Brown 1341e022e7ebSLen Brown if (cstate + 1 > max_cstate) { 1342654d08a4SJoe Perches pr_info("max_cstate %d reached\n", max_cstate); 134346bcfad7SDeepthi Dharwar break; 134446bcfad7SDeepthi Dharwar } 134546bcfad7SDeepthi Dharwar 1346e022e7ebSLen Brown mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags); 1347e022e7ebSLen Brown mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint); 134846bcfad7SDeepthi Dharwar 134924bfa950SLen Brown /* number of sub-states for this state in CPUID.MWAIT */ 1350e022e7ebSLen Brown num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4)) 1351e022e7ebSLen Brown & MWAIT_SUBSTATE_MASK; 1352e022e7ebSLen Brown 135324bfa950SLen Brown /* if NO sub-states for this state in CPUID, skip it */ 135424bfa950SLen Brown if (num_substates == 0) 1355e022e7ebSLen Brown continue; 1356e022e7ebSLen Brown 1357d70e28f5SLen Brown /* if state marked as disabled, skip it */ 1358d70e28f5SLen Brown if (cpuidle_state_table[cstate].disabled != 0) { 1359654d08a4SJoe Perches pr_debug("state %s is disabled\n", 1360d70e28f5SLen Brown cpuidle_state_table[cstate].name); 1361d70e28f5SLen Brown continue; 1362d70e28f5SLen Brown } 1363d70e28f5SLen Brown 1364d70e28f5SLen Brown 1365e022e7ebSLen Brown if (((mwait_cstate + 1) > 2) && 136646bcfad7SDeepthi Dharwar !boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) 136746bcfad7SDeepthi Dharwar mark_tsc_unstable("TSC halts in idle" 136846bcfad7SDeepthi Dharwar " states deeper than C2"); 136946bcfad7SDeepthi Dharwar 137046bcfad7SDeepthi Dharwar drv->states[drv->state_count] = /* structure copy */ 137146bcfad7SDeepthi Dharwar cpuidle_state_table[cstate]; 137246bcfad7SDeepthi Dharwar 137346bcfad7SDeepthi Dharwar drv->state_count += 1; 137446bcfad7SDeepthi Dharwar } 137546bcfad7SDeepthi Dharwar 13768c058d53SLen Brown if (icpu->byt_auto_demotion_disable_flag) { 13778c058d53SLen Brown wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0); 13788c058d53SLen Brown wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0); 13798c058d53SLen Brown } 138046bcfad7SDeepthi Dharwar } 138146bcfad7SDeepthi Dharwar 138246bcfad7SDeepthi Dharwar 138346bcfad7SDeepthi Dharwar /* 138465b7f839SThomas Renninger * intel_idle_cpu_init() 138526717172SLen Brown * allocate, initialize, register cpuidle_devices 138665b7f839SThomas Renninger * @cpu: cpu/core to initialize 138726717172SLen Brown */ 1388fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_init(unsigned int cpu) 138926717172SLen Brown { 139026717172SLen Brown struct cpuidle_device *dev; 139126717172SLen Brown 139265b7f839SThomas Renninger dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu); 139365b7f839SThomas Renninger dev->cpu = cpu; 139426717172SLen Brown 139526717172SLen Brown if (cpuidle_register_device(dev)) { 1396654d08a4SJoe Perches pr_debug("cpuidle_register_device %d failed!\n", cpu); 139726717172SLen Brown return -EIO; 139826717172SLen Brown } 139965b7f839SThomas Renninger 1400b66b8b9aSAndi Kleen if (icpu->auto_demotion_disable_flags) 1401fb1013a0SSebastian Andrzej Siewior auto_demotion_disable(); 140226717172SLen Brown 1403dbf87ab8SBartlomiej Zolnierkiewicz if (icpu->disable_promotion_to_c1e) 1404fb1013a0SSebastian Andrzej Siewior c1e_promotion_disable(); 1405fb1013a0SSebastian Andrzej Siewior 1406fb1013a0SSebastian Andrzej Siewior return 0; 1407fb1013a0SSebastian Andrzej Siewior } 1408fb1013a0SSebastian Andrzej Siewior 1409fb1013a0SSebastian Andrzej Siewior static int intel_idle_cpu_online(unsigned int cpu) 1410fb1013a0SSebastian Andrzej Siewior { 1411fb1013a0SSebastian Andrzej Siewior struct cpuidle_device *dev; 1412fb1013a0SSebastian Andrzej Siewior 1413fb1013a0SSebastian Andrzej Siewior if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) 1414fb1013a0SSebastian Andrzej Siewior __setup_broadcast_timer(true); 1415fb1013a0SSebastian Andrzej Siewior 1416fb1013a0SSebastian Andrzej Siewior /* 1417fb1013a0SSebastian Andrzej Siewior * Some systems can hotplug a cpu at runtime after 1418fb1013a0SSebastian Andrzej Siewior * the kernel has booted, we have to initialize the 1419fb1013a0SSebastian Andrzej Siewior * driver in this case 1420fb1013a0SSebastian Andrzej Siewior */ 1421fb1013a0SSebastian Andrzej Siewior dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu); 1422fb1013a0SSebastian Andrzej Siewior if (!dev->registered) 1423fb1013a0SSebastian Andrzej Siewior return intel_idle_cpu_init(cpu); 1424dbf87ab8SBartlomiej Zolnierkiewicz 142526717172SLen Brown return 0; 142626717172SLen Brown } 142726717172SLen Brown 142826717172SLen Brown static int __init intel_idle_init(void) 142926717172SLen Brown { 1430fb1013a0SSebastian Andrzej Siewior int retval; 143126717172SLen Brown 1432d1896049SThomas Renninger /* Do not load intel_idle at all for now if idle= is passed */ 1433d1896049SThomas Renninger if (boot_option_idle_override != IDLE_NO_OVERRIDE) 1434d1896049SThomas Renninger return -ENODEV; 1435d1896049SThomas Renninger 143626717172SLen Brown retval = intel_idle_probe(); 143726717172SLen Brown if (retval) 143826717172SLen Brown return retval; 143926717172SLen Brown 1440e9df69ccSRichard Cochran intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device); 1441e9df69ccSRichard Cochran if (intel_idle_cpuidle_devices == NULL) 1442e9df69ccSRichard Cochran return -ENOMEM; 1443e9df69ccSRichard Cochran 144446bcfad7SDeepthi Dharwar intel_idle_cpuidle_driver_init(); 144526717172SLen Brown retval = cpuidle_register_driver(&intel_idle_driver); 144626717172SLen Brown if (retval) { 14473735d524SKonrad Rzeszutek Wilk struct cpuidle_driver *drv = cpuidle_get_driver(); 1448654d08a4SJoe Perches printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"), 14493735d524SKonrad Rzeszutek Wilk drv ? drv->name : "none"); 1450fb1013a0SSebastian Andrzej Siewior goto init_driver_fail; 145126717172SLen Brown } 145226717172SLen Brown 14532259a819SRichard Cochran if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ 14542259a819SRichard Cochran lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE; 14552259a819SRichard Cochran 1456fb1013a0SSebastian Andrzej Siewior retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online", 1457fb1013a0SSebastian Andrzej Siewior intel_idle_cpu_online, NULL); 1458fb1013a0SSebastian Andrzej Siewior if (retval < 0) 1459fb1013a0SSebastian Andrzej Siewior goto hp_setup_fail; 146026717172SLen Brown 1461654d08a4SJoe Perches pr_debug("lapic_timer_reliable_states 0x%x\n", 14622259a819SRichard Cochran lapic_timer_reliable_states); 14632259a819SRichard Cochran 146426717172SLen Brown return 0; 1465fb1013a0SSebastian Andrzej Siewior 1466fb1013a0SSebastian Andrzej Siewior hp_setup_fail: 1467fb1013a0SSebastian Andrzej Siewior intel_idle_cpuidle_devices_uninit(); 1468fb1013a0SSebastian Andrzej Siewior cpuidle_unregister_driver(&intel_idle_driver); 1469fb1013a0SSebastian Andrzej Siewior init_driver_fail: 1470fb1013a0SSebastian Andrzej Siewior free_percpu(intel_idle_cpuidle_devices); 1471fb1013a0SSebastian Andrzej Siewior return retval; 1472fb1013a0SSebastian Andrzej Siewior 147326717172SLen Brown } 147402c4fae9SPaul Gortmaker device_initcall(intel_idle_init); 147526717172SLen Brown 147602c4fae9SPaul Gortmaker /* 147702c4fae9SPaul Gortmaker * We are not really modular, but we used to support that. Meaning we also 147802c4fae9SPaul Gortmaker * support "intel_idle.max_cstate=..." at boot and also a read-only export of 147902c4fae9SPaul Gortmaker * it at /sys/module/intel_idle/parameters/max_cstate -- so using module_param 148002c4fae9SPaul Gortmaker * is the easiest way (currently) to continue doing that. 148102c4fae9SPaul Gortmaker */ 148226717172SLen Brown module_param(max_cstate, int, 0444); 1483