【发布时间】:2018-01-14 18:13:59
【问题描述】:
我设法访问了 i386 内核中的 GRUB 多重引导信息结构 (multiboot_info_t),其中有两个字段分别称为 mem_lower 和 mem_upper。如何使用它们来获取可用 RAM 总量(以字节为单位)?
【问题讨论】:
我设法访问了 i386 内核中的 GRUB 多重引导信息结构 (multiboot_info_t),其中有两个字段分别称为 mem_lower 和 mem_upper。如何使用它们来获取可用 RAM 总量(以字节为单位)?
【问题讨论】:
简单地说,你不能。
mem_lower 和 mem_upper 是过时字段,指的是 conventional memory 和 extended memory。
引用specifications:
如果设置了
flags字中的bit 0,则mem_*字段有效。mem_lower和mem_upper表示低位和高位内存的数量,分别以千字节千字节为单位。低位内存从地址0开始,高位内存从地址1开始
兆字节兆字节。较低内存的最大可能值为 640千字节千字节。上层内存返回的值最大是第一个上层内存孔的地址减去1
兆字节兆字节。不保证是这个值。
这段摘录的两个关键方面是:
flags 字段需要在访问mem_* 字段之前进行测试。 mem_lower 和mem_upper 字段对内存漏洞的处理非常糟糕。特别是mem_upper 将扩展内存的第一个连续块的大小保存到第一个孔。 第二点很重要,值得进一步讨论。
虽然可以访问内存本身,但在内存控制器级别1,作为一个连续块,它在内存子系统级别不是连续的(曾经是north-bridge,现在是uncore )。
内存子系统在分配给内存的连续地址范围中创建空洞,方法是简单地不回收特定的子范围 - 从而浪费该内存 - 或者通过将子范围移动到更高的地址。
这种看似奇怪的行为背后的原因深深植根于 IBM PC 的历史演变。
完整的讨论不在主题范围内,但可以列出一个简短的版本。
最初,IBM 为常规内存保留了 1MiB 地址空间中的前 640KiB,其余 384KiB 用于映射 ROM(包括 BIOS ROM)。
请注意,内存控制器不得响应 640KiB 以上的读/写访问,以便它们访问 ROM。
当 1MiB 障碍被打破时(包括或不包括 HMA),从 640KiB 到 1MiB 的范围不能用于向后兼容。
这创建了第一个孔:标准孔。
286 只有一个 24 位地址总线,因此有 16MiB 的地址空间。
同时,ISA bus 已经战胜了MCA bus,并在 IBM PC 兼容硬件中进行。
一些 ISA 扩展卡带有扩展 ROM,标准孔已用尽,在 16MiB 地址空间的末尾保留了一个 1MiB 孔。
我把这个洞称为ISA hole。
从 32 位系统转换到 64 位系统时,PCI(e) 发生了几乎相同的事情,生成 PCI hole。
除了这些漏洞之外,还有一些内存范围可以读/写,但会携带 BIOS 设置的宝贵信息——即ACPI tables。
此类范围不能被操作系统随意覆盖,因此必须向其报告。
所有这一切都在e820 service 中达到顶峰,而不是返回内存大小(根据上面的讨论,这没有意义)它返回一个由范围及其类型组成的 内存映射 (可用、保留、可回收、坏、NVS)。
这也反映在 GRUB multiboot_info_t 结构字段 mmap_* 中,您应该使用它来代替 mem_lower 和 mem_upper,如 OSDev wiki 中所示。
1DIMMs 是通过秩、组、列和行号访问的,但内存控制器通常使这种寻址线性且连续。
【讨论】: