Skip to content
FreeBSDDeep Dive Published Updated 7 min readViews unavailable

FreeBSD CPU Power Management: Driver-Aware Frequency Tuning in Production

Diagnose FreeBSD CPU frequency drivers, choose safe powerd or hardware-managed policies, and verify performance, thermals, and AC/battery behavior.

FreeBSD power tuning is not a single switch. Firmware and the processor expose performance and idle states; a kernel driver decides which controls are available; and a userland policy may request changes in response to load or AC power. The same powerd setting can be useful on one machine and ineffective on another because the active driver determines which layer actually owns frequency selection.

Treat power management as a measured control loop. Identify the active driver and available sysctls first, change one policy at a time, and verify behavior on the actual workload. A lower reported frequency is not proof of lower wall power, better thermals, or an acceptable service latency. The right configuration depends on hardware support, firmware, FreeBSD release, cooling, and whether the host is a server, laptop, or virtual machine.

Separate performance states from idle states

CPU frequency and CPU idle states solve related but different problems. Performance states (often called P-states) alter the requested performance level while a CPU is doing work. Idle states (C-states) let an idle CPU use less energy. FreeBSD exposes information about both through CPU sysctls when the platform and driver provide it. A frequency policy does not configure every device’s power state, and it does not replace ACPI suspend/resume testing.

The cpufreq(4) framework presents controls from one or more frequency drivers. Depending on the processor, the underlying driver may expose discrete levels, a hardware-managed policy, or only limited information. Examples include Intel Enhanced SpeedStep (est(4)) and Intel Speed Shift (hwpstate_intel(4)). The driver is not a generic promise that every advertised level is available on every core at every instant: firmware, thermal limits, and hardware policy can override a request.

powerd(8) is a userland policy daemon. It monitors load and, where supported, AC or battery state, then requests a frequency policy. The /etc/rc.d/power_profile mechanism is a separate AC-state policy path. Do not configure both to compete for the same controls. The FreeBSD manual specifically warns that powerd and power_profile may override one another.

Record the baseline before changing policy

Capture the software and hardware context so a later comparison is meaningful:

freebsd-version -kru
uname -m
sysctl dev.cpu.0.freq_driver dev.cpu.0.freq_levels dev.cpu.0.freq
sysctl dev.cpu.0.cx_supported dev.cpu.0.cx_lowest
sysctl dev.hwpstate_intel.0.epp 2>/dev/null
dmesg | egrep -i 'cpu|cpufreq|hwpstate|speedstep|acpi|thermal'

Some sysctls do not exist on a particular architecture or CPU. A missing hwpstate_intel node means that this Intel-specific driver interface is not exposed; it is not a reason to load or force an unrelated module. The freq_driver, freq_levels, and current freq values provide evidence about what the CPU-frequency framework reports. cx_supported and cx_lowest concern idle states, not frequency scaling.

Keep a timestamped baseline under a representative idle period and under a repeatable CPU-bound workload. Sample more than CPU 0 on systems where per-core behavior matters. Record workload throughput or response time, temperature when supported, fan or BMC readings, battery discharge rate for laptops, and actual wall or rack power when the decision is about energy cost. Do not interpret the power figure in freq_levels as a calibrated measurement of whole-system watts; some hardware reports -1 or only an estimate.

Before changing anything, inspect existing policy and service state:

sysrc -n powerd_enable 2>/dev/null
sysrc -n powerd_flags 2>/dev/null
service powerd status
grep -n 'performance_\|economy_' /etc/rc.conf /etc/rc.conf.local 2>/dev/null

sysrc reports configured values, not necessarily the running hardware policy. A service can be enabled but unable to control the active driver, and a configured value may be overridden by another startup script. Preserve the output and the original configuration so rollback does not depend on memory.

Choose policy by the active driver

On a CPU using a driver that is compatible with powerd, choose modes according to the service objective. FreeBSD supports adaptive, hiadaptive, minimum, and maximum modes. adaptive is intended to reduce performance while a system appears idle and increase it when busy; hiadaptive responds more aggressively to preserve performance and interactivity. AC and battery modes can be set independently.

For example, after confirming that powerd is appropriate for this system, an operator might use a conservative battery policy while retaining a more responsive AC policy:

