ACPI DEBUG方法

获取ACPI TABLE的方法

1. 首先要安装acpidump和iasl命令。
$ sudo apt-get install acpidump
$ sudo apt-get install iasl
$ sudo apt-get install pmtools
有的机器上需要安装pmtools才可以。


2. 导出ACPI的数据。
$ sudo cat /proc/acpi/dsdt > dstd.dat
或者
$ sudo cat /sys/firmware/acpi/tables/DSDT > /tmp/dsdt.dat
如果找不到该文件可以使用下面的命令:
$ sudo acpidump > acpi.dat


3. 分离各表格数据,会生成多个数据文件。
$ acpixtract -a acpi.dat
Acpi table [DSDT] -  41555 bytes written to DSDT.dat
Acpi table [FACS] -     64 bytes written to FACS.dat
Acpi table [FACP] -    116 bytes written to FACP.dat
Acpi table [APIC] -    132 bytes written to APIC.dat
Acpi table [ASF!] -     99 bytes written to ASF!.dat
Acpi table [MCFG] -     60 bytes written to MCFG.dat
Acpi table [TCPA] -     50 bytes written to TCPA.dat
Acpi table [SLIC] -    374 bytes written to SLIC.dat
Acpi table [HPET] -     56 bytes written to HPET.dat
Acpi table [DMAR] -    456 bytes written to DMAR.dat
Acpi table [RSDT] -     68 bytes written to RSDT.dat
Acpi table [RSDP] -     20 bytes written to RSDP.dat


4. 反汇编DSDT.dat,
$ iasl -d DSDT.dat
Intel ACPI Component Architecture
AML Disassembler version 20100528 [Oct 15 2010]
Copyright (c) 2000 - 2010 Intel Corporation
Supports ACPI Specification Revision 4.0a
Loading Acpi table from file DSDT.dat
Acpi table [DSDT] successfully installed and loaded
Pass 1 parse of [DSDT]
Pass 2 parse of [DSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)
...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Parsing completed
Disassembly completed, written to "DSDT.dsl"


5. 根据需要修改DSDT.dsl文件,然后重新编译该文件,会生成DSDT.aml和DSDT.hex两个文件。
$ iasl -tc dsdt.dsl
Intel ACPI Component Architecture
ASL Optimizing Compiler version 20100528 [Oct 15 2010]
Copyright (c) 2000 - 2010 Intel Corporation
Supports ACPI Specification Revision 4.0a
......................................................
ASL Input:  DSDT.dsl - 8762 lines, 320704 bytes, 3778 keywords
AML Output: DSDT.aml - 39328 bytes, 780 named objects, 2998 executable opcodes
Compilation complete. 0 Errors, 41 Warnings, 0 Remarks, 988 Optimizations


6. 更新DSDT的方法。
其一(没有测试过,不知道能否成功):
使用新的dsdt.aml代替BIOS中的版本:
    cp /boot/initrd.img-2.6.20-16-generic /boot/initrd.img-2.6.20-16-generic-bak
    sudo cp dsdt.aml /etc/initramfs-tools/DSDT.aml
    sudo update-initramfs -u -k all
其二(需要安装acpiexec,为找到):
iasl -sa DSDT.dsl        # e.g. recompile a modified, disassembled DSDT for
                           initramfs inclusion (see later)
acpiexec DSDT.dat        # parse, interpret and load a DSDT in userspace
其三:
这个方法需要重新编译内核。
首先将DSDT.hex文件复制到内核源码的include目录下。
$ cp DSDT.hex $SRC/include/
然后修改内核配置文件.config
    CONFIG_STANDALONE=n
    CONFIG_ACPI_CUSTOM_DSDT=y
    CONFIG_ACPI_CUSTOM_DSDT_FILE="DSDT.hex"
重新编译,更新内核,然后启动,可以在dmesg中看到
[    0.000000] ACPI: Override [DSDT- CDV-TPT], this is unsafe: tainting kernel
[    0.000000] Disabling lock debugging due to kernel taint
[    0.000000] ACPI: DSDT @ 0x7f378010 Table override, replaced with:
[    0.000000] ACPI: DSDT c0f0f140 0703F (v02  Intel  CDV-TPT 00000000 INTL 20091214)
就说明DSDT已经被替换成修改过的了。


