Page MenuHomeFreeBSD
Authored By
olce
May 28 2026, 2:40 PM
Size
14 KB
Referenced Files
None
Subscribers
None

D56791-olce.patch

diff --git i/sys/x86/power/intel_rapl.c w/sys/x86/power/intel_rapl.c
index 8917891d860e..4dcfcc04014b 100644
--- i/sys/x86/power/intel_rapl.c
+++ w/sys/x86/power/intel_rapl.c
@@ -43,29 +43,25 @@ struct rapl_softc {
uint32_t model;
struct timeout_task rapl_task;
bool running;
- uint64_t pu;
- uint64_t esu;
- uint64_t tu;
+ uint64_t pu;
+ uint64_t esu;
+ uint64_t tu;
- uint64_t dram_pu;
- uint64_t dram_esu;
- uint64_t dram_tu;
-
- struct rapl_reading last_reading;
+ struct rapl_reading last_reading;
int read_frequency;
};
-static void rapl_reading_task(void *, int);
+static void rapl_reading_task(void *, int);
static void intel_rapl_identify(driver_t *, device_t);
static int intel_rapl_probe(device_t dev);
static int intel_rapl_attach(device_t dev);
static int intel_rapl_detach(device_t dev);
-static void take_reading(struct rapl_softc *, struct rapl_reading *);
+static void take_reading(struct rapl_softc *, struct rapl_reading *);
#define INTEL_MODEL_ATOM_C2000 0x4D
#define INTEL_MODEL_SKY_LAKE 0x4E
#define INTEL_MODEL_SKY_LAKE_2 0x5E
@@ -133,256 +129,241 @@ uint8_t intel_rapl_lake_models[] = {
uint8_t intel_rapl_atom_models[] = {
INTEL_MODEL_ATOM_C2000,
};
-#define RAPL_F_PP0_ENERGY_STATUS 0x000000001
-#define RAPL_F_PP1_ENERGY_STATUS 0x000000002
-#define RAPL_F_CORE_PERF_LIMIT_REASONS 0x000000004
-#define RAPL_F_PLATFORM_POWER_LIMIT 0x000000008
-#define RAPL_F_POWER_UNIT 0x000000010
-#define RAPL_F_PKG_POWER_LIMIT 0x000000020
-#define RAPL_F_PKG_ENERGY_STATUS_MSR 0x000000040
-#define RAPL_F_PKG_POWER_INFO 0x000000080
-#define RAPL_F_PKG_POWER_INFO_ATOM 0x000000100
-#define RAPL_F_PKG_PERF_STATUS 0x000000200
-#define RAPL_F_PP0_POWER_LIMIT 0x000000400
-#define RAPL_F_PP1_POWER_LIMIT 0x000000800
-#define RAPL_F_PP0_ENERGY_STAUS 0x000001000
-#define RAPL_F_PP1_ENERGY_STAUS 0x000002000
-#define RAPL_F_PP0_POLICY 0x000004000
-#define RAPL_F_PP1_POLICY 0x000008000
-#define RAPL_F_PP0_PERF_STATUS 0x000010000
-#define RAPL_F_DRAM_POWER_UNIT 0x000020000
-#define RAPL_F_DRAM_ENERGY_STATUS 0x000040000
-#define RAPL_F_DRAM_POWER_INFO 0x000080000
-#define RAPL_F_DRAM_PERF_STATUS 0x000100000
-#define RAPL_F_PLATFORM_ENERGY_COUNTER 0x000200000
+#define RAPL_FM_POWER_UNIT 0x000000001
+#define RAPL_FM_PKG_POWER_LIMIT 0x000000002
+#define RAPL_FM_PKG_ENERGY_STATUS 0x000000004
+#define RAPL_FM_PKG_POWER_STATUS 0x000000008
+#define RAPL_FM_PKG_POWER_INFO 0x000000010
+#define RAPL_FM_PKG_POWER_INFO_ATOM 0x000000020
+#define RAPL_FM_DRAM_POWER_LIMIT 0x000000040
+#define RAPL_FM_DRAM_ENERGY_STATUS 0x000000080
+#define RAPL_FM_DRAM_PERF_STATUS 0x000000100
+#define RAPL_FM_DRAM_POWER_INFO 0x000000200
+#define RAPL_FM_PP0_POWER_LIMIT 0x000000400
+#define RAPL_FM_PP0_ENERGY_STATUS 0x000000800
+#define RAPL_FM_PP0_POLICY 0x000001000
+#define RAPL_FM_PP0_PERF_STATUS 0x000002000
+#define RAPL_FM_PP1_POWER_LIMIT 0x000004000
+#define RAPL_FM_PP1_ENERGY_STATUS 0x000008000
+#define RAPL_FM_PP1_POLICY 0x000010000
+#define RAPL_FM_PLATFORM_ENERGY_COUNTER 0x000020000
+#define RAPL_FM_CORE_PERF_LIMIT_REASONS 0x000040000
+#define RAPL_FM_PLATFORM_POWER_LIMIT 0x000080000
-#define INTEL_RAPL_LAKE_FLAGS (RAPL_F_POWER_UNIT | \
- RAPL_F_PP0_ENERGY_STATUS | \
- RAPL_F_PP1_ENERGY_STATUS | \
- RAPL_F_DRAM_ENERGY_STATUS | \
- RAPL_F_PLATFORM_ENERGY_COUNTER | \
- RAPL_F_CORE_PERF_LIMIT_REASONS | \
- RAPL_F_PKG_POWER_INFO | \
- RAPL_F_PLATFORM_POWER_LIMIT)
+#define INTEL_RAPL_LAKE_FLAGS (RAPL_FM_POWER_UNIT | \
+ RAPL_FM_PKG_POWER_INFO | \
+ RAPL_FM_DRAM_ENERGY_STATUS | \
+ RAPL_FM_PP0_ENERGY_STATUS | \
+ RAPL_FM_PP1_ENERGY_STATUS | \
+ RAPL_FM_PLATFORM_ENERGY_COUNTER | \
+ RAPL_FM_CORE_PERF_LIMIT_REASONS | \
+ RAPL_FM_PLATFORM_POWER_LIMIT)
-#define INTEL_RAPL_ATOM_FLAGS (RAPL_F_POWER_UNIT | \
- RAPL_F_PP0_ENERGY_STATUS | \
- RAPL_F_PP1_ENERGY_STATUS | \
- RAPL_F_DRAM_ENERGY_STATUS | \
- RAPL_F_PLATFORM_ENERGY_COUNTER | \
- RAPL_F_CORE_PERF_LIMIT_REASONS | \
- RAPL_F_PLATFORM_POWER_LIMIT)
+#define INTEL_RAPL_ATOM_FLAGS (RAPL_FM_POWER_UNIT | \
+ RAPL_FM_PKG_POWER_INFO_ATOM | \
+ RAPL_FM_DRAM_ENERGY_STATUS | \
+ RAPL_FM_PP0_ENERGY_STATUS | \
+ RAPL_FM_PP1_ENERGY_STATUS | \
+ RAPL_FM_PLATFORM_ENERGY_COUNTER | \
+ RAPL_FM_CORE_PERF_LIMIT_REASONS | \
+ RAPL_FM_PLATFORM_POWER_LIMIT)
-#define RAPL_MSR_BITS "\20" \
- "\1PP0_ENERGY_STATUS\2PLATFORM_ENERGY_COUNTER" \
- "\3CORE_PERF_LIMIT_REASONS\4PLATFORM_POWER_LIMIT" \
- "\5POWER_UNIT\6PKG_POWER_LIMIT" \
- "\7APL_MSR_PKG_ENERGY_STATUS_MSR\10PKG_POWER_INFO" \
- "\11PKG_POWER_INFO_ATOM" \
- "\12PKG_PERF_STATUS\13PP0_POWER_LIMIT" \
- "\14PP1_POWER_LIMIT\15PP0_ENERGY_STAUS" \
- "\16PP1_ENERGY_STAUS\17PP0_POLICY" \
- "\20PP1_POLICY\21PP0_PERF_STATUS" \
- "\22DRAM_POWER_UNIT\23DRAM_ENERGY_STATUS" \
- "\24DRAM_POWER_INFO\25DRAM_PERF_STATUS"
+#define RAPL_MSR_BITS "\20" \
+"XXX_FIXME_XXX"
#define RAPL_REASON_BITS "\20" \
- "\0REASON_PROCHOT\1REASON_THERMSTAT" \
- "\4REASON_RSRS_R0\5REASON_RATL_STAT" \
- "\6REASON_VRTHERM_ALRT\7REASON_VRTHERM_DES" \
- "\8REASON_OTHER\10REASON_PL1_STAT" \
- "\11REASON_PL2_STAT\12REASON_MAX_TURBO" \
- "\13REASON_TURBO_TRANS" \
- "\16REASON_PROCHOT_LOG\17REASON_THERMSTAT_LOG" \
- "\20REASON_RSRS_R0_LOG\21REASON_RATL_STAT_LOG" \
- "\22REASON_VRTHERM_ALRT_LOG\23REASON_VRTHERM_DES_LOG" \
- "\24REASON_OTHER_LOG\26REASON_PL1_STAT_LOG" \
- "\27REASON_PL2_STAT_LOG\28REASON_MAX_TURBO_LOG" \
- "\29REASON_TURBO_TRANS_LOG"
+ "\0PROCHOT\1THERMSTAT" \
+ "\4RSRS_R0\5RATL_STAT" \
+ "\6VRTHERM_ALRT\7VRTHERM_DES" \
+ "\8OTHER\10PL1_STAT" \
+ "\11PL2_STAT\12MAX_TURBO" \
+ "\13TURBO_TRANS" \
+ "\16PROCHOT_LOG\17THERMSTAT_LOG" \
+ "\20RSRS_R0_LOG\21RATL_STAT_LOG" \
+ "\22VRTHERM_ALRT_LOG\23VRTHERM_DES_LOG" \
+ "\24OTHER_LOG\26PL1_STAT_LOG" \
+ "\27PL2_STAT_LOG\28MAX_TURBO_LOG" \
+ "\29TURBO_TRANS_LOG"
static void
rapl_reading_task(void *arg, int pending)
{
struct rapl_softc *sc = (struct rapl_softc *)arg;
take_reading(sc, &sc->last_reading);
if (sc->running)
taskqueue_enqueue_timeout(taskqueue_thread, &sc->rapl_task,
- hz/sc->read_frequency);
+ max(hz/sc->read_frequency, 1));
}
static void
take_reading(struct rapl_softc *sc, struct rapl_reading *r)
{
uint64_t value;
/*
* On first call read out base units, these cannot change at run time.
* This field should always be available.
*/
if (sc->pu == 0 || sc->esu == 0 || sc->tu == 0) {
rdmsr_safe(MSR_RAPL_POWER_UNIT, &value);
+ /* XXX OC - Switch to µW for better precision. */
sc->pu = (1000) / (1 << (value & 0xf)); // milli Watts
/*
* ESU reads from the register are reported Joules, (i.e. we
* get 15.3 uJ from the datasheet default value, but we need to
* scale it up to represent it as an integer).
*
*/
+ /* XXX OC - Switch to nJ and ns for better precision. */
sc->esu = (1000 * 1000) / (1 << ((value >> 8) & 0x1f)); // micro Joules
sc->tu = (1000 * 1000) / (1 << ((value >> 16) & 0xf)); // micro Seconds
}
- if (sc->rapl_flags & RAPL_F_PP0_ENERGY_STATUS) {
+ if (sc->rapl_flags & RAPL_FM_PP0_ENERGY_STATUS) {
rdmsr_safe(MSR_PP0_ENERGY_STATUS, &value);
r->pp0 = (value & 0x00000000FFFFFFFF) * sc->esu;
}
- if (sc->rapl_flags & RAPL_F_PP1_ENERGY_STATUS) {
+ if (sc->rapl_flags & RAPL_FM_PP1_ENERGY_STATUS) {
rdmsr_safe(MSR_PP1_ENERGY_STATUS, &value);
r->pp1 = (value & 0x00000000FFFFFFFF) * sc->esu;
}
- if (sc->rapl_flags & RAPL_F_PLATFORM_ENERGY_COUNTER) {
+ if (sc->rapl_flags & RAPL_FM_PLATFORM_ENERGY_COUNTER) {
rdmsr_safe(MSR_PLATFORM_ENERGY_COUNTER, &value);
r->platform = (value & 0x00000000FFFFFFFF) * sc->esu;
}
- if (sc->rapl_flags & RAPL_F_CORE_PERF_LIMIT_REASONS) {
+ if (sc->rapl_flags & RAPL_FM_CORE_PERF_LIMIT_REASONS) {
rdmsr_safe(MSR_CORE_PERF_LIMIT_REASONS, &value);
}
- if (sc->rapl_flags & RAPL_F_PLATFORM_POWER_LIMIT) {
+ if (sc->rapl_flags & RAPL_FM_PLATFORM_POWER_LIMIT) {
rdmsr_safe(MSR_PLATFORM_POWER_LIMIT, &value);
}
- /* DRAM power domain */
- if (sc->dram_pu == 0 || sc->dram_esu == 0 || sc->dram_tu == 0) {
-
- rdmsr_safe(MSR_RAPL_POWER_UNIT, &value);
-
- sc->dram_pu = (1000) / (1 << (value & 0xf)); // milli Watts
-
- /*
- * ESU reads from the register are reported Joules, (i.e. we
- * get 15.3 uJ from the datasheet default value, but we need to
- * scale it up to represent it as an integer).
- *
- */
- sc->dram_esu = (1000 * 1000) / (1 << ((value >> 8) & 0x1f)); // micro Joules
- sc->dram_tu = (1000 * 1000) / (1 << ((value >> 16) & 0xf)); // micro Seconds
- }
- if (sc->rapl_flags & RAPL_F_DRAM_ENERGY_STATUS) {
+ if (sc->rapl_flags & RAPL_FM_DRAM_ENERGY_STATUS) {
rdmsr_safe(MSR_DRAM_ENERGY_STATUS, &value);
- r->dram = (value & 0x00000000FFFFFFFF) * sc->dram_esu;
+ r->dram = (value & 0x00000000FFFFFFFF) * sc->esu;
}
}
static int
intel_rapl_dump_sysctl_handler(SYSCTL_HANDLER_ARGS)
{
struct rapl_softc *sc;
uint64_t value = 0;
struct sbuf *sb;
+ struct sbuf sbs;
int ret;
sc = (struct rapl_softc *)arg1;
- sb = sbuf_new_auto();
+ sb = sbuf_new_for_sysctl(&sbs, NULL, 0, req);
sbuf_printf(sb, "\n");
take_reading(sc, &sc->last_reading);
- if (sc->rapl_flags & RAPL_F_POWER_UNIT) {
+ if (sc->rapl_flags & RAPL_FM_POWER_UNIT) {
sbuf_printf(sb, "POWER UNIT\t\t\t\t0x%016lx\n", value);
sbuf_printf(sb, "\t\tPU\t%ld mW\n", sc->pu);
sbuf_printf(sb, "\t\tESU\t%ld pJ\n", sc->esu);
sbuf_printf(sb, "\t\tTU\t%ld uS\n", sc->tu);
}
- if (sc->rapl_flags & RAPL_F_PP0_ENERGY_STATUS) {
+ if (sc->rapl_flags & RAPL_FM_PP0_ENERGY_STATUS) {
rdmsr_safe(MSR_PP0_ENERGY_STATUS, &value);
sbuf_printf(sb, "PP0_ENERGY_STATUS\t\t0x%016lx\n", value);
if (sc->esu != 0) {
uint64_t e = (value & 0x00000000FFFFFFFF) * sc->esu;
sbuf_printf(sb, "\tenergy\t\t%ld\n", e);
}
}
- if (sc->rapl_flags & RAPL_F_PLATFORM_ENERGY_COUNTER) {
+ if (sc->rapl_flags & RAPL_FM_PLATFORM_ENERGY_COUNTER) {
rdmsr_safe(MSR_PLATFORM_ENERGY_COUNTER, &value);
sbuf_printf(sb, "PLATFORM_ENERGY_COUNTER\t0x%016lx\n", value);
if (sc->esu != 0 && value != 0) {
uint64_t e = (value & 0x00000000FFFFFFFF) * sc->esu;
sbuf_printf(sb, "\tenergy\t\t%ld\n", e);
}
}
- if (sc->rapl_flags & RAPL_F_CORE_PERF_LIMIT_REASONS) {
+ if (sc->rapl_flags & RAPL_FM_CORE_PERF_LIMIT_REASONS) {
rdmsr_safe(MSR_CORE_PERF_LIMIT_REASONS, &value);
sbuf_printf(sb, "CORE_PERF_LIMIT_REASONS\t0x%016lx\n", value);
}
- if (sc->rapl_flags & RAPL_F_PLATFORM_POWER_LIMIT) {
+ if (sc->rapl_flags & RAPL_FM_PLATFORM_POWER_LIMIT) {
rdmsr_safe(MSR_PLATFORM_POWER_LIMIT, &value);
sbuf_printf(sb, "PLATFORM_POWER_LIMIT\t\t0x%016lx\n", value);
}
ret = sbuf_finish(sb);
- if (ret == 0)
- ret = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
sbuf_delete(sb);
return (ret);
}
static int
intel_rapl_reason_sysctl_handler(SYSCTL_HANDLER_ARGS)
{
struct rapl_softc *sc;
uint64_t value;
int ret;
struct sbuf *sb;
+ struct sbuf sbs;
sc = (struct rapl_softc *)arg1;
- if (sc->rapl_flags & RAPL_F_CORE_PERF_LIMIT_REASONS) {
+ if (sc->rapl_flags & RAPL_FM_CORE_PERF_LIMIT_REASONS) {
rdmsr_safe(MSR_CORE_PERF_LIMIT_REASONS, &value);
- sb = sbuf_new_auto();
+ sb = sbuf_new_for_sysctl(&sbs, NULL, 0, req);
bool log = false;
if (value & 0x00000000FFFF0000)
log = true;
- sbuf_printf(sb, "%b\n", (int)value, RAPL_MSR_BITS);
+ sbuf_printf(sb, "%b\n", (int)value, RAPL_REASON_BITS);
ret = sbuf_finish(sb);
- if (ret == 0)
- ret = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
sbuf_delete(sb);
/* Clear the log if it exists */
if (log)
wrmsr_safe(MSR_CORE_PERF_LIMIT_REASONS, 0);
} else {
return (0);
}
- return ret;
+ return (ret);
}
static int
intel_rapl_read_freq_sysctl_handler(SYSCTL_HANDLER_ARGS)
{
+ struct rapl_softc *const sc = arg1;
int err, val;
- val = 1;
- err = sysctl_handle_int(oidp, &val, 0, req);
+ val = sc->read_frequency;
+ err = sysctl_handle_int(oidp, &val, 0, req);
if (err != 0 || req->newptr == NULL)
return (err);
if(val == 0 || val > 1000)
return (EINVAL);
+ if (val != sc->read_frequency) {
+ sc->read_frequency = val;
+
+ if (taskqueue_cancel_timeout(taskqueue_thread, &sc->rapl_task,
+ NULL) != 0)
+ taskqueue_drain_timeout(taskqueue_thread,
+ &sc->rapl_task);
+ /* Trigger an immediate read. */
+ taskqueue_enqueue_timeout(taskqueue_thread, &sc->rapl_task, 0);
+ }
+
return (0);
}
void
intel_rapl_identify(driver_t *driver, device_t parent)
@@ -428,12 +409,24 @@ intel_rapl_probe(device_t dev)
}
static int
intel_rapl_attach(device_t dev)
{
- struct rapl_softc *sc;
- sc = device_get_softc(dev);
+ struct rapl_softc *const sc = device_get_softc(dev);
+
+ /*
+ * Only one device per package is needed (there is no per-core
+ * tuning/reporting).
+ *
+ * As mentioned in identify() above, this driver currently does not
+ * support multiple-packages. Actually, it currently behaves badly on
+ * a multi-package machine (as it does not force MSR reading/writing on
+ * a logical processor for a given package)!
+ */
+ if (device_get_unit(dev) != 0)
+ return (ENXIO);
+
sc->dev = dev;
bool found = false;
for(int i = 0; i < nitems(intel_rapl_lake_models); i++) {
@@ -453,11 +446,11 @@ intel_rapl_attach(device_t dev)
break;
}
}
if (!found)
- return ENXIO;
+ return (ENXIO);
device_printf(dev, "RAPL flags %b\n", sc->rapl_flags, RAPL_MSR_BITS);
struct sysctl_ctx_list *ctx;
struct sysctl_oid *tree_node;
struct sysctl_oid_list *tree;
@@ -477,42 +470,43 @@ intel_rapl_attach(device_t dev)
intel_rapl_read_freq_sysctl_handler, "A", "RAPL update frequency in Hz (max 1000Hz)");
SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "reason",
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
sc, 0,
- intel_rapl_reason_sysctl_handler, "A", "dump limit reason and log");
+ intel_rapl_reason_sysctl_handler, "A", "Limit reason and log");
SYSCTL_ADD_QUAD(ctx, tree, OID_AUTO, "pp0",
CTLFLAG_RD | CTLFLAG_MPSAFE,
&sc->last_reading.pp0, "Read Power Domain 0");
SYSCTL_ADD_QUAD(ctx, tree, OID_AUTO, "pp1",
CTLFLAG_RD | CTLFLAG_MPSAFE,
&sc->last_reading.pp1, "Read Power Domain 1");
SYSCTL_ADD_QUAD(ctx, tree, OID_AUTO, "platform",
CTLFLAG_RD | CTLFLAG_MPSAFE,
&sc->last_reading.platform, "Read Platform Power Domain");
SYSCTL_ADD_QUAD(ctx, tree, OID_AUTO, "dram",
CTLFLAG_RD | CTLFLAG_MPSAFE,
&sc->last_reading.dram, "Read DRAM Power Domain");
TIMEOUT_TASK_INIT(taskqueue_thread,
&sc->rapl_task, 0, rapl_reading_task, sc);
sc->running = true;
sc->read_frequency = 1;
- taskqueue_enqueue_timeout(taskqueue_thread, &sc->rapl_task,
- hz/sc->read_frequency);
+ /* Trigger an immediate read. */
+ taskqueue_enqueue_timeout(taskqueue_thread, &sc->rapl_task, 0);
return (0);
}
static int
intel_rapl_detach(device_t dev)
{
struct rapl_softc *sc = device_get_softc(dev);
sc->running = false;
+
taskqueue_drain_timeout(taskqueue_thread, &sc->rapl_task);
return (0);
}

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33613346
Default Alt Text
D56791-olce.patch (14 KB)

Event Timeline