AML工作原理快速调研

馋奶兔 提交于 2020-03-21 02:30:01

3 月,跳不动了?>>>

前两天邀请人做这个文档的Review:in nek:评审邀请:Linux内核软件架构基础,有读者告诉我我对AML的理解有误。我找我们做BIOS的兄弟确认了一把,把逻辑链放在这里。

先定义一下问题:ACPI是一种定义BIOS和OS之间接口的方法。和其他一些方法,比如Device Tree(简称DTS),不同,ACPI支持函数接口,也就是说,OS可以通过“调用”接口给出的函数实现功能。这种所谓的“调用”,有几种可能:

  1. BIOS中给定一个数据结构,整体描述了一个函数,这个函数本身就是CPU的本地汇编。BIOS把整个数据接口传递到OS管理的内存空间,OS直接调用这个空间中的函数。
  2. BIOS中给定一个数据结构,整体描述了一个函数,这个函数本身就是CPU的本地汇编。这个数据结构留在BIOS控制的内存中,传递给OS一个指针,OS远程调用这个指令的地址,完成请求。
  3. BIOS中实现了一个本地函数,然后把这个函数的位置和格式告知OS,OS通过一个统一的接口把函数的标识和请求的参数传递给BIOS,BIOS内部完成调用,然后把结果通知OS。
  4. BIOS给定一个数据结构,整体描述了一个函数,用一种平台无关的格式标识,这个数据结构整体提供给OS,OS上有一个解释器,解释执行这个平台无关的格式,实现对功能的执行。

用图来表达,区别如下:

严格来说,前两个方案没有什么区别,内存这东西,都是一样的内存。什么你的我的,其实都是我的!:)我们差不多就可以了。

我自己不是做BIOS的,这部分的理解是做BIOS的兄弟给我介绍的,当时我的理解是第二种形式。但这位读者告诉我,这个理解不对,所以我回去再咨询了几个做BIOS的兄弟,他们给了我另外一些可以确认的证据,我通过这个文档把这些证据摆出来。

首先看定义,这里是一个DSDT中实现的AML的定义:

                Method (_STA, 0, NotSerialized)  // _STA: Status
                {
                    If ((TPEN == One))
                    {
                        Return (0x0F)
                    }
                    Else
                    {
                        Return (Zero)
                    }
                }

我们直接看它的DSDT编译结果:

0000a670: 0800 0000 005c 5f53 422e 5350 4930 0079  .....\_SB.SPI0.y
0000a680: 00a4 5242 5546 1415 5f53 5441 00a0 0a93  ..RBUF.._STA....
0000a690: 5450 454e 01a4 0a0f a103 a400 1048 065f  TPEN.........H._
0000a6a0: 5342 5f5b 8240 0649 5049 3008 5f48 4944  SB_[.@.IPI0._HID

可以看到_STA函数访问了TPEN,这个参数是直接在DSDT表中的,至少说明一点,至少在呈现为DSDT表形态的时候,这是一个解释形的语言,而不是被编译成了二进制。

我们再找一个证据,这个是BIOS的同事推荐给我的一个文档:https://acpica.org/sites/acpica/files/asl_tutorial_v20190625.pdf,其中的表述如下:

这说明OS中是存在一个解释器,AML是一个类似Java的Bincode,通过解释器建立数据结构,从而可以解释执行。

所以我们的逻辑碎片只剩下最后一环:看看Linux内核中的具体实现:

内核对这个函数的调用是这样的:

		status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta);
		if (ACPI_SUCCESS(status) && sta)
			return 1;

acpi_evaluate_integer()实际调用acpi_evaluate_object()。这个实现在./drivers/acpi/acpica/nsxfeval.c中,其最终的实现是这个函数:acpi_ns_evaluate(info)->acpi_ps_execute_method(info)->acpi_ps_parse_aml(),跟踪进去,就可以看到针对每个opcode的执行过程。

换句话说,内核中确实带了一个解释器来执行这个函数,至于这个函数的bincode到底在BIOS的内存空间中还是已经拷贝到内核的内存空间中,这个已经不重要了。

老实说,我个人对UEFI和ACPI的编程风格素来没有好感,简直就是反人类,这回跟踪完这个AML的实现,我更没有好感了。但谁让它在服务器领域发展的时间长呢。这个世界就是这么无奈。这也告诉我们当架构师的:

  1. 技术优美抵不过资源投入,虽然两者都是控制要素,但前者难暴力投入,后者可以
  2. 架构前期不要作妖,前期再轻微的决定,后面都是要生要死的大限制

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!