Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/58857 )
Change subject: [UNTESTED]soc/intel/common/block/power_limit: Compute pl1_time msr value ......................................................................
[UNTESTED]soc/intel/common/block/power_limit: Compute pl1_time msr value
Instead of using a static lookup table compute the best value at runtime. This also removes the 128s limit.
Change-Id: I3a66b86b61e512a45daaa06d2c459a200413ecdf Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M src/soc/intel/common/block/include/intelblocks/power_limit.h M src/soc/intel/common/block/power_limit/power_limit.c 2 files changed, 38 insertions(+), 68 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/57/58857/1
diff --git a/src/soc/intel/common/block/include/intelblocks/power_limit.h b/src/soc/intel/common/block/include/intelblocks/power_limit.h index 3f18126..93b22b8 100644 --- a/src/soc/intel/common/block/include/intelblocks/power_limit.h +++ b/src/soc/intel/common/block/include/intelblocks/power_limit.h @@ -37,7 +37,7 @@ };
/* Configure power limits for turbo mode */ -void set_power_limits(u8 power_limit_1_time, +void set_power_limits(int power_limit_1_time, struct soc_power_limits_config *config);
u8 get_cpu_tdp(void); diff --git a/src/soc/intel/common/block/power_limit/power_limit.c b/src/soc/intel/common/block/power_limit/power_limit.c index 417dd04..2b71e0e 100644 --- a/src/soc/intel/common/block/power_limit/power_limit.c +++ b/src/soc/intel/common/block/power_limit/power_limit.c @@ -7,69 +7,19 @@ #include <soc/msr.h> #include <soc/systemagent.h>
-/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */ -static const u8 power_limit_time_sec_to_msr[] = { - [0] = 0x00, - [1] = 0x0a, - [2] = 0x0b, - [3] = 0x4b, - [4] = 0x0c, - [5] = 0x2c, - [6] = 0x4c, - [7] = 0x6c, - [8] = 0x0d, - [10] = 0x2d, - [12] = 0x4d, - [14] = 0x6d, - [16] = 0x0e, - [20] = 0x2e, - [24] = 0x4e, - [28] = 0x6e, - [32] = 0x0f, - [40] = 0x2f, - [48] = 0x4f, - [56] = 0x6f, - [64] = 0x10, - [80] = 0x30, - [96] = 0x50, - [112] = 0x70, - [128] = 0x11, -}; - -/* Convert POWER_LIMIT_1_TIME MSR value to seconds */ -static const u8 power_limit_time_msr_to_sec[] = { - [0x00] = 0, - [0x0a] = 1, - [0x0b] = 2, - [0x4b] = 3, - [0x0c] = 4, - [0x2c] = 5, - [0x4c] = 6, - [0x6c] = 7, - [0x0d] = 8, - [0x2d] = 10, - [0x4d] = 12, - [0x6d] = 14, - [0x0e] = 16, - [0x2e] = 20, - [0x4e] = 24, - [0x6e] = 28, - [0x0f] = 32, - [0x2f] = 40, - [0x4f] = 48, - [0x6f] = 56, - [0x10] = 64, - [0x30] = 80, - [0x50] = 96, - [0x70] = 112, - [0x11] = 128, -}; +/* Returns time limit in s depending on Y, Z and TU */ +static int power_limit_time(uint8_t tu_bits, uint8_t y, uint8_t z) +{ + if (y < tu_bits) + return 0; + return POWER_OF_2(y - tu_bits) * (4 + z) / 4; +}
/* * Configure processor power limits if possible * This must be done AFTER set of BIOS_RESET_CPL */ -void set_power_limits(u8 power_limit_1_time, +void set_power_limits(int power_limit_1_time, struct soc_power_limits_config *conf) { msr_t msr = rdmsr(MSR_PLATFORM_INFO); @@ -78,10 +28,6 @@ unsigned int tdp, min_power, max_power, max_time, tdp_pl2, tdp_pl1; u8 power_limit_1_val;
- if (power_limit_1_time >= ARRAY_SIZE(power_limit_time_sec_to_msr)) - power_limit_1_time = - ARRAY_SIZE(power_limit_time_sec_to_msr) - 1; - if (!(msr.lo & PLATFORM_INFO_SET_TDP)) return;
@@ -98,17 +44,12 @@
printk(BIOS_INFO, "CPU TDP = %u Watts\n", tdp / power_unit);
- if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time) - power_limit_1_time = power_limit_time_msr_to_sec[max_time]; - if (min_power > 0 && tdp < min_power) tdp = min_power;
if (max_power > 0 && tdp > max_power) tdp = max_power;
- power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time]; - /* Set long term power limit to TDP */ limit.lo = 0; tdp_pl1 = ((conf->tdp_pl1_override == 0) ? @@ -119,6 +60,35 @@ /* Set PL1 Pkg Power clamp bit */ limit.lo |= PKG_POWER_LIMIT_CLAMP;
+ /* + * RAPL time window calculation defined as follows: + * Time Window = Time_Unit * (1+X/4)*(2*^Y), X Corresponds to [23:22], + * Y to [21:17] in MSR 0x610. 28 sec is equal to 0x6e. + */ + { +#define MSR_RAPL_POWER_UNIT 0x606 + + /* bits 16:19 = 2 ^ - time_unit */ + const uint8_t time_unit_bits = (rdmsr(MSR_RAPL_POWER_UNIT).lo >> 16) & 0xf; + /* Start at 1s */ + uint8_t best_y = time_unit_bits; + uint8_t best_z = 0; + int closest_time = power_limit_time(time_unit_bits, best_y, best_z); + + for (uint8_t y = time_unit_bits; y <= 0x1f; y++) { + for (uint8_t z = 0; z < 4; z++) { + if (ABS(power_limit_1_time - closest_time) + > ABS(power_limit_1_time - power_limit_time(time_unit_bits, y, z))) { + closest_time = power_limit_time(time_unit_bits, y, z); + best_y = y; + best_z = z; + } + } + } + + power_limit_1_val = (best_y & 0x1f) | ((best_z & 3) << 5); + } + limit.lo |= PKG_POWER_LIMIT_EN; limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) << PKG_POWER_LIMIT_TIME_SHIFT;