Page MenuHomeFreeBSD

D56791.id178377.diff
No OneTemporary

D56791.id178377.diff

diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -114,6 +114,9 @@
# CPU frequency control
device cpufreq
+# RAPL
+device rapl
+
# Bus support.
device acpi
device smbios
diff --git a/sys/conf/files.x86 b/sys/conf/files.x86
--- a/sys/conf/files.x86
+++ b/sys/conf/files.x86
@@ -361,6 +361,7 @@
x86/iommu/intel_qi.c optional acpi iommu pci
x86/iommu/intel_quirks.c optional acpi iommu pci
x86/iommu/intel_utils.c optional acpi iommu pci
+x86/power/intel_rapl.c optional rapl
x86/iommu/iommu_utils.c optional acpi iommu pci
x86/isa/atrtc.c standard
x86/isa/clock.c standard
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -176,6 +176,7 @@
imgact_binmisc \
${_imx} \
${_intelspi} \
+ ${_intel_rapl} \
${_io} \
${_ioat} \
${_ipoib} \
@@ -823,6 +824,7 @@
_ichwd= ichwd
_ida= ida
_intelspi= intelspi
+_intel_rapl= intel_rapl
_ips= ips
_isci= isci
_ipw= ipw
diff --git a/sys/modules/intel_rapl/Makefile b/sys/modules/intel_rapl/Makefile
new file mode 100644
--- /dev/null
+++ b/sys/modules/intel_rapl/Makefile
@@ -0,0 +1,4 @@
+.PATH: ${SRCTOP}/sys/x86/power
+KMOD= intel_rapl
+SRCS= intel_rapl.c bus_if.h device_if.h
+.include <bsd.kmod.mk>
diff --git a/sys/x86/power/intel_rapl.c b/sys/x86/power/intel_rapl.c
new file mode 100644
--- /dev/null
+++ b/sys/x86/power/intel_rapl.c
@@ -0,0 +1,536 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 The FreeBSD Foundation
+ *
+ * This file was written by Tom Jones (thj@freebsd.org) under sponsorship from
+ * The FreeBSD Foundation.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/sbuf.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/smp.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+#include <machine/cputypes.h>
+#include <machine/specialreg.h>
+
+extern uint64_t tsc_freq;
+
+struct rapl_reading {
+ uint64_t pp0;
+ uint64_t pp1;
+ uint64_t platform;
+ uint64_t dram;
+};
+
+struct rapl_softc {
+ device_t dev;
+ uint32_t rapl_flags;
+ uint32_t model;
+
+ struct timeout_task rapl_task;
+ bool running;
+
+ 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;
+ int read_frequency;
+};
+
+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 *);
+
+#define INTEL_MODEL_ATOM_C2000 0x4D
+
+#define INTEL_MODEL_SKY_LAKE 0x4E
+#define INTEL_MODEL_SKY_LAKE_2 0x5E
+#define INTEL_MODEL_SKYCOPPER 0x55
+#define INTEL_MODEL_XEON_E 0x8E
+#define INTEL_MODEL_XEON_E_2 0x9E
+#define INTEL_MODEL_CANNON_LAKE 0x66
+#define INTEL_MODEL_COMET_LAKE 0xA5
+#define INTEL_MODEL_COMET_LAKE_2 0xA6
+#define INTEL_MODEL_TIGER_LAKE 0x8C
+#define INTEL_MODEL_TIGER_LAKE_2 0x8D
+#define INTEL_MODEL_ICE_LAKE 0x7E
+#define INTEL_MODEL_ICE_LAKE_2 0x6A
+#define INTEL_MODEL_ICE_LAKE_3 0x6C
+#define INTEL_MODEL_ALDER_LAKE 0x97
+#define INTEL_MODEL_ALDER_LAKE_2 0x9A
+#define INTEL_MODEL_RAPTOR_LAKE 0xBA
+#define INTEL_MODEL_RAPTOR_LAKE_2 0xB7
+#define INTEL_MODEL_RAPTOR_LAKE_3 0xBF
+#define INTEL_MODEL_SAPPHIRE_RAPIDS 0x8F
+#define INTEL_MODEL_EMERALD_RAPIDS 0xCF
+#define INTEL_MODEL_METEOR_LAKE 0xAA
+#define INTEL_MODEL_GRANITE_RAPIDS 0xAD
+#define INTEL_MODEL_GRANITE_RAPIDS_2 0xAE
+#define INTEL_MODEL_SIERRA_FOREST 0xAF
+#define INTEL_MODEL_LUNAR_LAKE 0xBD
+
+/*
+ * The Intel SDM doesn't provide an easy way to know which models will support
+ * RAPL or which features are supported. Intel Architectures SDM: Volume 4
+ * Chapter 2.17 says that the following models should all support a common set
+ * of MSRs.
+ *
+ * It is possible to lock out the use of some RAPL MSRs, so even with
+ * documented support they may read as 0 or default values.
+ *
+ */
+uint8_t intel_rapl_lake_models[] = {
+ INTEL_MODEL_SKY_LAKE,
+ INTEL_MODEL_SKY_LAKE_2,
+ INTEL_MODEL_SKYCOPPER,
+ INTEL_MODEL_XEON_E,
+ INTEL_MODEL_XEON_E_2,
+ INTEL_MODEL_CANNON_LAKE,
+ INTEL_MODEL_COMET_LAKE,
+ INTEL_MODEL_COMET_LAKE_2,
+ INTEL_MODEL_ICE_LAKE,
+ INTEL_MODEL_TIGER_LAKE,
+ INTEL_MODEL_TIGER_LAKE_2,
+ INTEL_MODEL_ICE_LAKE,
+ INTEL_MODEL_ICE_LAKE_2 ,
+ INTEL_MODEL_ALDER_LAKE,
+ INTEL_MODEL_ALDER_LAKE_2,
+ INTEL_MODEL_RAPTOR_LAKE,
+ INTEL_MODEL_RAPTOR_LAKE_2,
+ INTEL_MODEL_RAPTOR_LAKE_3,
+ INTEL_MODEL_SAPPHIRE_RAPIDS,
+ INTEL_MODEL_EMERALD_RAPIDS,
+ INTEL_MODEL_METEOR_LAKE,
+ INTEL_MODEL_GRANITE_RAPIDS,
+ INTEL_MODEL_GRANITE_RAPIDS_2,
+ INTEL_MODEL_SIERRA_FOREST,
+ INTEL_MODEL_LUNAR_LAKE,
+};
+
+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 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_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 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_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"
+
+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);
+}
+
+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);
+
+ 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).
+ *
+ */
+ 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) {
+ rdmsr_safe(MSR_PP0_ENERGY_STATUS, &value);
+ r->pp0 = (value & 0x00000000FFFFFFFF) * sc->esu;
+ }
+ if (sc->rapl_flags & RAPL_F_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) {
+ rdmsr_safe(MSR_PLATFORM_ENERGY_COUNTER, &value);
+ r->platform = (value & 0x00000000FFFFFFFF) * sc->esu;
+ }
+ if (sc->rapl_flags & RAPL_F_CORE_PERF_LIMIT_REASONS) {
+ rdmsr_safe(MSR_CORE_PERF_LIMIT_REASONS, &value);
+ }
+ if (sc->rapl_flags & RAPL_F_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) {
+ rdmsr_safe(MSR_DRAM_ENERGY_STATUS, &value);
+ r->dram = (value & 0x00000000FFFFFFFF) * sc->dram_esu;
+ }
+}
+
+static int
+intel_rapl_dump_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+ struct rapl_softc *sc;
+ uint64_t value = 0;
+ struct sbuf *sb;
+ int ret;
+
+ sc = (struct rapl_softc *)arg1;
+
+ sb = sbuf_new_auto();
+
+ sbuf_printf(sb, "\n");
+
+ take_reading(sc, &sc->last_reading);
+
+ if (sc->rapl_flags & RAPL_F_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) {
+ 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) {
+ 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) {
+ 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) {
+ 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;
+
+ sc = (struct rapl_softc *)arg1;
+ if (sc->rapl_flags & RAPL_F_CORE_PERF_LIMIT_REASONS) {
+ rdmsr_safe(MSR_CORE_PERF_LIMIT_REASONS, &value);
+
+ sb = sbuf_new_auto();
+
+ bool log = false;
+ if (value & 0x00000000FFFF0000)
+ log = true;
+ sbuf_printf(sb, "%b\n", (int)value, RAPL_MSR_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;
+}
+
+static int
+intel_rapl_read_freq_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+ int err, val;
+ val = 1;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+
+ if(val == 0 || val > 1000)
+ return (EINVAL);
+
+ return (0);
+}
+
+void
+intel_rapl_identify(driver_t *driver, device_t parent)
+{
+
+ /* XXX: rapl doesn't support multi socket right now */
+ if (devclass_get_device(devclass_find("intel_rapl"), 0))
+ return;
+
+ if (device_find_child(parent, "intel_rapl", DEVICE_UNIT_ANY) != NULL)
+ return;
+
+ if (cpu_vendor_id != CPU_VENDOR_INTEL)
+ return;
+
+ if (resource_disabled("intel_rapl", 0))
+ return;
+
+ for(int i = 0; i < nitems(intel_rapl_lake_models); i++) {
+ if (intel_rapl_lake_models[i] == CPUID_TO_MODEL(cpu_id)) {
+ if (BUS_ADD_CHILD(parent, 10, "intel_rapl",
+ device_get_unit(parent)) == NULL)
+ device_printf(parent,"rapl_intel: add child failed\n");
+ return;
+ }
+ }
+
+ for(int i = 0; i < nitems(intel_rapl_atom_models); i++) {
+ if (intel_rapl_atom_models[i] == CPUID_TO_MODEL(cpu_id)) {
+ if (BUS_ADD_CHILD(parent, 10, "intel_rapl",
+ device_get_unit(parent)) == NULL)
+ device_printf(parent,"rapl_intel: add child failed\n");
+ return;
+ }
+ }
+}
+
+static int
+intel_rapl_probe(device_t dev)
+{
+ device_set_desc(dev, "Intel RAPL (Running Average Power Limit)");
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+intel_rapl_attach(device_t dev)
+{
+ struct rapl_softc *sc;
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ bool found = false;
+
+ for(int i = 0; i < nitems(intel_rapl_lake_models); i++) {
+ if (intel_rapl_lake_models[i] == CPUID_TO_MODEL(cpu_id)) {
+ sc->model = intel_rapl_lake_models[i];
+ sc->rapl_flags = INTEL_RAPL_LAKE_FLAGS;
+ found = true;
+ break;
+ }
+ }
+
+ for(int i = 0; i < nitems(intel_rapl_atom_models); i++) {
+ if (intel_rapl_atom_models[i] == CPUID_TO_MODEL(cpu_id)) {
+ sc->model = intel_rapl_atom_models[i];
+ sc->rapl_flags = INTEL_RAPL_ATOM_FLAGS;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ 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;
+
+ ctx = device_get_sysctl_ctx(sc->dev);
+ tree_node = device_get_sysctl_tree(sc->dev);
+ tree = SYSCTL_CHILDREN(tree_node);
+
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "dump",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ sc, 0,
+ intel_rapl_dump_sysctl_handler, "A", "dump raw rapl values");
+
+ SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "read_frequency",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+ sc, 0,
+ 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");
+
+ 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);
+
+ 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);
+}
+
+static device_method_t rapl_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, intel_rapl_identify),
+ DEVMETHOD(device_probe, intel_rapl_probe),
+ DEVMETHOD(device_attach, intel_rapl_attach),
+ DEVMETHOD(device_detach, intel_rapl_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t rapl_intel_driver = {
+ "intel_rapl",
+ rapl_methods,
+ sizeof(struct rapl_softc),
+};
+
+DRIVER_MODULE(rapl_intel, cpu, rapl_intel_driver, NULL, NULL);
+MODULE_VERSION(rapl_intel, 1);

File Metadata

Mime Type
text/plain
Expires
Sun, Aug 30, 10:40 AM (56 m, 27 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37591937
Default Alt Text
D56791.id178377.diff (16 KB)

Event Timeline