【问题标题】:How does the Operating systems get a memory map of the x86 PC Despite Several Chipsets?尽管有几个芯片组,操作系统如何获得 x86 PC 的内存映射?
【发布时间】:2020-12-02 14:24:24
【问题描述】:

首先:这个问题在这里有重复:

How does a modern operating system like Windows or Linux know the chipset specific memory map?

但是这个问题的答案是关于设备树和 ACPI(用于旧版 PC),没有详细信息我需要编写程序集或 c 代码来利用 ACPI 表中的信息,我现在正在尝试了解旧版 PC首先以及如何解码 ACPI 的表,我尝试进行一些搜索,发现最重要的表是 DSDT,现在我的问题如何解码表中的信息以获得详细的内存映射(范围) 以及获取哪些设备连接到 CPU 以及如何获取内存中 DSDT 的地址?,我尝试进行一些搜索,但我无法理解我认为与此相关的 AML 语言主题......想知道相同的操作系统版本如何在不同的芯片组上运行,有m必须是检测整个地图的动态方式,所以获取整个地图的建议过程也是我的另一个问题

请注意,这是我学习如何直接与裸机硬件设备单独通信的第一步(这是第二步)

谢谢

【问题讨论】:

  • @Joshua,并非所有物理地址空间都由 RAM 支持。其中一些映射到设备控制寄存器、视频内存等。基本上有内存映射类型,操作系统设置的虚拟内存映射将进程内存映射到物理内存(或交换)。以及将数据总线上的地址映射到 RAM 或设备的芯片组。
  • 你会想要像操作系统一样依赖 bios 直到它接管,所以看看 linux 和 bsd 源代码,模仿一下。
  • x86 主板可以有一些半机密的硬件,只有 bios 知道。 BIOS [由主板制造商] 与板上的确切硬件匹配。这被认为是专有的。此外,PC 设备具有一种机制,通过这种机制,各种控制器可以对 bios 启动期间附加的 bios 代码进行扩展。它们允许设备通过 bios int 调用工作。所以,不要吹掉bios。如果没有它的帮助,可能直到启动链的很晚才发现和/或使用某些硬件:引导到操作系统的 bios。
  • 虽然很多硬件可以通过探测 PciE 插槽发现,并通过 PnP 机制呈现出来,但一些硬件配置信息是硬连线到 bios 中的。 [仅] ACPI 接口可以发现该硬件。
  • 如果您熟悉 U-Boot,您可以查看它的源代码,并且至少重新创建了几个 (x86) 平台以从头开始拥有 ACPI 表。最新的 ACPI 规范非常有用(请参阅 uefi.org)。

标签: c assembly osdev bare-metal acpi


【解决方案1】:

让我们把它分成 3 个不同的问题。

如何获取内存中DSDT的地址?

固件提供了一个指向(一个或两个)ACPI 表的指针,其中包含所有其他表的索引。这些表是 RSDT(根系统描述符表)和 XSDT(扩展根系统描述符表);它们之间唯一真正的区别是 XSDT 支持 64 位地址(并且应该尽可能使用),而旧的 RSDT 不支持(并且应该被视为“已弃用”并且仅用作现代 64 位操作的后备)系统)。这些表主要提供所有其他表的标识符和地址;因此,如果您想查找特定表(例如 DSDT),您可以在索引中搜索标识符(例如 4 个 ASCII 字符“DSDT”)并找到包含表物理地址的条目。

指向索引的指针包含在称为 RSDP(根系统描述指针)的特殊结构中;对于不同类型的固件,可以以不同的方式找到它。对于 BIOS,您必须搜索物理内存的一些特定区域以寻找特殊结构(具有特殊签名和有效校验和);对于 UEFI,您只需询问固件(并避免“缓存冲击”搜索)。

这都是 ACPI 规范描述的(比较清楚的),包括如何找到 RSDT(例如“根系统描述指针(RSDP)”部分),包括所有结构和表的格式,以及含义和所有领域的目的。

如何解码 DSDT 中的信息?

