12.17 Using and Debugging FreeBSD ACPI

Written by Nate Lawson. With contributions from Peter Schultz and Tom Rhodes.

ACPI is a fundamentally new way of discovering devices, managing power usage, and providing standardized access to various hardware previously managed by the BIOS. Progress is being made toward ACPI working on all systems, but bugs in some motherboards' ACPI Machine Language (AML) bytecode, incompleteness in FreeBSD's kernel subsystems, and bugs in the Intel® ACPI-CA interpreter continue to appear.

This section is intended to help users assist the FreeBSD ACPI maintainers in identifying the root cause of problems you observe and debugging and developing a solution.

12.17.1 Submitting Debugging Information

Note: Before submitting a problem, be sure you are running the latest BIOS version and, if available, embedded controller firmware version.

When submitting a problem, send the following information to freebsd-acpi@FreeBSD.org:

Most FreeBSD developers watch 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, you may be asked to submit a PR using send-pr(1). 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.

12.17.2 Background

ACPI is present in all modern computers that conform to the ia32 (x86), ia64 (Itanium), 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 the bus enumeration parts 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 (e.g., FADT) in memory that specify things like the APIC map (used for SMP), config registers, and simple configuration values. Additionally, a table of bytecode (the Differentiated System Description Table DSDT) is provided that 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.

12.17.3 Common Problems

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.

12.17.3.1 Mouse Issues

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. If this does not work, consider sending a bug report using send-pr(1).

12.17.3.2 Suspend/Resume

ACPI has three suspend to RAM (STR) states, S1-S3, and one suspend to disk state (STD), called S4. S5 is “soft off” and is the normal state the system is in when plugged in but not powered up. S4 can actually be implemented two separate ways. S4BIOS is a BIOS-assisted suspend to disk. S4OS is implemented entirely by the operating system.

Start by checking sysctl hw.acpi for the suspend-related items. Here are the results for a Thinkpad:

hw.acpi.supported_sleep_state: S3 S4 S5
hw.acpi.s4bios: 0

Use acpiconf -s to test S3, S4OS, and S5. An s4bios of one (1), indicates S4BIOS support instead of S4 OS.

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. The next thing to try is S3. This is the deepest STR state and requires a lot of driver support to properly reinitialize the hardware. If you have problems resuming, feel free to email freebsd-acpi, but do not expect the problem to be resolved since there are a lot of drivers and hardware that need more testing and work.

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 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/cable for serial console or a Firewire port/cable for dcons(4), and kernel debugging skills.

To help isolate the problem, remove as many drivers from the kernel 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 you can properly load/unload the drivers, automate this by putting the appropriate commands in /etc/rc.suspend and /etc/rc.resume. There is a commented-out example for unloading and loading a driver. Try setting hw.acpi.reset_video to zero (0) if the display is messed up after resume. Try setting longer or shorter values for hw.acpi.sleep_delay to see if that helps.

Another thing to try is load a recent Linux distribution with ACPI support and test their suspend/resume support on the same hardware. If it works on Linux, it is likely a FreeBSD driver problem and narrowing down which driver causes the problems will help us fix the problem. Note that the ACPI maintainers do not usually maintain other drivers, such as sound or ATA, so any work done on tracking down a driver problem should probably eventually be posted to the freebsd-current list and mailed to the driver maintainer. Advanced users can start by putting some 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, you may be better off sticking 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.

12.17.3.3 System Hangs (Temporary or Permanent)

Most system hangs are a result of lost interrupts or an interrupt storm. Chipsets have a lot of problems based on how the BIOS configures interrupts before boot, 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 loader.conf.

12.17.3.4 Panics

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 (see Section 27.6.5.3) or setting up a dump(8) partition. To get a backtrace in DDB, use tr. When handwriting the backtrace, get at least the lowest five (5) and top five (5) 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.

12.17.3.5 System Powers Up After Suspend or Shutdown

First, try setting hw.acpi.disable_on_poweroff="0" in loader.conf(5). 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.

12.17.3.6 Other Problems

For other problems with ACPI such as it not working with a docking station or devices not being detected, email a description to the mailing list. Some issues may be related to unfinished parts of the ACPI subsystem which might take a while to be implemented. Be patient and prepared to test patches.

12.17.4 ASL, acpidump, and IASL

The most common problem is the BIOS vendors providing incorrect (or outright 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 when there are other problems like the battery status is not working, these messages are a good place to start looking for problems in the AML. The bytecode, known as AML, is compiled from a source language called ASL. The AML is found in the table known as the DSDT. To get a copy of the system's ASL, use acpidump(8). Include both -t, to show the contents of the fixed tables, and -d, to disassemble the AML. Refer to Submitting Debugging Information for an example syntax.

The simplest first check is to recompile the ASL to check for errors. Warnings can usually be ignored, but errors are bugs that will usually prevent ACPI from working correctly. To recompile the ASL, issue the following command:

# iasl your.asl

12.17.5 Fixing Your ASL

In the long run, the goal of FreeBSD is for almost everyone to have working ACPI without any user intervention. At this point, workarounds are still being developed for common mistakes made by the 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 exactly what non-standard behavior is allowed by Microsoft's interpreter and replicate it so FreeBSD can work without forcing users to fix the ASL. As a workaround, and to help identify behavior, fix the ASL manually. If this works, send a diff(1) of the old and new ASL so developers can possibly work around the buggy behavior in ACPI-CA and thus make the unnecessary fix.

Here is a list of common error messages, their cause, and how to fix them:

12.17.5.1 _OS Dependencies

Some AML assumes the world consists of various Windows versions. You can tell FreeBSD to claim it is any OS to see if this fixes problems you may have. An easy way to override this is to set hw.acpi.osname="Windows 2001" in /boot/loader.conf or other similar strings you find in the ASL.

12.17.5.2 Missing Return Statements

Some methods do not explicitly return a value as the standard requires. While ACPI-CA does not handle this, FreeBSD has a workaround that allows it to return the value implicitly. Explicit Return statements can be added where required if you know what value should be returned. To force iasl to compile the ASL, use the -f flag.

12.17.5.3 Overriding the Default AML

After customizing your.asl, compile it with this command:

# iasl your.asl

Adding the -f flag will force creation of the AML, even if there are errors during compilation. Some errors, such as missing Return statements, are automatically worked around by the interpreter.

DSDT.aml is the default output filename for iasl. 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.

12.17.6 Getting Debugging Output from ACPI

The ACPI driver has a very 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 ACPI-CA components (ACPI_ALL_COMPONENTS) and ACPI hardware support (ACPI_ALL_DRIVERS). The verbosity of debugging output is specified as the “level” and ranges from ACPI_LV_ERROR (just report errors) to ACPI_LV_VERBOSE (everything). 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 if it is so long it flushes the console message buffer. 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 kernel configuration file if ACPI is compiled into the kernel. Add ACPI_DEBUG=1 to /etc/make.conf to enable it globally. If it is a module, recompile just the acpi.ko module as follows:

# cd /sys/modules/acpi/acpi
&& make clean &&
make ACPI_DEBUG=1

Install acpi.ko in /boot/kernel and add the desired level and layer to loader.conf. This example enables debug messages for all ACPI-CA components and all ACPI hardware drivers such as (CPU and LID. It only outputs 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, leave out changes to loader.conf and instead use sysctl to specify the layer and level after booting and preparing the system for the specific event. The sysctls are named the same as the tunables in loader.conf.

12.17.7 References

More information about ACPI may be found in the following locations: