It is important to utilize hardware resources in an efficient manner. Power and resource management allows the operating system to monitor system limits and to possibly provide an alert if the system temperature increases unexpectedly. An early specification for providing power management was the Advanced Power Management (APM) facility. APM controls the power usage of a system based on its activity. However, it was difficult and inflexible for operating systems to manage the power usage and thermal properties of a system. The hardware was managed by the BIOS and the user had limited configurability and visibility into the power management settings. The APM BIOS is supplied by the vendor and is specific to the hardware platform. An APM driver in the operating system mediates access to the APM Software Interface, which allows management of power levels.
There are four major problems in APM. First, power management is done by the vendor-specific BIOS, separate from the operating system. For example, the user can set idle-time values for a hard drive in the APM BIOS so that, when exceeded, the BIOS spins down the hard drive without the consent of the operating system. Second, the APM logic is embedded in the BIOS, and it operates outside the scope of the operating system. This means that users can only fix problems in the APM BIOS by flashing a new one into the ROM, which is a dangerous procedure with the potential to leave the system in an unrecoverable state if it fails. Third, APM is a vendor-specific technology, meaning that there is a lot of duplication of efforts and bugs found in one vendor's BIOS may not be solved in others. Lastly, the APM BIOS did not have enough room to implement a sophisticated power policy or one that can adapt well to the purpose of the machine.
The Plug and Play BIOS (PNPBIOS) was unreliable in many situations. PNPBIOS is 16-bit technology, so the operating system has to use 16-bit emulation in order to interface with PNPBIOS methods. FreeBSD provides an APM driver as APM should still be used for systems manufactured at or before the year 2000. The driver is documented in apm(4).
The successor to APM is the Advanced Configuration and Power Interface (ACPI). ACPI is a standard written by an alliance of vendors to provide an interface for hardware resources and power management. It is a key element in Operating System-directed configuration and Power Management as it provides more control and flexibility to the operating system.
This chapter demonstrates how to configure ACPI on FreeBSD. It then offers some tips on how to debug ACPI and how to submit a problem report containing debugging information so that developers can diagnosis and fix ACPI issues.
In FreeBSD the acpi(4) driver is loaded by default at
	system boot and should not be compiled
	into the kernel.  This driver cannot be unloaded after boot
	because the system bus uses it for various hardware
	interactions.  However, if the system is experiencing
	problems, ACPI can be disabled altogether
	by rebooting after setting
	hint.acpi.0.disabled="1" in
	/boot/loader.conf or by setting this
	variable at the loader prompt, as described in Section 12.2.3, “Stage Three”.
ACPI and APM cannot coexist and should be used separately. The last one to load will terminate if the driver notices the other is running.
ACPI can be used to put the system into
	a sleep mode with acpiconf, the
	-s flag, and a number from
	1 to 5.  Most users only
	need 1 (quick suspend to
	RAM) or 3 (suspend to
	RAM).  Option 5 performs
	a soft-off which is the same as running
	halt -p.
Other options are available using
	sysctl.  Refer to acpi(4) and
	acpiconf(8) for more information.
ACPI is present in all modern computers that conform to the ia32 (x86) and amd64 (AMD) architectures. The full standard has many features including CPU performance management, power planes control, thermal zones, various battery systems, embedded controllers, and bus enumeration. Most systems implement less than the full standard. For instance, a desktop system usually only implements bus enumeration while a laptop might have cooling and battery management support as well. Laptops also have suspend and resume, with their own associated complexity.
An ACPI-compliant system has various components. The BIOS and chipset vendors provide various fixed tables, such as FADT, in memory that specify things like the APIC map (used for SMP), config registers, and simple configuration values. Additionally, a bytecode table, the Differentiated System Description Table DSDT, specifies a tree-like name space of devices and methods.
The ACPI driver must parse the fixed
	tables, implement an interpreter for the bytecode, and modify
	device drivers and the kernel to accept information from the
	ACPI subsystem.  For FreeBSD, Intel® has
	provided an interpreter (ACPI-CA) that is
	shared with Linux® and NetBSD.  The path to the
	ACPI-CA source code is
	src/sys/contrib/dev/acpica.  The glue
	code that allows ACPI-CA to work on FreeBSD is
	in src/sys/dev/acpica/Osd.  Finally,
	drivers that implement various ACPI devices
	are found in src/sys/dev/acpica.
For ACPI to work correctly, all the parts have to work correctly. Here are some common problems, in order of frequency of appearance, and some possible workarounds or fixes. If a fix does not resolve the issue, refer to Section 11.13.4, “Getting and Submitting Debugging Info” for instructions on how to submit a bug report.
In some cases, resuming from a suspend operation will
	  cause the mouse to fail.  A known work around is to add
	  hint.psm.0.flags="0x3000" to
	  /boot/loader.conf.
ACPI has three suspend to
	  RAM (STR) states,
	  S1-S3, and one suspend
	  to disk state (STD), called
	  S4.  STD can be
	  implemented in two separate ways.  The
	  S4BIOS is a
	  BIOS-assisted suspend to disk and
	  S4OS is implemented
	  entirely by the operating system.  The normal state the
	  system is in when plugged in but not powered up is
	  “soft off” (S5).
Use sysctl hw.acpi to check for the
	  suspend-related items.  These example results are from a
	  Thinkpad:
hw.acpi.supported_sleep_state: S3 S4 S5 hw.acpi.s4bios: 0
Use acpiconf -s to test
	  S3, S4, and
	  S5.  An s4bios of one
	  (1) indicates
	  S4BIOS support instead
	  of S4 operating system support.
When testing suspend/resume, start with
	  S1, if supported.  This state is most
	  likely to work since it does not require much driver
	  support.  No one has implemented S2,
	  which is similar to S1.  Next, try
	  S3.  This is the deepest
	  STR state and requires a lot of driver
	  support to properly reinitialize the hardware.
A common problem with suspend/resume is that many device drivers do not save, restore, or reinitialize their firmware, registers, or device memory properly. As a first attempt at debugging the problem, try:
#sysctl debug.bootverbose=1#sysctl debug.acpi.suspend_bounce=1#acpiconf -s 3
This test emulates the suspend/resume cycle of all
	  device drivers without actually going into
	  S3 state.  In some cases, problems such
	  as losing firmware state, device watchdog time out, and
	  retrying forever, can be captured with this method.  Note
	  that the system will not really enter S3
	  state, which means devices may not lose power, and many
	  will work fine even if suspend/resume methods are totally
	  missing, unlike real S3 state.
Harder cases require additional hardware, such as a serial port and cable for debugging through a serial console, a Firewire port and cable for using dcons(4), and kernel debugging skills.
To help isolate the problem, unload as many drivers as
	  possible.  If it works, narrow down which driver is the
	  problem by loading drivers until it fails again.  Typically,
	  binary drivers like nvidia.ko, display
	  drivers, and USB will have the most
	  problems while Ethernet interfaces usually work fine.  If
	  drivers can be properly loaded and unloaded, automate this
	  by putting the appropriate commands in
	  /etc/rc.suspend and
	  /etc/rc.resume.  Try setting
	  hw.acpi.reset_video to 1
	  if the display is messed up after resume.  Try setting
	  longer or shorter values for
	  hw.acpi.sleep_delay to see if that
	  helps.
Try loading a recent Linux® distribution to see if suspend/resume works on the same hardware. If it works on Linux®, it is likely a FreeBSD driver problem. Narrowing down which driver causes the problem will assist developers in fixing the problem. Since the ACPI maintainers rarely maintain other drivers, such as sound or ATA, any driver problems should also be posted to the freebsd-current list and mailed to the driver maintainer. Advanced users can include debugging printf(3)s in a problematic driver to track down where in its resume function it hangs.
Finally, try disabling ACPI and enabling APM instead. If suspend/resume works with APM, stick with APM, especially on older hardware (pre-2000). It took vendors a while to get ACPI support correct and older hardware is more likely to have BIOS problems with ACPI.
Most system hangs are a result of lost interrupts or an interrupt storm. Chipsets may have problems based on boot, how the BIOS configures interrupts before correctness of the APIC (MADT) table, and routing of the System Control Interrupt (SCI).
Interrupt storms can be distinguished from lost
	  interrupts by checking the output of
	  vmstat -i and looking at the line that
	  has acpi0.  If the counter is increasing
	  at more than a couple per second, there is an interrupt
	  storm.  If the system appears hung, try breaking to
	  DDB (CTRL+ALT+ESC on console) and type
	  show interrupts.
