Memory 如何检测、探测或扫描可用/可访问的物理内存?

Memory 如何检测、探测或扫描可用/可访问的物理内存?,memory,x86,bootloader,osdev,memory-mapping,Memory,X86,Bootloader,Osdev,Memory Mapping,如何彻底检测、探测或扫描可用/可访问的物理内存 我目前正在NASM中为x86_64自定义操作系统制作一个自定义引导加载程序 为了分配包含哪些数据的物理地址,我想确保内存可以免费使用。我已经尝试过BIOS中断int 0x15 eax 0xE820并签出了设备管理器内存资源。 问题是它们都没有完全覆盖 比如说,, 它表示0x0000000000000000~0x000000000009FC00可用。 但严格来说,0x0000000000000000~0x0000000500不可用,因为它存储IVT和

如何彻底检测、探测或扫描可用/可访问的物理内存

我目前正在NASM中为x86_64自定义操作系统制作一个自定义引导加载程序

为了分配包含哪些数据的物理地址,我想确保内存可以免费使用。我已经尝试过BIOS中断int 0x15 eax 0xE820并签出了设备管理器内存资源。 问题是它们都没有完全覆盖

比如说,, 它表示
0x0000000000000000~0x000000000009FC00
可用。 但严格来说,
0x0000000000000000~0x0000000500
不可用,因为它存储IVT和BDA

此外,这里和那里都有PCI孔

我的目标是检测、探测或扫描硬件中可用的全部内存,并制作内存映射,以便区分哪个地址是哪个地址。(下面的示例地图)


我的处理器是英特尔i7-8700K第8代。

您需要多少信息

如果您只想知道哪些区域是可用的RAM;然后,“int0x15,eax=0xE820”(限制BDA将被视为可用)或UEFI的“获取内存映射”功能就是您所需要的。请注意,对于这两种情况,一个/一些区域可能被报告为“ACPI可回收”,这意味着在您完成对ACPI表的解析后(或者如果您不关心ACPT表),RAM将变得可用

如果你想要更多的信息,你需要做更多的工作,因为信息分散在各处。具体而言:

  • ACPI的SRAT表描述了哪些事物(例如,哪些内存区域)位于哪个NUMA域中;ACPI的狭缝表描述了这一点对性能的影响

  • ACPI的SRAT表还描述了哪些内容(例如内存的哪些区域)是“可热插拔”的,并保留为“热插拔”

  • CPU的CPUID指令将告诉您“以位为单位的物理地址大小”。这对于了解您是否/何时试图找到一个合适的物理地址空间区域用于内存映射PCI设备的条非常有用,因为您得到的内存映射太愚蠢,无法告诉您“内存映射PCI设备无法使用”、“内存映射PCI设备可使用”和“内存映射PCI设备使用”之间的区别

  • 解析(或配置)PCI配置空间(必要时与IOMMUs结合使用)会告诉您物理地址空间的哪些区域当前由哪些PCI设备使用

  • 解析“系统管理BIOS”表可以(通过大量工作和“启发式摸索”)告诉您物理地址空间的哪些区域对应于主板上的哪些RAM芯片以及这些RAM芯片的详细信息(类型、速度等)

  • 各种ACPI表(例如MADT/APIC和HPET)可用于确定各种特殊设备(本地APIC、IO APIC、HPET)的位置

  • 您可以假设(部分)以物理地址0xFFFFFFFF结尾的区域将是固件的ROM;并且(通过更多的“启发式摸索”,从固件内存映射报告为“保留”的区域中减去任何特殊设备),您可以确定该区域的大小


如果您执行所有这些操作,您将拥有一个合理完整的映射,描述物理地址空间中的所有内容。

0x0000和0x0500之间的RAM是可用的。没有任何东西可以阻止您重用该内存,甚至用其他东西覆盖该区域,包括实模式中断表。当然,如果您关闭它,则无法使用BIOS中断,BDA中的实模式BIOS状态将消失等。应认为不可用的内存区域是0xA0000处视频RAM下方的EBDA。当操作系统运行时,SMM(系统管理模式)可以读取和写入该区域中的数据。E820是用于旧式BIOS内存映射的机制。如果您使用的是UEFI,那么UEFI具有查询相同类型信息的机制。没有方法询问BIOS正在使用哪些RAM区域。由于我通常启用分页,所以我将使EBDA下0x1000到4KB页面之间的所有内存可用。谢谢Michael Petch。EBDA,我应该避免使用的另一个地址,已经添加。你能回答检测、扫描或探测的方法吗?这将是非常真诚的感谢。我使用的是传统的BIOS方法,而不是UEFI。你可以在这里找到更多关于这一切的信息:其中包括你自己手动探测内存的陷阱哇!令人惊叹的!谢谢你,布伦丹。这是真正的感谢!
0x0000000000000000 ~ 0x00000000000003FF : Real Mode IVT
0x0000000000000400 ~ 0x00000000000004FF : BDA
...
0x0000000000007C00 ~ 0x0000000000007DFF : MBR Load Address
...
0x00000000000B8000 ~ 0x00000000000B8FA0 : VGA Color Text Video Memory
...
0x00000000C0000000 ~ 0x00000000FFFFFFFF : PCI Space