7. 在DSDT中添加LOG。
首先应该打开CONFIG_ACPI_DEBUG=y。
acpi.debug_level= ACPI_LV_DEBUG_OBJECT,
acpi.debug_layer= ACPI_TABLES | ACPI_NAMESPACE,
使用将想要的变量或者字符串赋值给Debug即可。
(Store (AAAA, Debug)


下面附上原文:
Dumping ACPI tables using acpidump and acpixtract
Most of the time when I'm looking at BIOS issues I just look at the disassembled ACPI DSDT using the following runes:
$ sudo cat /proc/acpi/dsdt > dstd.dat
$ iasl -d dstd.dat
..and look at the disassembly in dstd.dsl
Some BIOS bugs need a little more examination, and that's where I use acpidump + acpixtract. The simplest way to dump all the ACPI tables is as follows:
$ sudo acpidump > acpi.dat
$ acpixtract -a acpi.dat
Acpi table [DSDT] - 24564 bytes written to DSDT.dat
Acpi table [FACS] - 64 bytes written to FACS.dat
Acpi table [FACP] - 244 bytes written to FACP1.dat
Acpi table [APIC] - 104 bytes written to APIC1.dat
Acpi table [HPET] - 56 bytes written to HPET.dat
Acpi table [MCFG] - 60 bytes written to MCFG.dat
Acpi table [TCPA] - 50 bytes written to TCPA.dat
Acpi table [TMOR] - 38 bytes written to TMOR.dat
Acpi table [SLIC] - 374 bytes written to SLIC.dat
Acpi table [APIC] - 104 bytes written to APIC2.dat
Acpi table [BOOT] - 40 bytes written to BOOT.dat
Acpi table [SSDT] - 685 bytes written to SSDT1.dat
Acpi table [SSDT] - 163 bytes written to SSDT2.dat
Acpi table [SSDT] - 607 bytes written to SSDT3.dat
Acpi table [SSDT] - 166 bytes written to SSDT4.dat
Acpi table [SSDT] - 1254 bytes written to SSDT5.dat
Acpi table [XSDT] - 148 bytes written to XSDT.dat
Acpi table [FACP] - 116 bytes written to FACP2.dat
Acpi table [RSDT] - 88 bytes written to RSDT.dat
Acpi table [RSDP] - 36 bytes written to RSDP.dat
..this dumps out all the tables into files.
One can the disassemble the required file using iasl, e.g.:
$ iasl -d APIC1.dat
or decode the table using madt:
$ madt < ACPI1.dsl
ACPI: APIC (v001 INTEL CRESTLNE 0x06040000 LOHR 0x0000005a) @ 0x(nil)
ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled)
ACPI: LAPIC (acpi_id[0x01] lapic_id[0x01] enabled)
ACPI: IOAPIC (id[0x01] address[0xfec00000] global_irq_base[0x0])
ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
ACPI: LAPIC_NMI (acpi_id[0x00] high edge lint[0x1])
ACPI: LAPIC_NMI (acpi_id[0x01] high edge lint[0x1])
Length 104 OK
Checksum OK
Or to just get one particular table, I use:
$ sudo acpidump -t SSDT > SSDT.dat
$ acpixtract -a SSDT.dat
$ iasl -d SSDT.dat
Intel ACPI Component Architecture
AML Disassembler version 20090521 [Jun 30 2009]
Copyright (C) 2000 - 2009 Intel Corporation
Supports ACPI Specification Revision 3.0a
Loading Acpi table from file SSDT.dat
Acpi table [SSDT] successfully installed and loaded
Pass 1 parse of [SSDT]
Pass 2 parse of [SSDT]
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)
.........
Parsing completed
Disassembly completed, written to "SSDT.dsl"
Armed with a copy of the ACPI spec, one can then start digging into why there are weird Linux/BIOS interactions occurring.
How to Build a custom DSDT into the kernel
    Get original DSDT:
    # cp /proc/acpi/dsdt DSDT
    or
    # acpidump > acpidump.out
    $ acpixtract DSDT acpidump > DSDT.dat
    Disassemble it
    $ iasl -d DSDT.dat
    Make your changes:
    $ vi DSDT.dsl
    Build it:
    $ iasl -tc DSDT.dsl
    Put it where the kernel build can include it:
    $ cp DSDT.hex $SRC/include/
    Add this to the kernel .config:
    CONFIG_STANDALONE=n
    CONFIG_ACPI_CUSTOM_DSDT=y
    CONFIG_ACPI_CUSTOM_DSDT_FILE="DSDT.hex"
    Make the kernel and off you go!
    You should see in dmesg:
    Table [DSDT] replaced by host OS


Linux ACPI Custom Control Method How To
Written by Zhang Rui <[email protected]>
Linux supports customizing ACPI control methods at runtime.
Users can use this to
1. override an existing method which may not work correctly, or just for debugging purposes.
2. insert a completely new method in order to create a missing method such as _OFF, _ON, _STA, _INI, etc. For these cases, it is far simpler to dynamically install a single control method rather than override the entire DSDT, because kernel rebuild/reboot is not needed and test result can be got in minutes.
Note: Only ACPI METHOD can be overridden, any other object types like "Device", "OperationRegion", are not recognized. Note: The same ACPI control method can be overridden for many times, and it's always the latest one that used by Linux/kernel. Note: To get the ACPI debug object output (Store (AAAA, Debug)), please run "echo 1 > /sys/module/acpi/parameters/aml_debug_output".
1. override an existing method a) get the ACPI table via ACPI sysfs I/F. e.g. to get the DSDT, just run "cat /sys/firmware/acpi/tables/DSDT > /tmp/dsdt.dat" b) disassemble the table by running "iasl -d dsdt.dat".
   c) rewrite the ASL code of the method and save it in a new file,
   d) package the new file (psr.asl) to an ACPI table format. Here is an example of a customized \_SB._AC._PSR method,
      DefinitionBlock ("", "SSDT", 1, "", "", 0x20080715)
      { External (ACON)
Method (\_SB_.AC._PSR, 0, NotSerialized)
{ Store ("In AC _PSR", Debug)
Return (ACON) } }
      Note that the full pathname of the method in ACPI namespace
      should be used.
      And remember to use "External" to declare external objects. e) assemble the file to generate the AML code of the method. e.g. "iasl psr.asl" (psr.aml is generated as a result) f) mount debugfs by "mount -t debugfs none /sys/kernel/debug"
   g) override the old method via the debugfs by running "cat /tmp/psr.aml > /sys/kernel/debug/acpi/custom_method"
2. insert a new method This is easier than overriding an existing method.
   We just need to create the ASL code of the method we want to
   insert and then follow the step c) ~ g) in section 1.
3. undo your changes The "undo" operation is not supported for a new inserted method
   right now, i.e. we can not remove a method currently.
   For an overrided method, in order to undo your changes, please
   save a copy of the method original ASL code in step c) section 1,
   and redo step c) ~ g) to override the method with the original one.
Note: We can use a kernel with multiple custom ACPI method running, But each individual write to debugfs can implement a SINGLE
      method override. i.e. if we want to insert/override multiple
      ACPI methods, we need to redo step c) ~ g) for multiple times.
Note: Be aware that root can mis-use this driver to modify arbitrary memory and gain additional rights, if root's privileges got
      restricted (for example if root is not allowed to load additional modules after boot).
/sys/module/acpi/parameters/:
trace_method_name The AML method name that the user wants to trace
trace_debug_layer The temporary debug_layer used when tracing the method.
Using 0xffffffff by default if it is 0.
trace_debug_level The temporary debug_level used when tracing the method.
Using 0x00ffffff by default if it is 0.
trace_state The status of the tracing feature.
"enabled" means this feature is enabled
and the AML method is traced every time it's executed.
"1" means this feature is enabled and the AML method
will only be traced during the next execution.
"disabled" means this feature is disabled.
Users can enable/disable this debug tracing feature by
"echo string > /sys/module/acpi/parameters/trace_state".
"string" should be one of "enable", "disable" and "1".


ACPI Debug Output
The ACPI CA, the Linux ACPI core, and some ACPI drivers can generate debug output.  This document describes how to use this facility.
Compile-time configuration
--------------------------
ACPI debug output is globally enabled by CONFIG_ACPI_DEBUG.  If this config option is turned off, the debug messages are not even built into the kernel.
Boot- and run-time configuration
--------------------------------
When CONFIG_ACPI_DEBUG=y, you can select the component and level of messages you're interested in.  At boot-time, use the acpi.debug_layer and acpi.debug_level kernel command line options.  After boot, you can use the debug_layer and debug_level files in /sys/module/acpi/parameters/ to control the debug messages.
debug_layer (component)
-----------------------
The "debug_layer" is a mask that selects components of interest, e.g., a specific driver or part of the ACPI interpreter.  To build the debug_layer bitmask, look for the "#define _COMPONENT" in an ACPI source file.
You can set the debug_layer mask at boot-time using the acpi.debug_layer command line argument, and you can change it after boot by writing values to /sys/module/acpi/parameters/debug_layer.
The possible components are defined in include/acpi/acoutput.h and include/acpi/acpi_drivers.h.  Reading /sys/module/acpi/parameters/debug_layer shows the supported mask values, currently these:
    ACPI_UTILITIES                  0x00000001
    ACPI_HARDWARE                   0x00000002
    ACPI_EVENTS                     0x00000004
    ACPI_TABLES                     0x00000008
    ACPI_NAMESPACE                  0x00000010
    ACPI_PARSER                     0x00000020
    ACPI_DISPATCHER                 0x00000040
    ACPI_EXECUTER                   0x00000080
    ACPI_RESOURCES                  0x00000100
    ACPI_CA_DEBUGGER                0x00000200
    ACPI_OS_SERVICES                0x00000400
    ACPI_CA_DISASSEMBLER            0x00000800
    ACPI_COMPILER                   0x00001000
    ACPI_TOOLS                      0x00002000
    ACPI_BUS_COMPONENT              0x00010000
    ACPI_AC_COMPONENT               0x00020000
    ACPI_BATTERY_COMPONENT          0x00040000
    ACPI_BUTTON_COMPONENT           0x00080000
    ACPI_SBS_COMPONENT              0x00100000
    ACPI_FAN_COMPONENT              0x00200000
    ACPI_PCI_COMPONENT              0x00400000
    ACPI_POWER_COMPONENT            0x00800000
    ACPI_CONTAINER_COMPONENT        0x01000000
    ACPI_SYSTEM_COMPONENT           0x02000000
    ACPI_THERMAL_COMPONENT          0x04000000 ACPI_MEMORY_DEVICE_COMPONENT    0x08000000
    ACPI_VIDEO_COMPONENT            0x10000000
    ACPI_PROCESSOR_COMPONENT        0x20000000
