相关参考
- ACPI协议规范: ACPI_6_3_May16.pdf
- ASL教程:asl_tutorial_v20190625.pdf
- UEFI-ACPI: https://uefi.org/acpi
- AML工作原理快速调研 - X86新手必看
- Linux内核软件架构基础-鲲鹏920
相关资料下载:
链接: https://pan.baidu.com/s/1uUwhHKztLcZlruONLPm-oA 密码: 7kgf
ACPI协议中关键点
- P120 Table 5-29 描述了 /sys/firmware/acpi/tables/ 中各表项 内容
ACPI使用
因为ACPI不是研究的重点,但X86系统各方面离不开这玩意,所以先介绍下Linux下使用
可以参考:Linux内核软件架构基础-鲲鹏920 是比设备树更牛逼的东西。
先不用去就纠结这些表咋来的,只需要怎么获取,后期对照相关架构的硬件手册来看即可。
ACPI系统描述表的获取
首先要知道系统中 ACPI有个系统描述表
可参考 ACPI协议规范 Chapter 5.2: ACPI System Description Tables
在用户空间可解析这些表信息
sudo apt-get install -y iasl acpica-tools
sudo su # need root
############## acpi工具快速打印################
### acpidump 可快速打印出所有的表项概要
root@inno-MS-7B89:testacpi# acpidump -s
ACPI: SSDT 0x0000000000000000 003EC9 (v01 AMD AMD CPU 00000001 AMD 00000001)
ACPI: MCFG 0x0000000000000000 00003C (v01 ALASKA A M I 01072009 MSFT 00010013)
ACPI: APIC 0x0000000000000000 00015E (v03 ALASKA A M I 01072009 AMI 00010013)
ACPI: CRAT 0x0000000000000000 000ED8 (v01 AMD AMD CRAT 00000001 AMD 00000001)
ACPI: PCCT 0x0000000000000000 00006E (v01 AMD AMD PCCT 00000001 AMD 00000000)
ACPI: SSDT 0x0000000000000000 008C98 (v02 AMD AMD ALIB 00000002 MSFT 04000000)
ACPI: CDIT 0x0000000000000000 000029 (v01 AMD AMD CDIT 00000001 AMD 00000001)
ACPI: UEFI 0x0000000000000000 000042 (v01 ALASKA A M I 00000002 01000013)
ACPI: IVRS 0x0000000000000000 0000D0 (v02 AMD AMD IVRS 00000001 AMD 00000000)
ACPI: DSDT 0x0000000000000000 007C55 (v02 ALASKA A M I 01072009 INTL 20120913)
ACPI: WSMT 0x0000000000000000 000028 (v01 ALASKA A M I 01072009 AMI 00010013)
ACPI: SSDT 0x0000000000000000 001D4A (v01 AMD AmdTable 00000001 INTL 20120913)
ACPI: SSDT 0x0000000000000000 003776 (v01 AMD AMD AOD 00000001 INTL 20120913)
ACPI: FACP 0x0000000000000000 000114 (v06 ALASKA A M I 01072009 AMI 00010013)
ACPI: FPDT 0x0000000000000000 000044 (v01 ALASKA A M I 01072009 AMI 00010013)
ACPI: SSDT 0x0000000000000000 0000FC (v02 ALASKA CPUSSDT 01072009 AMI 01072009)
ACPI: HPET 0x0000000000000000 000038 (v01 ALASKA A M I 01072009 AMI 00000005)
ACPI: SSDT 0x0000000000000000 0000BF (v01 AMD AMD PT 00001000 INTL 20120913)
ACPI: FIDT 0x0000000000000000 00009C (v01 ALASKA A M I 01072009 AMI 00010013)
ACPI: FACS 0x0000000000000000 000040
ACPI: BGRT 0x0000000000000000 000038 (v01 ALASKA A M I 01072009 AMI 00010013)
mkdir -p testacpi && cd testacpi
acpidump > acpidump.out # 将ACPI表二进制打印到文件
acpixtract -a acpidump.out # 解析acpi表,生成各个dat文件
iasl -d xxx.dat # iasl会解析acpi 二进制表,生成xxx.dsl描述文件
注:也可将cp /sys/firmware/acpi/tables/* 中的文件拷贝到其他目录(sysfs下不能用iasl去解析),
然后用iasl去解析
mkdir -p testacpi && cp /sys/firmware/acpi/tables/* ./testacpi -r
cd testacpi
rm data dynamic -rf
iasl -d *
会给每个文件生成对应的 .dsl文件,这是将acpi翻译成描述信息的内容
内核代码中获取ACPI表信息 demo
// 比如:./drivers/iommu/intel/dmar.c中
detect_intel_iommu
dmar_table_detect();
acpi_status status = acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_tbl);
acpi_put_table(dmar_tbl);
struct acpi_table_header {
char signature[ACPI_NAME_SIZE]; /* ASCII table signature */
u32 length; /* Length of table in bytes, including this header */
u8 revision; /* ACPI Specification minor version number */
u8 checksum; /* To make sum of entire table == 0 */
char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */
u32 oem_revision; /* OEM revision number */
char asl_compiler_id[ACPI_NAME_SIZE]; /* ASCII ASL compiler vendor ID */
u32 asl_compiler_revision; /* ASL compiler version */
};
cat dmar.dsl | more
[000h 0000 4] Signature : "DMAR" [DMA Remapping table]
[004h 0004 4] Table Length : 000000A8
[008h 0008 1] Revision : 01
[009h 0009 1] Checksum : 2A
[00Ah 0010 6] Oem ID : "INTEL "
[010h 0016 8] Oem Table ID : "NUC8i3BE"
[018h 0024 4] Oem Revision : 00000040
[01Ch 0028 4] Asl Compiler ID : " "
[020h 0032 4] Asl Compiler Revision : 01000013
......
ACPI的METHOD获取
在看PCI代码的时候,遇到关键点的时候,总是被ACPI打断,导致无法继续分析
比如:PCI域的获取,PCI mcfg的地址,PCI资源信息
acpi_pci_root_add
|- acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL,
&segment);
acpi_pci_root_get_mcfg_addr
|- status = acpi_evaluate_integer(handle, METHOD_NAME__CBA,
NULL, &mcfg_addr);
acpi_evaluate_integer()实际调用 acpi_evaluate_object()。
这个实现在./drivers/acpi/acpica/nsxfeval.c中,其最终的实现是这个函数:
acpi_ns_evaluate(info)->acpi_ps_execute_method(info)->acpi_ps_parse_aml()
......
#define METHOD_NAME__CBA "_CBA"
#define METHOD_NAME__SEG "_SEG"
#define METHOD_NAME__SRS "_SRS"
#define METHOD_NAME__STA "_STA"
#define METHOD_NAME__SUB "_SUB"
#define METHOD_NAME__UID "_UID"
Linux内核软件架构基础-鲲鹏920 中描述了:acpi_evaluate_object 是调用ACPI的 (AML作为一种抽象语言集成在ACPI的数据结构中,由)OS一侧 的AML虚拟机解释执行。
什么是ACPI
高级配置与电源接口(Advanced Configuration and Power Interface),简称ACPI,1997年由Intel、Microsoft、Toshiba 所共同制定提供操作系统应用程序管理所有电源管理接口
**
ACPI的目标
ASL教程:asl_tutorial_v20190625.pdf中描述
ACPI就是根据 硬件手册 去抽象出 计算机中 所有components, 生成AML文件,然后进行所有的组件管理等任务。
ACPI规范不是仅仅针对某一项调节,而是要协调各个部分,综合管理,使其达到最佳状态。
ACPI是一种工业级的接口协议,它同时规范了硬件和软件的接口,使得OS可以直接配置和电源管理所有设备以及整个系统。操作系统可以收集用户、应用、硬件等各方面信息做出综合判断以及执行。
支持传统BIOS电源管理的电脑从传统模式启动然后等到ACPI OS启动之后转换到工作状态。而不支持传统模式的电脑如(RISC:ARM)直接冲G3直接到G0。
ACPI整体框图
ACPI主要包含以下几个部分:
- 1.系统电源管理(System power management)
- 2.设备电源管理(Device power management)
- 3. 处理器电源管理(Processor power management)
- 4.设备和处理器性能管理(Device and processor performance management)
- 5.配置/即插即用(Configuration/Plug and Play)
- 6.系统事件(System Event)
- 7.电池管理(Battery management)
- 8.温度管理(Thermal management)
- 9.嵌入式控制器(Embedded Controller)
- 10.SMBus控制器(SMBus Controller)