sysrc powerd_enable="YES"
sysrc powerd_flags="-a hiadaptive -b adaptive"
service powerd start
service powerd status

This is a policy example, not a universal recommendation. The -a and -b flags select behavior on AC and battery, respectively. powerd also offers load thresholds and frequency bounds, but set those only after establishing what the active driver supports. A lower minimum may reduce energy under light load while increasing completion time; a cap can violate a latency objective even if it lowers peak frequency.

Intel Speed Shift needs special care. On supported Intel CPUs, hwpstate_intel(4) gives hardware control over performance states. Current FreeBSD documentation notes that this driver supersedes the behavior users may expect from powerd or the Ports powerdxx utility. Check dev.cpu.%d.freq_driver and the driver’s own sysctls before applying a polling-daemon recipe. In particular, dev.hwpstate_intel.%d.epp, when present, is an energy/performance preference hint in the range 0 to 100, not a fixed clock setting: lower values favor performance and higher values favor energy efficiency. The processor still chooses actual operating points.

Test a supported EPP adjustment at runtime before making it persistent:

sysctl dev.hwpstate_intel.0.epp
sysctl dev.hwpstate_intel.0.epp=60

Use the exact device instance exposed by the host. If the write is rejected, the sysctl is absent, or measured behavior does not improve, revert the change. Do not copy that Intel-specific key into a fleet-wide sysctl.conf; hardware without the driver will not have the same interface.

Keep boot configuration and runtime control distinct

Put a service policy in rc.conf only when it is meant to persist across reboots. Use sysrc for service variables and confirm the service’s own manual for accepted flags. A runtime sysctl experiment disappears at reboot unless it is deliberately persisted. Before adding a sysctl to /etc/sysctl.conf, prove that the key exists on every target class, is writable in its current state, and is not controlled by firmware or an active driver.

Do not copy a dev.cpu.N.cx_lowest value from another machine as a power optimization. It selects an idle-state boundary and can affect interrupt or wake latency. Latency-sensitive storage, audio, or network workloads may react differently from a laptop workload. Likewise, performance_cx_lowest and economy_cx_lowest profile variables interact with the power-profile path; they are not substitutes for knowing which frequency driver is active.

For an Intel Speed Shift system, review the installed release’s hwpstate_intel(4) manual before disabling or replacing the driver. Its loader tunable exists specifically to disable that driver so another compatible driver can manage the CPU. Disabling it without a tested replacement can remove the active control path instead of “unlocking” performance. Never put an unverified driver override into a remote-only machine’s loader configuration without console or boot-environment recovery.

Validate under load, transition, and rollback

Use the same workload and observation interval before and after each change. Check that a short burst still meets latency goals, sustained CPU work does not throttle unexpectedly, and idle draw changes in the intended direction. Test the AC-to-battery transition and the reverse transition on actual laptop hardware. On a server, check the BMC or power meter rather than inferring whole-system energy from one CPU sysctl.

Useful evidence includes:

sysctl dev.cpu.0.freq_driver dev.cpu.0.freq_levels dev.cpu.0.freq
sysctl dev.cpu.0.cx_usage dev.cpu.0.cx_lowest
sysctl dev.hwpstate_intel.0.epp 2>/dev/null
service powerd status
tail -n 50 /var/log/messages

Repeat the sample across multiple cores and time windows; an instantaneous frequency is only a snapshot. Confirm the workload’s throughput or request latency, temperature or throttle indicators, battery discharge, and measured power. If powerd is used, a controlled foreground test with its verbose mode can help explain policy transitions, but do not leave a second foreground daemon running beside the rc-managed service.

Rollback should be straightforward. Stop and disable powerd if the test worsens the service objective, restore the prior powerd_flags, remove only the tested sysctl override, and reboot only if a loader-time change requires it. Retest after rollback. Keep separate profiles for genuinely different hardware classes rather than distributing a successful laptop setting to server CPUs with different driver semantics.

FreeBSD power tuning is successful when the intended policy is active, the workload still meets its service-level objective, and measured energy or thermal behavior improves without a hidden controller conflict. A sysctl value in a file proves intent; only an observed, repeatable test proves effect.

Related:

Sources:

Comments