分析: 1,acpi build 源代码qemu-2.8/hw/i386/acpi-build.c 在acpi_build函数中, ? 可见,是在acpi的各个table都添加完成后,最后检查的时候,报出来的error。 2,build_dsdt 既然tables_blob->len超过了ACPI_BUILD_TABLE_SIZE (0x20000),那么要么减少tables_blob->len,要么增大ACPI_BUILD_TABLE_SIZE 例如在acpi_add_table(table_offsets, tables_blob); 函数后面加上ACPI_BUILD_DPRINTF("%s,%d,%d\n", __FILE__, __LINE “ACPI tables are larger than 64k.”这个问题就是这里引起的。 4,memory slot 再来说memory slot。
那么,换个思路,本文从ACPI设备的虚拟化出发,看软件如何虚拟化出来的ACPI设备,从代码上分析ACPI。 那么,CPU可以使用io指令访问对应的地址,就可以控制ACPI设备了。 2,piix4 acpi 在qemu2.8/hw/acpi/piix4.c中,实现了acpi设备的虚拟化: ? 代码的上半段,是acpi的pci配置空间的设置。看白色背景的代码,可见,acpi主要实现了: a,acpi的timer。 b,acpi的event通知。 c,acpi的控制。 d,acpi的gpe。 3,acpi timer 在qemu2.8/hw/acpi/core.c中,实现了acpi timer的主要逻辑: ? 4,acpi cnt 在qemu2.8/hw/acpi/core.c中,实现了acpi pm1 cnt的主要逻辑: ?
关于ACPI的定义在这里引用自维基百科: 高级配置与电源接口(Advanced Configuration and Power Interface),简称ACPI,是1997年由英特尔 ACPI作为电源管理标准,在日常中最形象的实例就是待机、睡眠、休眠。如果是热爱DIY的玩家,应该也会在主板BIOS设置中见到过电源管理选项。 ACPI的电源状态一共有S0~S5六种,下面一一介绍。 S0:正常工作状态,即平时使用计算机时的状态,不必多说。
ACPI几个关键概念整理,未翻译为中文,供需。 SLIT ACPI System Locality Distance Information Table (SLIT): The relative distance between nodes on a It Is a major ACPI table and is used to describe what peripherals the machine has. Each of these three has its own ACPI proximity domain and associated Linux NUMA node. Additionally we can have extra NUMA nodes that don't map back to ACPI proximity domains.
报错与现象: ACPI BIOS Error… 电脑花屏 解决方法: 插入启动盘,当进入引导界面后,键盘输入’e’,编辑Linux启动命令,把命令中的"---“替换成"nomodeset”,按下F10保存
; 10//ACPI对象 11union acpi_object { 12 acpi_object_type type; /* See definition of acpi_ns_type for 函数,这个函数中会调用acpi_scan_init函数,acpi_scan_init函数会完成如下: 1、注册ACPI总线 1result = bus_register(&acpi_bus_type); 5.2 接下来,调用acpi_get_object_info函数: 1acpi_status acpi_get_object_info(acpi_handle handle,struct acpi_device_info acpi_add_id(pnp, ACPI_BAY_HID); 13 else if (acpi_dock_match(handle)) 14 acpi_add_id(pnp, ACPI_DOCK_HID 接下来请看内核源码/drivers/acpi/acpi_pnp.c 1void __init acpi_pnp_init(void) 2{ 3 acpi_scan_add_handler(&acpi_pnp_handler
ACPI这个单词,用电脑用多了的同学应该或多或少能在系统的报错信息等地方见过它。 通过ACPI规范,就能查询计算机硬件的一些信息。 于是我就找到了ACPI规范,能够通过它来获取电脑的状态信息。这些信息里面就包括了I/O APIC控制寄存器的基地址。 根据ACPI规范,RSDT的结构是这样的: 然后,我们就可以根据Entry数组中的物理地址,一个个的查找我们需要的数据结构。这时,我们仍然需要在页表中映射这些地址。 然后,根据ACPI规范,我们可以看到,这个Entry指向了多种数据结构,如APIC、HPET等。
指令来控制虚拟机的电源,而KVM虚拟机安装linux系统时默认没有安装acpi服务,反以导致不能关闭虚拟机,需要安装acpi。 ACPId服务与内核的通信方式:acpid用poll函数挂在/proc/acpi/event文件上。 内核在drivers/acpi/event.c中实现了该文件的接口,一旦总线事件列表(acpi_bus_event_list)上有电源管理事件发生,内核就会唤醒挂在/proc/acpi/event上的acpid ,acpid再从/proc/acpi/event中读取相应的事件。 ACPId服务配置文件在/etc/acpi/events/目录下, 下面是一个示例: event=button/power.
20150619) [ 0.000000] ACPI: FACS 000000003fffe000 00040 [ 0.000000] ACPI: SSDT 000000003ffff1eb 00838 : PM-Timer IO Port: 0x608 [ 0.000000] ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled) [ 0.000000] ACPI: LAPIC_NMI (acpi_id[0xff] dfl dfl lint[0x1]) [ 0.000000] ACPI: IOAPIC (id[0x00] address[0xfec00000 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 10 global_irq 10 high level) [ 0.000000] ACPI: INT_SRC_OVR : Added _OSI(Module Device) [ 0.160012] ACPI: Added _OSI(Processor Device) [ 0.164012] ACPI: Added _
BIOS收集IOMMU相关的信息,通过ACPI中的特定表组织数据,放置在内存中,等操作系统接管硬件后,它会加载驱动,驱动再详细解析ACPI表中的信息。 对应代码宏定义如下: enum acpi_dmar_type { ACPI_DMAR_TYPE_HARDWARE_UNIT = 0, ACPI_DMAR_TYPE_RESERVED_MEMORY = 1, ACPI_DMAR_TYPE_ROOT_ATS = 2, ACPI_DMAR_TYPE_HARDWARE_AFFINITY = 3, ACPI_DMAR_TYPE_NAMESPACE = struct acpi_table_header * __initdata dmar_tbl; static acpi_size dmar_tbl_size; start_kernel └─mm_init | | └─for(dev_scope_num in acpi table) | | ├─acpi_bus_get_device | |
和syslog我的盘符分了100G一晚上就占用满了,我通过 echo "" > kern.log 和echo "" > syslog然后tail -f查看日志,发下如下错误 [ 0.049316] ACPI Exception:AE_NOT_FOUND,During name lookup/catalog(20170831/psobject-252) [ 0.049328] ACPI Error: Method parse/execution failed \_SB.PCI0.RP04.PXSX, AE_NOT_FOUND (20170831/psparse-550) [ 0.049682] ACPI Error :[_SB_.PCI0.RP09.PXSX] Namespace lookup failure, AE_NOT_FOUND(20170831/dswload2-191) [ 0.049687] ACPI 后来在执行 echo "disable" > /sys/firmware/acpi/interrupts/gpe6F 可完美解决,gpe6F可通过执行grep .
,放置在内存中,等操作系统接管硬件后,它会加载驱动,驱动再详细解析ACPI表中的信息。 对应代码宏定义如下: enum acpi_dmar_type { ACPI_DMAR_TYPE_HARDWARE_UNIT = 0, ACPI_DMAR_TYPE_RESERVED_MEMORY = 1, ACPI_DMAR_TYPE_ROOT_ATS = 2, ACPI_DMAR_TYPE_HARDWARE_AFFINITY = 3, ACPI_DMAR_TYPE_NAMESPACE = struct acpi_table_header * __initdata dmar_tbl; static acpi_size dmar_tbl_size; start_kernel └─mm_init | | └─for(dev_scope_num in acpi table) | | ├─acpi_bus_get_device | |
/asus-keyboard-backlight.sh OK /etc/acpi/events/asus-keyboard-backlight-down OK /etc/acpi/ibm-wireless.sh OK /etc/acpi/events/tosh-wireless OK /etc/acpi/asus-wireless.sh OK /etc/acpi/events/lenovo-undock OK /etc/default/acpi-support OK /etc/acpi/events/ibm-wireless OK /etc/acpi/events/asus-wireless-on OK / etc/acpi/events/asus-wireless-off OK /etc/acpi/tosh-wireless.sh OK /etc/acpi/events/asus-keyboard-backlight-up OK /etc/acpi/events/thinkpad-cmos OK /etc/acpi/undock.sh OK /etc/acpi/events/powerbtn OK /etc/acpi/powerbtn.sh
.driver = { .name = XXX_POE_DRV_NAME, .of_match_table = xxx_poe_match, .acpi_match_table = ACPI_PTR(xxx_poe_acpi_ids), }, }; 有name、of_match_table、acpi_match_table三个字段;总线上的device和driver进行匹配的时候会调用 style match first */ if (of_driver_match_device(dev, drv)) return 1; /* Then try ACPI style match */ if (acpi_driver_match_device(dev, drv)) return 1; /* Then try to driver name match */ return (strcmp(pdev->name, drv->name) == 0); } 很明显,先匹配of_match_table,再是acpi_match_table
从ACPI 生成device acpi初始化函数 static struct acpi_scan_handler apd_handler = { .ids = acpi_apd_device_ids , .attach = acpi_apd_create_device, }; void __init acpi_apd_init(void) { acpi_scan_add_handler (&apd_handler); } 其中的ids,存放了 acpi中定义的属性,如下格式。 static const struct acpi_device_id acpi_apd_device_ids[] = { /* Generic apd devices */ #ifdef CONFIG_ARM64 , }; 创建入口为 acpi_apd_create_device ——- acpi_create_platform_device —– platform_device_register_full device
clocksource=apcipm" near the beginning of "GRUBCMDLINELINUXDEFAULT=" just tells it directly to use an acpi based motherboards power management timer. if "clocksource=acpi_pm" fails for some reason try "clocksource [root@localhost ~]# cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pm confusion with the software multimedia timers introduced in the MultiMedia Extensions to Windows 3.0. acpi_pm The ACPI Power Management Timer (ACPI PMT) is yet another clock device included in almost all ACPI-based
例如,查找指定目录/etc/acpi 及其子目录(如果存在子目录的话)下所有文件中包含字符串"update"的文件,并打印出该字符串所在行的内容,使用的命令为: grep -r update /etc/ acpi 输出结果如下: $ grep -r update /etc/acpi #以递归的方式查找“etc/acpi”下包含“update”的文件 /etc/acpi/ac.d/85-anacron.sh Rather than /etc/acpi/resume.d/85-anacron.sh:# (Things like the slocate updatedb cause a lot of IO Rather than /etc/acpi/events/thinkpad-cmos:action=/usr/sbin/thinkpad-keys--update 3、反向查找。
在这里,BDOOR_CMD_PATCH_ACPI_TABLES命令是最有意思的了,因为它可以从用户的内存中解析ACPI表,下面的分析过程基于的是VMware Workstation的Linux版本(v $ sudo cat /sys/firmware/acpi/tables/DSDT > DSDT $ iasl -d DSDT Intel ACPI Component Architecture DSDT表中包含了一个ACPI Header,后面跟着的是AML字节码。 ACPI Header的数据结构如下所示: struct acpi_table_header { char signature[ACPI_NAMESEG_SIZE]; 虽然这种OOB写入操作是高度受限的,但ACPI校验和计算过程中的OOB读取是可以泄露主机堆内存数据的。 ACPI表校验和是一个值,它使得表中所有字节的总和为0(mod 256)。
INSTALL crypto/xor.ko INSTALL crypto/xxhash_generic.ko INSTALL crypto/zstd.ko INSTALL drivers/acpi /acpi_configfs.ko INSTALL drivers/acpi/acpi_extlog.ko INSTALL drivers/acpi/acpi_ipmi.ko INSTALL drivers/acpi/acpi_pad.ko INSTALL drivers/acpi/apei/einj.ko INSTALL drivers/acpi/dptf/dptf_power.ko INSTALL drivers/acpi/ec_sys.ko INSTALL drivers/acpi/nfit/nfit.ko INSTALL drivers/acpi/sbs.ko INSTALL drivers/acpi/sbshc.ko INSTALL drivers/acpi/video.ko INSTALL drivers/ata/acard-ahci.ko INSTALL
查看浮点寄存器 - INCLUDE_HW_FP_SHOW /* Print the list of available registers */ void fppRegListShow(); 查看ACPI - INCLUDE_ACPI_SHOW /* ACPI - Advanced Configuration and Power Management Interface */ /* Print ACPI table information for all tables */ STATUS acpiTablesShow(); /* Show ACPI devices */ STATUS acpiDevicesShow (); /* Show ACPI internal database */ STATUS acpiObjectsShow(); /* Display CPU info obtained by ACPI