When dealing with interrupt problems, try disabling
	  APIC support with
	  hint.apic.0.disabled="1" in
	  /boot/loader.conf.
Panics are relatively rare for ACPI
	  and are the top priority to be fixed.  The first step is to
	  isolate the steps to reproduce the panic, if possible, and
	  get a backtrace.  Follow the advice for enabling
	  options DDB and setting up a serial
	  console in Section 26.6.4, “Entering the DDB Debugger from the Serial Line” or setting
	  up a dump partition.  To get a backtrace in
	  DDB, use tr.  When
	  handwriting the backtrace, get at least the last five and
	  the top five lines in the trace.
Then, try to isolate the problem by booting with
	  ACPI disabled.  If that works, isolate
	  the ACPI subsystem by using various
	  values of debug.acpi.disable.  See
	  acpi(4) for some examples.
First, try setting
	  hw.acpi.disable_on_poweroff="0" in
	  /boot/loader.conf.  This keeps
	  ACPI from disabling various events during
	  the shutdown process.  Some systems need this value set to
	  1 (the default) for the same reason.
	  This usually fixes the problem of a system powering up
	  spontaneously after a suspend or poweroff.
Some BIOS vendors provide incorrect or buggy bytecode. This is usually manifested by kernel console messages like this:
ACPI-1287: *** Error: Method execution failed [\\_SB_.PCI0.LPC0.FIGD._STA] \\ (Node 0xc3f6d160), AE_NOT_FOUND
Often, these problems may be resolved by updating the BIOS to the latest revision. Most console messages are harmless, but if there are other problems, like the battery status is not working, these messages are a good place to start looking for problems.
The BIOS bytecode, known as ACPI Machine Language (AML), is compiled from a source language called ACPI Source Language (ASL). The AML is found in the table known as the Differentiated System Description Table (DSDT).
The goal of FreeBSD is for everyone to have working
	ACPI without any user intervention.
	Workarounds are still being developed for common mistakes made
	by BIOS  vendors.  The Microsoft®
	interpreter (acpi.sys and
	acpiec.sys) does not strictly check for
	adherence to the standard, and thus many
	BIOS vendors who only test
	ACPI under Windows® never fix their
	ASL.  FreeBSD developers continue to identify
	and document which non-standard behavior is allowed by
	Microsoft®'s interpreter and replicate it so that FreeBSD can
	work without forcing users to fix the
	ASL.
To help identify buggy behavior and possibly fix it
	manually, a copy can be made of the system's
	ASL.  To copy the system's
	ASL to a specified file name, use
	acpidump with -t, to show
	the contents of the fixed tables, and -d, to
	disassemble the AML:
#acpidump -td >my.asl
Some AML versions assume the user is
	running Windows®.  To override this, set
	hw.acpi.osname= in
	"Windows
	  2009"/boot/loader.conf, using the most recent
	Windows® version listed in the ASL.
Other workarounds may require my.asl
	to be customized.  If this file is edited, compile the new
	ASL using the following command.  Warnings
	can usually be ignored, but errors are bugs that will usually
	prevent ACPI from working correctly.
#iasl -fmy.asl
Including -f forces creation of the
	AML, even if there are errors during
	compilation.  Some errors, such as missing return statements,
	are automatically worked around by the FreeBSD
	interpreter.
The default output filename for iasl is
	DSDT.aml.  Load this file instead of the
	BIOS's buggy copy, which is still present
	in flash memory, by editing
	/boot/loader.conf as follows:
acpi_dsdt_load="YES" acpi_dsdt_name="/boot/DSDT.aml"
Be sure to copy DSDT.aml to
	/boot, then reboot the system.  If this
	fixes the problem, send a diff(1) of the old and new
	ASL to freebsd-acpi so that developers can
	work around the buggy behavior in
	acpica.
The ACPI driver has a flexible
	debugging facility.  A set of subsystems and the level of
	verbosity can be specified.  The subsystems to debug are
	specified as layers and are broken down into components
	(ACPI_ALL_COMPONENTS) and
	ACPI hardware support
	(ACPI_ALL_DRIVERS).  The verbosity of
	debugging output is specified as the level and ranges from
	just report errors (ACPI_LV_ERROR) to
	everything (ACPI_LV_VERBOSE).  The level is
	a bitmask so multiple options can be set at once, separated by
	spaces.  In practice, a serial console should be used to log
	the output so it is not lost as the console message buffer
	flushes.  A full list of the individual layers and levels is
	found in acpi(4).
Debugging output is not enabled by default.  To enable it,
	add options ACPI_DEBUG to the custom kernel
	configuration file if ACPI is compiled into
	the kernel.  Add ACPI_DEBUG=1 to
	/etc/make.conf to enable it globally.  If
	a module is used instead of a custom kernel, recompile just
	the acpi.ko module as follows:
#cd /sys/modules/acpi/acpi && make clean && make ACPI_DEBUG=1
Copy the compiled acpi.ko to
	/boot/kernel and add the desired level
	and layer to /boot/loader.conf.  The
	entries in this example enable debug messages for all
	ACPI components and hardware drivers and
	output error messages at the least verbose level:
debug.acpi.layer="ACPI_ALL_COMPONENTS ACPI_ALL_DRIVERS" debug.acpi.level="ACPI_LV_ERROR"
If the required information is triggered by a specific
	event, such as a suspend and then resume, do not modify
	/boot/loader.conf.  Instead, use
	sysctl to specify the layer and level after
	booting and preparing the system for the specific event.  The
	variables which can be set using sysctl are
	named the same as the tunables in
	/boot/loader.conf.
Once the debugging information is gathered, it can be sent to freebsd-acpi so that it can be used by the FreeBSD ACPI maintainers to identify the root cause of the problem and to develop a solution.
Before submitting debugging information to this mailing list, ensure the latest BIOS version is installed and, if available, the embedded controller firmware version.
When submitting a problem report, include the following information:
Description of the buggy behavior, including system type, model, and anything that causes the bug to appear. Note as accurately as possible when the bug began occurring if it is new.
The output of dmesg after running
	    boot -v, including any error messages
	    generated by the bug.
The dmesg output from boot
	      -v with ACPI disabled,
	    if disabling ACPI helps to fix the
	    problem.
Output from sysctl hw.acpi.  This
	    lists which features the system offers.
The URL to a pasted version of the system's ASL. Do not send the ASL directly to the list as it can be very large. Generate a copy of the ASL by running this command:
#acpidump -dt >name-system.asl
Substitute the login name for
	    name and manufacturer/model for
	    system.  For example, use
	    njl-FooCo6000.asl.
Most FreeBSD developers watch the FreeBSD-CURRENT mailing list, but one should submit problems to freebsd-acpi to be sure it is seen. Be patient when waiting for a response. If the bug is not immediately apparent, submit a bug report. When entering a PR, include the same information as requested above. This helps developers to track the problem and resolve it. Do not send a PR without emailing freebsd-acpi first as it is likely that the problem has been reported before.
More information about ACPI may be found in the following locations:
The FreeBSD ACPI Mailing List Archives
	    (https://lists.freebsd.org/pipermail/freebsd-acpi/)
The ACPI 2.0 Specification (http://acpi.info/spec.htm)
acpi(4), acpi_thermal(4), acpidump(8), iasl(8), and acpidb(8)
All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/
Questions that are not answered by the
    documentation may be
    sent to <freebsd-questions@FreeBSD.org>.
    Send questions about this document to <freebsd-doc@FreeBSD.org>.