From bdf757aa86f004889073390ed42138c65a8b5b10 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Tue, 24 Mar 2026 14:37:56 -0500 Subject: [PATCH] soc/intel/common/power_limit: Add option-driven PL1/PL2 overrides and locking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add option-backed overrides for PL1 and PL2, to allow for runtime configuration, with fallback to board programmed values. Clamp PL2 to at least PL1. Add an option to control setting the lock bit, to prevent OS or user tools from overriding the desired power limits. Add a CFR object for setting the lock bit, but not for the PL1/2 overrides, as the desired values there are board specific. TEST=tested with rest of patch train Change-Id: I7194df93e0602b4e00d1d39e44cb0b0ed2582cb9 Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/91846 Reviewed-by: Angel Pons Reviewed-by: Aralguppe, Sowmya Tested-by: build bot (Jenkins) Reviewed-by: Jérémy Compostella --- .../common/block/include/intelblocks/cfr.h | 8 ++++++++ .../common/block/include/intelblocks/msr.h | 1 + .../common/block/power_limit/power_limit.c | 17 +++++++++++++---- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/soc/intel/common/block/include/intelblocks/cfr.h b/src/soc/intel/common/block/include/intelblocks/cfr.h index 0185b0c028..0905d2d65d 100644 --- a/src/soc/intel/common/block/include/intelblocks/cfr.h +++ b/src/soc/intel/common/block/include/intelblocks/cfr.h @@ -184,4 +184,12 @@ static const struct sm_object bios_lock = SM_DECLARE_BOOL({ .default_value = CONFIG(BOOTMEDIA_SMM_BWP), }, WITH_CALLBACK(update_smm_bwp)); +static const struct sm_object pkg_power_limit_lock = SM_DECLARE_BOOL({ + .opt_name = "pkg_power_limit_lock", + .ui_name = "Package power limit lock", + .ui_helptext = "Lock the package power limits after programming.\n" + "This prevents the power limits from being changed by the OS or runtime tools.", + .default_value = false, +}); + #endif /* SOC_INTEL_CMN_CFR_H */ diff --git a/src/soc/intel/common/block/include/intelblocks/msr.h b/src/soc/intel/common/block/include/intelblocks/msr.h index 1965b36d59..26f433fb15 100644 --- a/src/soc/intel/common/block/include/intelblocks/msr.h +++ b/src/soc/intel/common/block/include/intelblocks/msr.h @@ -101,6 +101,7 @@ #define PKG_POWER_LIMIT_TIME_MASK (0x7f) #define PKG_POWER_LIMIT_DUTYCYCLE_SHIFT 24 #define PKG_POWER_LIMIT_DUTYCYCLE_MASK (0x7f) +#define PKG_POWER_LIMIT_LOCK (1 << 31) #define MSR_CORE_MKTME_ACTIVATION 0x9ff /* SMM save state MSRs */ 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 4758f09f82..167c8d7f73 100644 --- a/src/soc/intel/common/block/power_limit/power_limit.c +++ b/src/soc/intel/common/block/power_limit/power_limit.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -141,8 +142,8 @@ void set_power_limits(u8 power_limit_1_time, /* Set long term power limit to TDP */ limit.lo = 0; - tdp_pl1 = ((conf->tdp_pl1_override == 0) ? - tdp : (conf->tdp_pl1_override * power_unit)); + const unsigned int tdp_pl1_override = get_uint_option("tdp_pl1_override", conf->tdp_pl1_override); + tdp_pl1 = tdp_pl1_override ? (tdp_pl1_override * power_unit) : tdp; printk(BIOS_INFO, "CPU PL1 = %u Watts\n", tdp_pl1 / power_unit); limit.lo |= (tdp_pl1 & PKG_POWER_LIMIT_MASK); @@ -155,13 +156,21 @@ void set_power_limits(u8 power_limit_1_time, /* Set short term power limit to 1.25 * TDP if no config given */ limit.hi = 0; - tdp_pl2 = (conf->tdp_pl2_override == 0) ? - (tdp * 125) / 100 : (conf->tdp_pl2_override * power_unit); + const unsigned int tdp_pl2_override = get_uint_option("tdp_pl2_override", conf->tdp_pl2_override); + tdp_pl2 = tdp_pl2_override ? (tdp_pl2_override * power_unit) : ((tdp * 125) / 100); + /* Ensure PL2 isn't less than PL1 */ + if (tdp_pl2 < tdp_pl1) + tdp_pl2 = tdp_pl1; printk(BIOS_INFO, "CPU PL2 = %u Watts\n", tdp_pl2 / power_unit); limit.hi |= (tdp_pl2) & PKG_POWER_LIMIT_MASK; limit.hi |= PKG_POWER_LIMIT_CLAMP; limit.hi |= PKG_POWER_LIMIT_EN; + if (get_uint_option("pkg_power_limit_lock", 0)) { + limit.hi |= PKG_POWER_LIMIT_LOCK; + printk(BIOS_INFO, "Locking package power limits\n"); + } + /* Power limit 2 time is only programmable on server SKU */ wrmsr(MSR_PKG_POWER_LIMIT, limit);