因为启动后情况可能会发生变化(由于热插拔支持等);静态表不能用于某些事情,ACPI 通过定义一种称为 ASL(ACPI 汇编语言)的特殊语言来解决这个问题(并产生更多问题),该语言被编译成称为 AML(ACPI 机器语言)的可移植字节码。

DSDT 包含此 AML。

要理解它,您需要一个 AML 解释器来执行 DSDT 中包含的 AML。

这是“非常具有挑战性的”——要自己动手,您可能需要花费数月的时间研究 ACPI 规范(以及数年的时间来解决不同计算机中的错误)。大多数人移植了一个名为 ACPICA 的开源实现(最初由英特尔创建)(参见 https://acpica.org/)。

很遗憾;能够执行 AML 只是第一步。您还需要了解 ACPI 的命名空间、AML 提供了哪些功能/方法以及它们应该做什么。使情况变得更糟; ACPI 的 AML 期望知道操作系统是什么,然后启用/禁用各种功能并更改其行为以适应操作系统(取决于它被告知操作系统是什么);并且通常 AML 识别的唯一操作系统是 Windows 版本,如果您告诉它其他内容,它会禁用各种功能,因此大多数操作系统只是撒谎并说它们是 Windows 版本,因此 AML 不会提供残缺的其能力的子集。然而; “每个版本的 Windows 做了什么”(以及 AML 对每个特定版本的 Windows 的行为方式)是一场可怕的无证(根据 ACPI 规范)灾难。幸运的是; ACPICA 还隐藏了大部分这种痛苦(对于携带 ACPICA 的人)。

如何获取详细的内存映射(范围)以及哪些设备连接到 CPU?

大多数情况下你不会。具体来说,您不只是在一个不错的步骤中“获得详细的内存映射”。

相反;您首先从固件中获取一些有关物理内存的最小信息(来自 BIOS 的 int 0x15, eax=0xE820,或来自 UEFI 的 GetMemoryMap())。然后,您使用各种不同的来源为该最小信息添加更多细节,包括但不限于CPUID 指令(物理地址实际具有多少位)、ACPI“APIC/MADT”表(用于 IO APIC 和本地 APIC 地址)、ACPI“EDT/HPET”表(用于 HPET 地址)、ACPI“MCFG”表(用于 PCI Express 内存映射配置空间区域的地址)、ACPI“SRAT”表(用于 NUMA内存区域和“热插拔 RAM”信息),以及可能(可选)SMBIOS 表(如果您关心安装什么类型的 RAM 等)。

从静态/不变的来源获得您想要的所有信息后;您切换到“阶段 2”,这涉及不断管理内存映射并尝试在找到来自各种设备的信息时使其保持最新(并通过热插拔事件进行修改)。这就是能够执行 AML(从 DSDT,使用您的 AML 解释器)变得重要的地方。它还涉及特定于总线的方法(例如,扫描 PCI 总线并从每个 PCI 设备的 BAR/基地址寄存器中提取信息)。

请注意,这不仅仅是填写内存映射的详细信息。最好是发现设备使用的资源,包括 IO 端口、IRQ 线路、DMA 通道(而不仅仅是物理地址空间的区域)。

另外请注意,如果/当您拥有能够使用该信息“驱动”设备的设备驱动程序时,您才真正了解有关设备的信息。如果你不这样做,那么你拥有的内存映射只会说“保留”,你不会知道为什么,但你可能没有理由关心为什么。

最后说明

乍一看,这“非常令人生畏”。不要担心——你可以(而且应该)从小处着手,直到很久以后才忽略其中的大部分内容。仅使用固件中有关物理内存的最少信息,您就可以做很多事情;并添加代码来完成几乎所有其他事情,如果/当有一天它对你的操作系统真的很重要。

【讨论】:

  • 很好,但是 ACPI 规范的链接在哪里?您在这里说的很好,但规范通过图片和 ASL 示例详细说明了这一点。
猜你喜欢
  • 2020-09-01
  • 1970-01-01
  • 2016-07-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2012-07-06
  • 2021-10-01
相关资源
最近更新 更多