ACPI on ARMv8 Servers

news2024/9/29 15:33:40

文章目录

  • 前言
  • 一、Why ACPI on ARM?
  • 二、Kernel Compatibility
  • 三、Relationship with Device Tree
  • 四、Booting using ACPI tables
  • 五、ACPI Detection
  • 六、Device Enumeration
  • 七、Driver Recommendations
  • 参考资料

前言

ARM64处理器除了可以用设备树(DT)描述系统中设备的硬件,提供硬件抽象表述,还可以用ACPI(Advanced Configuration and Power Interface),比如:

# ls -l /sys/firmware/
acpi/       devicetree/ dmi/        efi/        fdt
# ls -l /sys/firmware/acpi/tables/
APIC     BGRT     data/    DSDT     dynamic/ FACP     GTDT     IORT     MCFG     PPTT     SPCR     SSDT

ARM64处理器兼容设备树和ACPI两者模式,但在内核启动时ACPI和DT只能选择一种启动方式。
ARM在移动端、嵌入式领域通常都是uboot+DT,ARM在服务器和桌面领域时,可以选择UEFI+ACPI,ACPI相比于DT,ACPI不但实现了硬件设备的静态抽象,还实现了硬件行为的动态抽象,同时ACPI基本占据了服务器生态。

比如我手中的飞腾处理器+麒麟桌面操作系统,就是采用和UEFI+ACPI:

[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi: EFI v2.70 by EDK II
[    0.000000] efi:  SMBIOS=0xeb790000  SMBIOS 3.0=0xeb770000  ACPI 2.0=0xec000000  MEMATTR=0xdeaefa98  MEMRESERVE=0xd5909e98
[    0.000000] secureboot: Secure boot disabled
[    0.000000] cma: Reserved 32 MiB at 0x00000000fa000000
[    0.000000] ACPI: Early table checksum verification disabled
[    0.000000] ACPI: RSDP 0x00000000EC000000 000024 (v02 PHYLTD)
[    0.000000] ACPI: XSDT 0x00000000EBFF0000 00006C (v01 PHYLTD PHYTIUM. 00000001 GGCL 00010000)
[    0.000000] ACPI: FACP 0x00000000EBFE0000 000114 (v06 PHYLTD PHYTIUM. 00000001 PHYT 00000001)
[    0.000000] ACPI: DSDT 0x00000000EBF70000 0014AC (v02 PHYLTD PHYTIUM. 00000001 INTL 20190509)
[    0.000000] ACPI: GTDT 0x00000000EBFD0000 000098 (v02 PHYLTD PHYTIUM. 00000001 PHYT 00000001)
[    0.000000] ACPI: IORT 0x00000000EBFC0000 000080 (v00 PHYLTD PHYTIUM. 00000001 PHYT 00000001)
[    0.000000] ACPI: APIC 0x00000000EBFB0000 0002D8 (v04 PHYLTD PHYTIUM. 00000001 PHYT 00000001)
[    0.000000] ACPI: MCFG 0x00000000EBFA0000 00003C (v01 PHYLTD PHYTIUM. 00000001 PHYT 00000001)
[    0.000000] ACPI: SPCR 0x00000000EBF90000 000050 (v02 PHYLTD PHYTIUM. 00000001 PHYT 00000001)
[    0.000000] ACPI: SSDT 0x00000000EBF80000 000515 (v02 PHYLTD PHYTIUM. 00000001 INTL 20190509)
[    0.000000] ACPI: PPTT 0x00000000EBF60000 000396 (v01 PHYLTD PHYTIUM. 00000001 PHYT 00000001)
[    0.000000] ACPI: BGRT 0x00000000EBF50000 000038 (v01 GWTLTD GWTLBGRT 00010000 GGCL 00010000)

ACPI可用于ARMv8通用服务器,其设计符合ARM SBSA(服务器基础系统架构)和SBBR(服务器基础引导要求)规范。

ARMv8内核实现了ACPI 5.1版或更高版本的精简硬件模式。在该模式中,没有使用硬件实现 ACPI 固定硬件接口,而是使用对应的软件替代方案。并且设置HW_REDUCED_ACPI 标志位
规范及其引用的所有外部文档的链接由UEFI论坛管理。请参考:https://uefi.org/specifications

根据 Linux 文档说明,对于 ARM64 上的 ACPI,表格分为如下类型:

Required: DSDT, FADT, GTDT, MADT, MCFG, RSDP, SPCR, XSDT

Recommended: BERT, EINJ, ERST, HEST, PCCT, SSDT

Optional: BGRT, CPEP, CSRT, DBG2, DRTM, ECDT, FACS, FPDT, IBFT, IORT, MCHI, MPST, MSCT, NFIT, PMTT, RASF, SBST, SLIT, SPMI, SRAT, STAO, TCPA, TPM2, UEFI, XENV

Not supported: BOOT, DBGP, DMAR, ETDT, HPET, IVRS, LPIT, MSDM, OEMx, PSDT, RSDT, SLIC, WAET, WDAT, WDRT, WPBT

ARM64服务器处理器通常要求实现上述 Required 表格这一项内容,其它表格项可由固件和OS根据需要实现。

如果ARMv8系统不符合SBSA和SBBR的要求,或者不能使用所需的ACPI规范中定义的机制进行描述,则ACPI可能不太适合该硬件。

接下来描述ARMv8系统上ACPI与Linux之间的交互。

一、Why ACPI on ARM?

在检查ACPI和Linux之间的接口细节之前,了解ACPI被使用的原因是很有用的。毕竟,Linux中已经存在一些描述不可枚举硬件的技术(比如设备树)。
这篇博文:https://www.secretlab.ca/archives/151,概述了ARMv8服务器上ACPI背后的原因。总结如下所示:
(1)ACPI的字节码(AML)允许平台对硬件行为进行编码,而DT明确不支持这一点。对于硬件供应商来说,能够编码行为是支持新硬件上的操作系统版本的关键工具。
(2)ACPI的OSPM定义了一个电源管理模型,该模型将平台允许做的事情限制在一个特定的模型中,同时还提供了硬件设计的灵活性。
(3)在企业服务器环境中,ACPI已经建立了当前在生产系统中使用的绑定(例如RAS)。DT没有。这样的绑定可以在DT中定义,但这样做意味着ARM和x86最终将在固件和内核中使用完全不同的代码路径。
(4)选择单一接口来描述平台和操作系统之间的抽象非常重要。如果硬件供应商想要支持多个操作系统,则不需要同时实现DT和ACPI。而且,在单个接口上达成一致,而不是将其分散到每个操作系统的接口中,有助于实现更好的整体互操作性。
(5)新的ACPI管理过程运行良好,Linux现在与硬件供应商和其他操作系统供应商处于同一位置。事实上,再也没有任何理由认为ACPI只属于Windows,或者在这一领域Linux在任何方面都是微软的次要产品。ACPI管理向UEFI论坛的转移极大地开放了规范开发过程,目前,ACPI的大部分更改都是由Linux驱动的。

ACPI使用的关键是 the support model 。对于一般的服务器,硬件行为的责任不能仅仅是内核的领域,而是必须在平台和内核之间划分,以允许随着时间的推移进行有序的更改。ACPI使操作系统无需了解硬件的所有细节,从而无需将操作系统单独移植到每个设备。它允许硬件供应商对电源管理行为负责,而不依赖于不受其控制的OS发布周期。

ACPI重要的一个原因是硬件和操作系统供应商已经制定出支持通用计算生态系统的机制(The infrastructure、 the bindings 、 the processes等都是现成的)。当使用纵向集成设备时,虽然完全符合Linux的要求,但没有很好的流程来支持服务器供应商的需要。Linux有可能通过DT实现这一目标,但这样做实际上只是复制了一些已经有效的东西。ACPI已经满足了硬件供应商的需求,微软不会在DT上合作,硬件供应商最终仍然会提供两个完全独立的固件接口:一个用于Linux,一个用于Windows。

对于ARM64,ACPI相比于DT来说跟适合用于服务器领域。

二、Kernel Compatibility

ACPI的主要动机之一是标准化,并利用它为Linux内核提供向后兼容性。在服务器市场上,软件和硬件经常被长期使用。ACPI允许内核和固件在一个一致的抽象层上达成一致,即使在硬件或软件发生变化时,该抽象层也可以随时间保持。只要支持抽象层,就可以更新系统,而不必更换内核。
ACPI充当操作系统和系统固件之间的接口层:
在这里插入图片描述
当Linux驱动程序或子系统第一次使用ACPI实现时,根据定义,它最终需要特定版本的ACPI规范–它是基准。ACPI固件必须继续工作,即使它可能不是最优的,因为最早的内核版本首先提供对ACPI基准版本的支持。可能需要额外的驱动程序,但添加新功能(例如,CPU电源管理)不应破坏较旧的内核版本。此外,ACPI固件还必须与最新版本的内核一起工作。

三、Relationship with Device Tree

ARMv8驱动程序和子系统中的ACPI支持在编译时不应与DT互斥,即两者编译兼容,两者可同时存在,再启动阶段选择一种。

在引导时,内核将仅使用一种描述方法,这取决于从引导加载器传递的参数(包括内核引导参数)。

无论使用DT还是ACPI,内核必须始终能够使用任一方案启动(在编译时启用两种方案的内核中)。

因此驱动可以 DT 和 ACPI 两种启动方式,如下所示:

static const struct of_device_id static_replicator_match[] = {
	{.compatible = "arm,coresight-replicator"},
	{.compatible = "arm,coresight-static-replicator"},
	{}
};

MODULE_DEVICE_TABLE(of, static_replicator_match);

#ifdef CONFIG_ACPI
static const struct acpi_device_id static_replicator_acpi_ids[] = {
	{"ARMHC985", 0}, /* ARM CoreSight Static Replicator */
	{}
};

MODULE_DEVICE_TABLE(acpi, static_replicator_acpi_ids);
#endif

static struct platform_driver static_replicator_driver = {
	.probe          = static_replicator_probe,
	.remove         = static_replicator_remove,
	.driver         = {
		.name   = "coresight-static-replicator",
		/* THIS_MODULE is taken care of by platform_driver_register() */
		.of_match_table = of_match_ptr(static_replicator_match),
		.acpi_match_table = ACPI_PTR(static_replicator_acpi_ids),
		.pm	= &replicator_dev_pm_ops,
		.suppress_bind_attrs = true,
	},
};

of_match_table 用于从DT启动匹配硬件设备。
acpi_match_table 用于从ACPI启动匹配硬件设备。

驱动设备有套方案,一套用于解析DT,一套用于解析ACPI,从解析的数据中获取相应的硬件属性。

ARM在移动端和嵌入式领域通常都是uboot+DT。
ARM在服务器和桌面领域时,可以选择UEFI+ACPI。

四、Booting using ACPI tables

在ARMv8上将ACPI表传递给内核的唯一定义方法是通过UEFI系统配置表。正因为如此,这意味着ACPI仅在通过UEFI引导的平台上受支持。

当ARMv8系统启动时,它可以有DT信息、ACPI表,或者在一些非常不寻常的情况下,两者都有。如果没有使用命令行参数,内核将尝试使用DT进行设备枚举;如果不存在DT,内核将尝试使用ACPI表,但前提是它们存在。如果两者都不可用,内核将无法启动。如果在命令行上使用acpi=force,内核将尝试首先使用acpi表,但如果没有acpi表则返回DT。

通过在内核命令行上传递ACPI=off,可以 disable ACPI表的处理;这是默认行为。

五、ACPI Detection

驱动程序应该通过检查ACPI_HANDLE的空值、检查.of_node或设备结构中的其他信息来确定其probe()类型。

在非驱动程序代码中,如果需要在运行时检测ACPI的存在,请检查acpi_disabled的值。如果未设置CONFIG_ACPI,acpi_disabled将始终为1。

六、Device Enumeration

ACPI中的设备描述应使用标准认可的ACPI接口。这些可能包含比通常通过设备树描述为同一设备提供的信息更少的信息,这也是ACPI有用的原因之一:驱动程序考虑到它可能没有关于设备的详细信息,而是使用合理的默认值。如果在驱动程序中做得适当,硬件可以随着时间的推移而改变和改进,而不必改变驱动程序。

时钟就是一个很好的例子。在DT中,需要指定时钟,驱动程序需要将其考虑在内。在ACPI中,假设UEFI将使设备处于合理的默认状态,包括任何时钟设置。如果出于某种原因,驱动程序需要更改时钟值,这可以通过ACPI方法完成;驱动程序需要做的只是调用方法,而不关心方法需要做什么来改变时钟。随着时间的推移,可以通过改变ACPI方法而不是驱动程序来改变硬件。

在DT中,驱动程序设置时钟所需的参数称为“bindings”;在ACPI中,这些参数称为“Device Properties”,并通过_DSD对象提供给驱动程序。

七、Driver Recommendations

为驱动程序添加ACPI支持时,请勿删除任何DT处理。同一设备可用于许多不同的系统。请尝试构造驱动程序,使其成为数据驱动的。也就是说,根据默认值设置一个包含每个设备内部状态的结构。驱动程序 probe 函数必须发现任何其他内容。然后,让驱动程序的其余部分对该结构的内容进行操作。这样做应该允许ACPI和DT功能之间的大部分差异保持在 probe 函数的本地,而不是分散在整个驱动器中。例如:

static int device_probe_dt(struct platform_device *pdev)
{
       /* DT specific functionality */
       ...
}

static int device_probe_acpi(struct platform_device *pdev)
{
       /* ACPI specific functionality */
       ...
}

static int device_probe(struct platform_device *pdev)
{
       ...
       struct device_node node = pdev->dev.of_node;
       ...

       if (node)
               ret = device_probe_dt(pdev);
       else if (ACPI_HANDLE(&pdev->dev))
               ret = device_probe_acpi(pdev);
       else
               /* other initialization */
               ...
       /* Continue with any generic probe operations */
       ...
}

一定要在驱动程序中将MODULE_DEVICE_TABLE条目放在一起,以明确从DT和ACPI探测驱动程序的不同名称:

static struct of_device_id virtio_mmio_match[] = {
        { .compatible = "virtio,mmio", },
        { }
};
MODULE_DEVICE_TABLE(of, virtio_mmio_match);

static const struct acpi_device_id virtio_mmio_acpi_match[] = {
        { "LNRO0005", },
        { }
};
MODULE_DEVICE_TABLE(acpi, virtio_mmio_acpi_match);

参考资料

https://static.lwn.net/kerneldoc/arm64/acpi_object_usage.html
https://static.lwn.net/kerneldoc/arm64/arm-acpi.html
https://www.linaro.org/blog/when-will-uefi-and-acpi-be-ready-on-arm/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/353560.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

V90伺服驱动器设置IP地址和PN设备名称的具体方法(2种)

V90伺服驱动器设置IP地址和PN设备名称的具体方法(2种) 1. 通过V-ASSISTANT软件进行配置 首先下载并安装V-ASSISTANT软件,然后将V90通过网线连接到电脑上,注意此时电脑使用的网卡,不能选择无线网卡, SINAMICS-V90伺服调试软件V-ASSISTANT_V1.07.01 打开V-ASSISTANT软件,…

Java 基础面试题——面向对象

目录1.面向对象和面向过程有什么区别?2.面向对象的有哪些特征?3.静态变量和实例变量有什么区别?4.Java 对象实例化顺序是怎样的?5.浅拷贝和深拷贝的区别是什么?5.1.浅拷贝5.2.深拷贝5.3.总结6.Java 中创建对象的方式有哪几种&…

Qt代码单元测试以及报告生成

简介 单元测试是所有测试中最底层的一类测试,是第一个环节,也是最重要的一个环节,是唯一一次有保证能够代码覆盖率达到100%的测试,是整个软件测试过程的基础和前提,单元测试防止了开发的后期因bug过多而失控&#xff0…

< elementUi 组件插件: el-table表格拖拽修改列宽及行高 及 使用注意事项 >

elementUi 组件插件: el-table拖拽修改列宽及行高 及 使用注意事项👉 资源Js包下载及说明👉 使用教程> 实现原理> 局部引入> 全局引入 (在main.js中)👉 注意事项往期内容 💨&#x1f4…

Android Studio adb命令

Android Studio在IP连接142的手机进行无线调试 adb tcpip 5555 // 端口 adb shell ifconfig wlan0 //查看ip adb connect 192.168.1.142:5555 当已经连接上142这个ip,还想再连接其他143这个ip 方法如下: adb devices -l 查看当前设备 adb …

直接下载docker镜像包

这周正在做APIcat的企业版研发,准备适配阿里云的计算巢提供企业直接云安装的功能,顺便把原来写过的一个直接下载docker镜像包的小程序挂到了Gitee上面,有需要的可以点击下载 https://gitee.com/extrame/dgethttps://gitee.com/extrame/dget …

安灯呼叫系统助力企业实现精益管理

在当前的生产企业管理过程当中,生产现场难免会出现各种异常情况影响生产,乳设备需要机修、品质问题、物料呼叫等各种情况,在以往这些问题出现过后处理的方式都是些申请单,由人工到各个部门去给领导签字,浪费大量时间沟…

【Unity VR开发】结合VRTK4.0:远距离抓取物体

语录: 我们都生活在阴沟里,但仍有人仰望星空。 前言: 空间场景中的一个常见问题是试图抓取一个无法触及或太远而无法到达的对象。VRTK提供了一种简单的方法来实现这种技术(Interactions.PointerInteractors.DistanceGrabber&…

上市公司每股社会贡献值(数据+代码)(2000-2020年)

数据来源:自我整理 时间跨度:2000-2020年 区域范围:上市公司 指标说明: 每股社会贡献值( 净利润所得税费用营业税金及附加支付给职工以及为职工支付的现金本期应付职工薪酬-上期应付职工薪酬财务费用捐赠-排污费及清理费) / 期…

MySQL服务器体系架构 执行原理

前言 前边我们了解了MySQL采用客户端/服务器架构,用户通过客户端程序发送增删改查需求,服务器程序收到请求后处理,并且把处理结果返回给客户端。这篇文章主要看下MySQL服务端是如何处理客户端的请求,感兴趣的小伙伴们可以参考借鉴…

【单目标优化算法】烟花优化算法(Matlab代码实现)

👨‍🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜…

定时器设计

定时器设计 定时器应用: 游戏的Buff实现,Redis中的过期任务,Linux中的定时任务等等心跳检测,如服务器接收队列满了,tcp客户端会定时探测是否能够发送数据 定时器数据结构选取要求: 需要快速找到到期任务…

防火墙设置实验(12)

预备知识防火墙基本原理 防火墙是一种访问控制技术,位于可信与不可信网络之间,通过设置一系列安全规则对两个网络之间的通信进行控制,检测交换的信息,防止对信息资源的非法存取和访问。防火墙分为软防火墙和硬防火墙,一…

关于分布式的一些基础知识

1、分布式锁 (ngix,zoomkeeper,raft,kafka) 在单机场景下,可以使用语言的内置锁来实现进程或者线程同步。但是在分布式场景下,需要同步的进程可能位于不同的节点上,那么就需要使用分布式锁。 为了保证一个方法或属性在高并发情况下的同一时间…

【面试题】前端春招第二面

不容错过的一些面试题小细节,话不多说,直接看题~大厂面试题分享 面试题库后端面试题库 (面试必备) 推荐:★★★★★地址:前端面试题库HTML/CSS/Javascript/ES篇(1)标准盒模型和怪异盒…

k8s集群概念组件简介

一、Kubernetes 集群概述1.2 Kubernetes 资源资源用途服务(Service)Kubernetes 使用服务在一组 pod 上公开正在运行的应用程序。ReplicaSetKubernetes 使用 ReplicaSet 来维护恒定的 pod 号。Deployment维护应用程序生命周期的资源对象。1.3 Kubernetes …

重生之我是赏金猎人-SRC漏洞挖掘(七)-看我如何从FUZZ到SRC官网XSS

0x01 前奏 本文来自:RGM78sec 截至发稿,vuln早已修复 前不久在挖掘某SRC时,偶然在该SRC官网的编辑器发现了一个接口。 起初以为是任意文件包含能RCE了,后来测试发现只是拼接读取了远程资源站的图片,原本都想着放弃…

TypeScript(二)基本数据类型

前言 距离上篇博客已有两年了,对TS也有了一定的认识,于是计划继续更新系列文章 基本数据类型 在JS中,基本数据类型有:Boolan(布尔),Number(数字),String&a…

什么是事务?Mysql事务怎么用?Mybatis怎么操作事务的?Spring呢?快进来看看

目录 一、计算机中的事务 1. 概念 2.事务的ACID特性 3.事务类型 1)手动事务 2)自动事务 4.为什么需要事务? 5.优点 二、MySQL事务 1.语法格式: 2.关闭自动提交,开启新事务 3.开启自动提交,关闭事务控制 三、Mybatis事务 Mybatis开关事务控…

Meta AR眼镜主管:正开发史无前例的AR,但要解决很多困难

前不久,Meta CTO Andrew Bosworth在个人博客上“怒斥”公司内部不够专注,应该将资源投入在有核心竞争力、高投资回报率的业务上,而不是开发取悦用户却不赚钱的产品。尽管删除一些小众功能后,用户可能会不满,但为了让Me…