CPUFREQ(4)
๐ฆ CPUFREQ(4) โ like, the CPU frequency control framework, bestie ๐ฆ
Okay so this is the cpufreq page from section 4 of the Kernel Interfaces Manual, and honestly? It's giving "let me introduce you to the friend group that runs your CPU's clock" ๐
Stick with me, it's all gonna make sense.
โจ NAME โจ
cpufreq โ the CPU frequency control framework. That's the whole vibe. ๐
๐ธ SYNOPSIS ๐ธ
device cpufreq
#include <sys/cpu.h>
int
cpufreq_levels(device_t dev, struct cf_level *levels, int *count);
int
cpufreq_set(device_t dev, const struct cf_level *level, int priority);
int
cpufreq_get(device_t dev, struct cf_level *level);
int
cpufreq_drv_settings(device_t dev, struct cf_setting *sets, int *count);
int
cpufreq_drv_type(device_t dev, int *type);
int
cpufreq_drv_set(device_t dev, const struct cf_setting *set);
int
cpufreq_drv_get(device_t dev, struct cf_setting *set);
๐ DESCRIPTION ๐
The cpufreq driver is literally the ultimate group-chat admin for CPU frequency control drivers โ it gives you one unified kernel and user interface to all of them. ๐ซถ It takes multiple drivers that each offer different settings and smushes them into a single interface of all possible levels. Iconic behavior, no cap.
You can hit this interface directly via sysctl(8), or you can just tell /etc/rc.d/power_profile that it should switch settings whenever the AC line state changes โ you do that through rc.conf(5). Set it and forget it, fr fr. โจ
๐ SYSCTL VARIABLES ๐
Heads up bestie: these settings may be overridden by kernel drivers requesting alternate settings. If that happens, the original values get restored once the condition has passed (think: the system has cooled sufficiently ๐ฎโ๐จ). And if a sysctl can't be set because of an override condition, it returns EPERM. Rude, but okay.
โ ๏ธ Big warning time โ ๏ธ The frequency cannot be changed if TSC is in use as the timecounter and the hardware does not support invariant TSC. Why? Because the timecounter system needs a source with a constant rate โ that's just the rules. (On invariant TSC hardware, the TSC runs at the P0 rate regardless of the configured P-state, so it's fine.) Modern hardware mostly has invariant TSC, so this is usually a non-issue. You can change the timecounter source with thekern.timecounter.hardwaresysctl, and the available modes live in thekern.timecounter.choicesysctl entry. ๐
dev.cpu.%d.freqโ the current active CPU frequency, in MHz. Live and in color. ๐ฅdev.cpu.%d.freq_driverโ the specific cpufreq driver that this cpu is using. Main character reveal.dev.cpu.%d.freq_levelsโ the currently available levels for the CPU, as frequency/power usage. Values are in units of MHz and milliwatts. โญdev.DEVICE.%d.freq_settingsโ the currently available settings for the driver, also frequency/power usage, also MHz and milliwatts. This one is lowkey a debugging hero โ it's helpful for understanding which settings are offered by which driver. ๐debug.cpufreq.lowestโ the lowest CPU frequency in MHz to offer to users. Also accessible via a tunable with the same name. Use it to disable very low levels that may be unusable on some systems. ๐debug.cpufreq.verboseโ prints verbose messages. Also accessible via a tunable with the same name. For the girlies who need the lore. ๐debug.hwpstate_pstate_limitโ if enabled, the AMD hwpstate driver limits administrative control of P-states (including bypowerd(8)) to the value in the0xc0010061MSR, known as"PStateCurLim[CurPstateLimit]."It is disabled (0) by default. On some hardware, the limit register seems to simply follow the configured P-state, which results in the inability to ever raise the P-state back to P0 from a reduced frequency state. ๐ญ So like, tread carefully.
๐ฆ SUPPORTED DRIVERS ๐ฆ
Okay so these drivers below offer absolute frequency control via the cpufreq interface. Usually only one of these can be active at a time, so it's giving "there can only be one" energy:
acpi_perfโ ACPI CPU performance statesest(4)โ Intel Enhanced SpeedStephwpstateโ AMD Cool'n'Quiet2 used in K10 through Family 17hhwpstate_intel(4)โ Intel SpeedShift driverichssโ Intel SpeedStep for ICHpowernowโ AMD PowerNow! and Cool'n'Quiet for K7 and K8smistโ Intel SMI-based SpeedStep for PIIX4
And these next ones are a different story โ they offer relative frequency control and have an additive effect. Teamwork makes the dream work ๐ซถ:
acpi_throttleโ ACPI CPU throttlingp4tccโ Pentium 4 Thermal Control Circuitry
๐ KERNEL INTERFACE ๐
Kernel components can query and set CPU frequencies through the cpufreq kernel interface. The whole little routine goes like this:
- Obtain a cpufreq device.
- Call
cpufreq_levels()to get the currently available frequency levels. - Check the current level with
cpufreq_get(). - Set a new one from the list with
cpufreq_set().
Each level may actually reference more than one cpufreq driver, but kernel components do not need to be aware of this โ don't worry about it bestie, it's handled. ๐
The total_set element of struct cf_level gives you a summary of the frequency and power for that level. Unknown or irrelevant values are set to CPUFREQ_VAL_UNKNOWN.
cpufreq_levels()โ takes a cpufreq device and an empty array of levels. Thecountvalue should be set to the number of levels available, and after the function completes it will be set to the actual number of levels returned. If there are more levels thancountwill allow, it should returnE2BIG. ๐คcpufreq_get()โ takes a pointer to space to store a level. After successful completion, the output will be the current active level, and it's equal to one of the levels returned bycpufreq_levels(). Matching set, slay. โจcpufreq_set()โ takes a pointer to a level and attempts to activate it. Thepriority(i.e.,CPUFREQ_PRIO_KERN) tells cpufreq whether to override previous settings while activating this level. Ifpriorityis higher than the current active level, that level gets saved and overridden with the new level. If a level is already saved, the new level is set without overwriting the older saved level. Ifcpufreq_set()is called with aNULLlevel, the saved level gets restored. If there is no saved level,cpufreq_set()returnsENXIO. And ifpriorityis lower than the current active level's priority, this method returnsEPERM. Know your rank, babe. ๐
๐ DRIVER INTERFACE ๐
Kernel drivers that offer hardware-specific CPU frequency control export their individual settings through the cpufreq driver interface. That means implementing these methods:
cpufreq_drv_settings()cpufreq_drv_type()cpufreq_drv_set()cpufreq_drv_get()
Plus, the driver must attach a device as a child of a CPU device so that these methods can be called by the cpufreq framework. No shortcuts, bestie. ๐ซถ
๐ธ cpufreq_drv_settings()
Returns an array of currently available settings, each of type struct cf_setting. The driver should set unknown or irrelevant values to CPUFREQ_VAL_UNKNOWN. All of the following elements for each setting should be returned:
struct cf_setting {
int freq; /* CPU clock in MHz or 100ths of a percent. */
int volts; /* Voltage in mV. */
int power; /* Power consumed in mW. */
int lat; /* Transition latency in us. */
device_t dev; /* Driver providing this setting. */
};
On entry to this method, count contains the number of settings that can be returned. On successful completion, the driver sets it to the actual number of settings returned. If the driver offers more settings than count will allow, it should return E2BIG. ๐
๐ฆ cpufreq_drv_type()
Indicates the type of settings it offers โ either CPUFREQ_TYPE_ABSOLUTE or CPUFREQ_TYPE_RELATIVE. Additionally, the driver may set the CPUFREQ_FLAG_INFO_ONLY flag if the settings it provides are information for other drivers only and cannot be passed to cpufreq_drv_set() to activate them. Look, don't touch. ๐
๐ cpufreq_drv_set()
Takes a driver setting and makes it active. If the setting is invalid or not currently available, it should return EINVAL. Periodt.
๐ cpufreq_drv_get()
Returns the currently-active driver setting. The struct cf_setting returned must be valid for passing to cpufreq_drv_set(), including all elements being filled out correctly. If the driver cannot infer the current setting (even by estimating it with cpu_est_clockrate()), then it should set all elements to CPUFREQ_VAL_UNKNOWN. Honesty is the policy. โจ
๐ SEE ALSO ๐
acpi(4), est(4), timecounters(4), powerd(8), sysctl(8)
๐ซถ AUTHORS ๐ซถ
Nate Lawson โ the originator, respect on the name. ๐
Bruno Ducrot โ contributed the powernow driver. Legend behavior. ๐ฅ
๐ BUGS ๐
- The following drivers have not yet been converted to the cpufreq interface:
longrun(4). It's giving "still in the group chat but never replies." ๐ญ - Notification of CPU and bus frequency changes is not implemented yet. Coming soon-ish. ๐
- When multiple CPUs offer frequency control, they cannot be set to different levels โ they must all offer the same frequency settings. Everyone matches, or nobody does. ๐
โจ and that's the whole page, bestie โ go forth and clock those CPUs โจ
๐ sign-off time: this was the CPUFREQ(4) page, source/version Debian, dated April 4, 2022 โ mwah, love u, bye ๐๐
๐ฆ where this page comes from
- freebsd 14.5: base 14.5
- freebsd 15.1: base 15.1
- nixpkgs unstable: source
- Copyright (c) 2005 Nate Lawson
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms