diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index c1b8869005..4d53112981 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -188,6 +188,12 @@ #define IA32_MSR_PAT_TYPE_WRITE_BACK 0x6ULL #define IA32_MSR_PAT_TYPE_UNCACHED 0x7ULL +// cpuid leaves +#define IA32_CPUID_LEAF_MWAIT 0x5 +#define IA32_CPUID_LEAF_XSTATE 0xd +#define IA32_CPUID_LEAF_TSC 0x15 +#define IA32_CPUID_LEAF_FREQUENCY 0x16 + // x86 features from cpuid eax 1, edx register // reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-5) #define IA32_FEATURE_FPU (1 << 0) // x87 fpu @@ -282,10 +288,6 @@ | IA32_FEATURE_AMD_EXT_RDTSCP \ | IA32_FEATURE_AMD_EXT_LONG) -// x86 defined features from cpuid eax 5, ecx register -#define IA32_FEATURE_POWER_MWAIT (1 << 0) -#define IA32_FEATURE_INTERRUPT_MWAIT (1 << 1) - // x86 defined features from cpuid eax 6, eax register // reference https://software.intel.com/content/dam/develop/public/us/en/documents/253666-sdm-vol-2a.pdf (Table 3-8) #define IA32_FEATURE_DTS (1 << 0) // Digital Thermal Sensor @@ -514,7 +516,6 @@ enum x86_feature_type { FEATURE_EXT, // cpuid eax=1, ecx register FEATURE_EXT_AMD_ECX, // cpuid eax=0x80000001, ecx register (AMD) FEATURE_EXT_AMD, // cpuid eax=0x80000001, edx register (AMD) - FEATURE_5_ECX, // cpuid eax=5, ecx register FEATURE_6_EAX, // cpuid eax=6, eax registers FEATURE_6_ECX, // cpuid eax=6, ecx registers FEATURE_7_EBX, // cpuid eax=7, ebx registers diff --git a/src/add-ons/kernel/power/cpuidle/x86_cstates/x86_cstates.cpp b/src/add-ons/kernel/power/cpuidle/x86_cstates/x86_cstates.cpp index d421f1cfbb..6247f09746 100644 --- a/src/add-ons/kernel/power/cpuidle/x86_cstates/x86_cstates.cpp +++ b/src/add-ons/kernel/power/cpuidle/x86_cstates/x86_cstates.cpp @@ -23,6 +23,10 @@ #define CPUIDLE_CSTATE_MAX 8 +#define CPUID_MWAIT_ECX_EXTENSIONS 0x1 +#define CPUID_MWAIT_ECX_INTERRUPTS_BREAK 0x2 +#define CPUID_MWAIT_ECX_SUPPORT (CPUID_MWAIT_ECX_EXTENSIONS | CPUID_MWAIT_ECX_INTERRUPTS_BREAK) + #define MWAIT_INTERRUPTS_BREAK (1 << 0) #define X86_CSTATES_MODULE_NAME CPUIDLE_MODULES_PREFIX "/x86_cstates/v1" @@ -126,10 +130,6 @@ init_cstates() { if (!x86_check_feature(IA32_FEATURE_EXT_MONITOR, FEATURE_EXT)) return B_ERROR; - if (!x86_check_feature(IA32_FEATURE_POWER_MWAIT, FEATURE_5_ECX)) - return B_ERROR; - if (!x86_check_feature(IA32_FEATURE_INTERRUPT_MWAIT, FEATURE_5_ECX)) - return B_ERROR; // we need invariant TSC if (!x86_check_feature(IA32_FEATURE_INVARIANT_TSC, FEATURE_EXT_7_EDX)) @@ -139,17 +139,26 @@ init_cstates() cpuid_info cpuid; get_current_cpuid(&cpuid, 0, 0); uint32 maxBasicLeaf = cpuid.eax_0.max_eax; - if (maxBasicLeaf < 5) + if (maxBasicLeaf < IA32_CPUID_LEAF_MWAIT) return B_ERROR; - get_current_cpuid(&cpuid, 5, 0); - if ((cpuid.regs.eax & 0xffff) < sizeof(int32)) + get_current_cpuid(&cpuid, IA32_CPUID_LEAF_MWAIT, 0); + uint32 minMonitorLineSize = cpuid.regs.eax & 0xffff; + //uint32 maxMonitorLineSize = cpuid.regs.ebx & 0xffff; + uint32 mwaitSubStates = cpuid.regs.edx; + if (minMonitorLineSize < sizeof(int32)) + return B_ERROR; + if (mwaitSubStates == 0) + return B_ERROR; + // check Enumeration of Monitor-Mwait extensions is supported + // and check treating interrupts as break-events even when interrupts disabled is supported + if ((cpuid.regs.ecx & CPUID_MWAIT_ECX_SUPPORT) != CPUID_MWAIT_ECX_SUPPORT) return B_ERROR; char cStates[64]; unsigned int offset = 0; for (int32 i = 1; i < CPUIDLE_CSTATE_MAX; i++) { - int32 subStates = (cpuid.regs.edx >> (i * 4)) & 0xf; + int32 subStates = (mwaitSubStates >> (i * 4)) & 0xf; // no sub-states means the state is not available if (subStates == 0) continue; diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index dde7fee9e5..4e01c91a38 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -1445,11 +1445,6 @@ detect_cpu(int currentCPU, bool full = true) cpu->arch.feature[FEATURE_EXT_AMD] &= IA32_FEATURES_INTEL_EXT; } - if (maxBasicLeaf >= 5) { - get_current_cpuid(&cpuid, 5, 0); - cpu->arch.feature[FEATURE_5_ECX] = cpuid.regs.ecx; - } - if (maxBasicLeaf >= 6) { get_current_cpuid(&cpuid, 6, 0); cpu->arch.feature[FEATURE_6_EAX] = cpuid.regs.eax; @@ -1627,23 +1622,23 @@ init_tsc_with_cpuid(kernel_args* args, uint32* conversionFactor) cpuid_info cpuid; get_current_cpuid(&cpuid, 0, 0); uint32 maxBasicLeaf = cpuid.eax_0.max_eax; - if (maxBasicLeaf < 0x15) + if (maxBasicLeaf < IA32_CPUID_LEAF_TSC) return; - get_current_cpuid(&cpuid, 0x15, 0); + get_current_cpuid(&cpuid, IA32_CPUID_LEAF_TSC, 0); if (cpuid.regs.eax == 0 || cpuid.regs.ebx == 0) return; uint32 khz = cpuid.regs.ecx / 1000; uint32 denominator = cpuid.regs.eax; uint32 numerator = cpuid.regs.ebx; if (khz == 0 && model == 0x5f) { - // CPUID 0x16 isn't supported, hardcoding + // CPUID_LEAF_FREQUENCY isn't supported, hardcoding khz = 25000; } - if (khz == 0 && maxBasicLeaf >= 0x16) { + if (khz == 0 && maxBasicLeaf >= IA32_CPUID_LEAF_FREQUENCY) { // for these CPUs the base frequency is also the tsc frequency - get_current_cpuid(&cpuid, 0x16, 0); + get_current_cpuid(&cpuid, IA32_CPUID_LEAF_FREQUENCY, 0); khz = cpuid.regs.eax * 1000 * denominator / numerator; } if (khz == 0) @@ -1908,10 +1903,10 @@ arch_cpu_init_post_vm(kernel_args* args) call_all_cpus_sync(&enable_osxsave, NULL); gXsaveMask = IA32_XCR0_X87 | IA32_XCR0_SSE; cpuid_info cpuid; - get_current_cpuid(&cpuid, 0xd, 0); + get_current_cpuid(&cpuid, IA32_CPUID_LEAF_XSTATE, 0); gXsaveMask |= (cpuid.regs.eax & IA32_XCR0_AVX); call_all_cpus_sync(&enable_xsavemask, NULL); - get_current_cpuid(&cpuid, 0xd, 0); + get_current_cpuid(&cpuid, IA32_CPUID_LEAF_XSTATE, 0); gFPUSaveLength = cpuid.regs.ebx; if (gFPUSaveLength > sizeof(((struct arch_thread *)0)->fpu_state)) gFPUSaveLength = 832;