Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168648461
D56791.id178377.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D56791.id178377.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D56791: Add intel_rapl driver
Attached
Detach File
Event Timeline
Log In to Comment