debug_level
-----------
The "debug_level" is a mask that selects different types of messages, e.g., those related to initialization, method execution, informational messages, etc. To build debug_level, look at the level specified in an ACPI_DEBUG_PRINT() statement.
The ACPI interpreter uses several different levels, but the Linux ACPI core and ACPI drivers generally only use ACPI_LV_INFO.
You can set the debug_level mask at boot-time using the acpi.debug_level command line argument, and you can change it after boot by writing values to /sys/module/acpi/parameters/debug_level.
The possible levels are defined in include/acpi/acoutput.h.  Reading /sys/module/acpi/parameters/debug_level shows the supported mask values, currently these:
    ACPI_LV_INIT                    0x00000001
    ACPI_LV_DEBUG_OBJECT            0x00000002
    ACPI_LV_INFO                    0x00000004
    ACPI_LV_INIT_NAMES              0x00000020
    ACPI_LV_PARSE                   0x00000040
    ACPI_LV_LOAD                    0x00000080
    ACPI_LV_DISPATCH                0x00000100
    ACPI_LV_EXEC                    0x00000200
    ACPI_LV_NAMES                   0x00000400
    ACPI_LV_OPREGION                0x00000800
    ACPI_LV_BFIELD                  0x00001000
    ACPI_LV_TABLES                  0x00002000
    ACPI_LV_VALUES                  0x00004000
    ACPI_LV_OBJECTS                 0x00008000
    ACPI_LV_RESOURCES               0x00010000
    ACPI_LV_USER_REQUESTS           0x00020000
    ACPI_LV_PACKAGE                 0x00040000
    ACPI_LV_ALLOCATIONS             0x00100000
    ACPI_LV_FUNCTIONS               0x00200000
    ACPI_LV_OPTIMIZATIONS           0x00400000
    ACPI_LV_MUTEX                   0x01000000
    ACPI_LV_THREADS                 0x02000000
    ACPI_LV_IO                      0x04000000
    ACPI_LV_INTERRUPTS              0x08000000
    ACPI_LV_AML_DISASSEMBLE         0x10000000
    ACPI_LV_VERBOSE_INFO            0x20000000
    ACPI_LV_FULL_TABLES             0x40000000
    ACPI_LV_EVENTS                  0x80000000
Examples
--------
For example, drivers/acpi/bus.c contains this:
    #define _COMPONENT              ACPI_BUS_COMPONENT
    ...
    ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
To turn on this message, set the ACPI_BUS_COMPONENT bit in acpi.debug_layer and the ACPI_LV_INFO bit in acpi.debug_level.  (The ACPI_DEBUG_PRINT statement uses ACPI_DB_INFO, which is macro based on the ACPI_LV_INFO definition.)
Enable all AML "Debug" output (stores to the Debug object while interpreting AML) during boot:
    acpi.debug_layer=0xffffffff acpi.debug_level=0x2
Enable PCI and PCI interrupt routing debug messages:
    acpi.debug_layer=0x400000 acpi.debug_level=0x4
Enable all ACPI hardware-related messages:
    acpi.debug_layer=0x2 acpi.debug_level=0xffffffff
Enable all ACPI_DB_INFO messages after boot:
    # echo 0x4 > /sys/module/acpi/parameters/debug_level
Show all valid component values:
    # cat /sys/module/acpi/parameters/debug_layer

你可能感兴趣的:(ACPI DEBUG方法)