diff --git a/src/cpu/intel/common/common.h b/src/cpu/intel/common/common.h index ef0a5d9044..a29fd2e6b6 100644 --- a/src/cpu/intel/common/common.h +++ b/src/cpu/intel/common/common.h @@ -47,4 +47,23 @@ void configure_dca_cap(void); */ void set_energy_perf_bias(u8 policy); +/* + * Check energy performance preference and HWP capabilities from Thermal and + * Power Management Leaf CPUID. + */ +bool check_energy_perf_cap(void); + +/* + * Set the IA32_HWP_REQUEST Energy-Performance Preference bits on the logical + * thread. 0 is a hint to the HWP to prefer performance, and 255 is a hint to + * prefer energy efficiency. + */ +void set_energy_perf_pref(u8 pref); + +/* + * Instructs the CPU to use EPP hints. This means that any energy policies set + * up in `set_energy_perf_bias` will be ignored afterwards. + */ +void enable_energy_perf_pref(void); + #endif diff --git a/src/cpu/intel/common/common_init.c b/src/cpu/intel/common/common_init.c index 24e3eeb60b..4d6df845f7 100644 --- a/src/cpu/intel/common/common_init.c +++ b/src/cpu/intel/common/common_init.c @@ -5,9 +5,12 @@ #include #include #include +#include #include "common.h" -#define CPUID_6_ECX_EPB (1 << 3) +#define CPUID_6_ECX_EPB (1 << 3) +#define CPUID_6_ENGERY_PERF_PREF (1 << 10) +#define CPUID_6_HWP (1 << 7) void set_vmx_and_lock(void) { @@ -182,3 +185,43 @@ void set_energy_perf_bias(u8 policy) msr_unset_and_set(IA32_ENERGY_PERF_BIAS, ENERGY_POLICY_MASK, epb); printk(BIOS_DEBUG, "cpu: energy policy set to %u\n", epb); } + +/* + * Check energy performance preference and HWP capabilities from Thermal and + * Power Management Leaf CPUID + */ +bool check_energy_perf_cap(void) +{ + const u32 cap = cpuid_eax(CPUID_LEAF_PM); + if (!(cap & CPUID_6_ENGERY_PERF_PREF)) + return false; + if (!(cap & CPUID_6_HWP)) + return false; + return true; +} + +/* + * Instructs the CPU to use EPP hints. This means that any energy policies set + * up in `set_energy_perf_bias` will be ignored afterwards. + */ +void enable_energy_perf_pref(void) +{ + msr_t msr = rdmsr(IA32_PM_ENABLE); + if (!(msr.lo & HWP_ENABLE)) { + /* Package-scoped MSR */ + printk(BIOS_DEBUG, "HWP_ENABLE: energy-perf preference in favor of energy-perf bias\n"); + msr_set(IA32_PM_ENABLE, HWP_ENABLE); + } +} + +/* + * Set the IA32_HWP_REQUEST Energy-Performance Preference bits on the logical + * thread. 0 is a hint to the HWP to prefer performance, and 255 is a hint to + * prefer energy efficiency. + * This function needs to be called when HWP_ENABLE is set. +*/ +void set_energy_perf_pref(u8 pref) +{ + msr_unset_and_set(IA32_HWP_REQUEST, IA32_HWP_REQUEST_EPP_MASK, + pref << IA32_HWP_REQUEST_EPP_SHIFT); +} diff --git a/src/include/cpu/x86/msr.h b/src/include/cpu/x86/msr.h index 4d1cb68279..9f30c057ed 100644 --- a/src/include/cpu/x86/msr.h +++ b/src/include/cpu/x86/msr.h @@ -86,8 +86,11 @@ #define IA32_VMX_MISC_MSR 0x485 #define IA32_PM_ENABLE 0x770 +#define HWP_ENABLE 0x1 #define IA32_HWP_CAPABILITIES 0x771 #define IA32_HWP_REQUEST 0x774 +#define IA32_HWP_REQUEST_EPP_MASK 0xff000000 +#define IA32_HWP_REQUEST_EPP_SHIFT 24 #define IA32_HWP_STATUS 0x777 #define IA32_L3_PROTECTED_WAYS 0xc85 #define IA32_SF_QOS_INFO 0xc87