Table of Contents
For power management, NetBSD supports sensor monitoring (including battery state, CPU temperature, and so on), CPU frequency adjustment, low-power mode for devices, hardware poweroff, and sleep (suspend-to-RAM) on some hardware.
Power management on NetBSD primarily takes the form of acpi(4) (Advanced Configuration and Power Interface) support, although sensors are also supported on many other types of non-ACPI hardware.
A NetBSD system with ACPI support can be physically powered off by running the poweroff(8) and reboot(8) commands, however, it is usually best to use shutdown(8) so the system shuts down with appropriate warning and has time to properly stop any running applications and services.
Shut the system down immediately:
#
shutdown -p now
Reboot with a 10 minute warning to any users:
#
shutdown -r +10
An ACPI system is always in one of any "sleep states":
fully running
power on suspend (CPU and hard disks are off)
similar to S3, usually not implemented
suspend-to-RAM ("sleep", most of the system is inactive to save power, but can quickly be brought back up)
suspend-to-disk ("hibernate", not currently supported on NetBSD)
powered off
The sleep state can be modified with sysctl(8), e.g. to suspend-to-RAM:
#
sysctl -w hw.acpi.sleep.state=3
The way the system wakes up is dependent on the hardware, and may include pressing the power button or lifting the lid. If supported, the system can resume from a suspended state much quicker than a full reboot.
If you've tested this and verified it works as expected, you may wish to trigger it automatically through a powerd(8) event, such as closing the lid of a laptop.
If your machine does not support full ACPI suspend and resume, it may still be possible to suspend and resume individual devices to save power while they are inactive. This can be accomplished with drvctl(8).
For example, /var/run/dmesg.boot
reports our hardware has a SD card reader, rtsx0
.
rtsx0 at pci1 dev 0 function 0: Realtek Semiconductor RTS5227 PCI-E Card Reader (rev. 0x01) rtsx0: interrupting at msi4 vec 0 sdmmc0 at rtsx0
We can suspend it:
#
drvctl -S rtsx0
And we can also resume it:
#
drvctl -R rtsx0
If a specific device is failing to suspend or resume, this can also be used for debugging.
Many modern machines allow the CPU frequency to be dynamically adjusted. A higher frequency provides better performance, but increased battery usage and generates more heat. On NetBSD, CPU frequency can be adjusted at runtime with sysctl(8).
For example, this machine is currently running at 1400 MHz, but also supports a 600 MHz low-power mode:
$
sysctl -a | grep freq
machdep.cpu.frequency.target = 1400 machdep.cpu.frequency.current = 1400 machdep.cpu.frequency.min = 600 machdep.cpu.frequency.max = 1400 machdep.cpu.frequency.available = 600 1400
We can enter the low power mode by setting the target frequency:
#
sysctl -w machdep.cpu.frequency.target=600
Many modern hardware supports an "automatic adjustment" frequency,
usually this will be a reported frequency that ends in 1.
On systems without this functionality,
sysutils/estd
can be installed from
pkgsrc to perform automatic adjustment depending on load in software,
although it will be less efficient than hardware scaling.
Some IEEE 802.11 (Wi-Fi) networking devices support a low power mode, which can be enabled with ifconfig(8):
#
ifconfig iwm0 powersave
You may notice an increase in reported latency from ping(8) and a decrease in performance. However, it may improve your device's battery life, as the radios in such devices can consume a lot of energy. It can be disabled again with ifconfig:
#
ifconfig iwm0 -powersave
The primary command-line frontend to NetBSD's sensor monitoring framework is envstat(8). Here is a typical example of envstat output:
$
envstat
Current CritMax WarnMax WarnMin CritMin Unit [acpiacad0] connected: FALSE [acpibat0] present: TRUE design voltage: 11.100 V voltage: 12.270 V design cap: 23.200 Wh last full cap: 16.940 Wh charge: 16.770 5.000% 1.181% Wh (99.00%) charge rate: N/A discharge rate: N/A charging: FALSE charge state: NORMAL [acpitz0] temperature: 48.000 128.000
acpiacad0
is the machine's AC adapter.
It is not currently connected.
acpibat0
is the machine's battery, currently 99%
full. At 5%, a warning will be printed to the console and an event
sent to powerd(8). At 1%, the system will shut down to prevent
data loss from loss of power.
A CPU temperature sensor is also detected, acpitz0
.
It indicates that the CPU's current temperature is 48 degrees Celsius,
and the critical temperature is 128 degrees Celsius.
If the critical temperature is reached, the system will shut down
to prevent damage to hardware.
powerd(8) can be notified of changes in temperature.
powerd(8) is a daemon that allows the system to respond to power management events, such as the AC adapter being unplugged, battery state changing, a laptop's lid being closed, or a "sleep" button being pressed.
As with other services, powerd can be enabled by editing
/etc/rc.conf
:
powerd=YES
And started with service(8):
#
service powerd start
powerd works by executing a named sh(1) script from the
directory /etc/powerd/scripts
whenever a power
event occurs.
We can use commands we learned in previous sections of this chapter
to our advantage in the scripts.
Example 11.1. /etc/powerd/scripts/lid_switch
#!/bin/sh - # # $NetBSD: chap-power.html,v 1.17 2021/12/14 17:15:55 snj Exp $ # # Generic script for lid switch events. # # Arguments passed by powerd(8): # # device event case "${2}" in pressed) # Lock the X11 display to prevent tampering DISPLAY=:0 /usr/pkg/bin/xlock -mode blank & # Wait for 1 second sleep 1 # Suspend /sbin/sysctl -w hw.acpi.sleep.state=3 exit 0 ;; released) exit 0 ;; *) logger -p warning "${0}: unsupported event ${2} on device ${1}" >&1 exit 1 esac
Example 11.2. /etc/powerd/scripts/acadapter
#!/bin/sh - # # $NetBSD: chap-power.html,v 1.17 2021/12/14 17:15:55 snj Exp $ # # Generic script for acadapter events. # # Arguments passed by powerd(8): # # device event case "${2}" in pressed) logger -p info "${0}: Full performance mode" >&1 # Disable power saving mode on all network interfaces. for intf in $(/sbin/ifconfig -l); do /sbin/ifconfig $intf -powersave >/dev/null 2>&1 done # Increase CPU frequency /sbin/sysctl -w machdep.cpu.frequency.target=2300 exit 0 ;; released) logger -p info "${0}: Power saving mode" >&1 # Enable power saving mode on all network interfaces. for intf in $(/sbin/ifconfig -l); do /sbin/ifconfig $intf powersave >/dev/null 2>&1 done # Reduce CPU frequency /sbin/sysctl -w machdep.cpu.frequency.target=1400 exit 0 ;; *) logger -p warning "${0}: unsupported event ${2} on device ${1}" >&1 exit 1 ;; esac