You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86_64 UEFI系统内存未按预期恒等映射问题咨询

问题描述

我正在开发一款小型x86_64 UEFI操作系统,获取内存映射并退出Boot Services后,打印内存映射时发现所有条目均将某一物理地址映射到虚拟地址0,内存映射前几项显示物理地址重复且虚拟地址全为0。

我使用的内存描述符结构如下:

#[repr(C)]
#[derive(Clone, Copy)]
pub struct MemoryDescriptor {
    pub t: MemoryType,
    pub physical_start: *const c_void,
    pub virtual_start: *const c_void,
    pub number_of_pages: u64,
    pub attribute: u64,
}

#[repr(u32)]
#[derive(Clone, Copy, Debug)]
pub enum MemoryType {
    ReservedMemoryType = 0,
    LoaderCode,
    LoaderData,
    BootServicesCode,
    BootServicesData,
    RuntimeServicesCode,
    RuntimeServicesData,
    ConventionalMemory,
    UnusableMemory,
    ACPIReclaimMemory,
    ACPIMemoryNVS,
    MemoryMappedIO,
    MemoryMappedIOPortSpace,
    PalCode,
    PersistentMemory,
    UnacceptedMemoryType,
    MaxMemoryType,
}

我已确认内存映射的遍历逻辑正确(按GetMemoryMap返回的描述符大小递增指针,而非结构体大小),但仍无法理解该现象。UEFI规范说明内存会被恒等映射,这是否意味着内存映射中物理地址应与虚拟地址相等?我是否遗漏了什么?该问题在QEMU及真机(Surface Pro 8)上均会出现。我还尝试通过CR3地址查看页表,但似乎操作有误或页表映射异常,因为仅Level 4表的首个条目存在,且指向的Level 3表无有效条目。

原因分析与解决方法

核心原因:内存描述符结构体定义不符合UEFI规范

UEFI标准的EFI_MEMORY_DESCRIPTOR结构中,32位的内存类型字段后必须紧跟一个32位的预留字段,而你定义的MemoryDescriptor直接在MemoryType(u32类型)后衔接了physical_start(u64类型),没有补充这个预留字段,导致结构体内存布局完全错位,读取到的所有字段值都是错误的——这就是虚拟地址全为0、物理地址重复的根本原因。

具体修正步骤

  1. 调整MemoryDescriptor结构体定义,补充UEFI要求的预留字段:
#[repr(C)]
#[derive(Clone, Copy)]
pub struct MemoryDescriptor {
    pub t: MemoryType,
    pub reserved: u32, // 新增UEFI规范要求的32位预留字段
    pub physical_start: *const c_void,
    pub virtual_start: *const c_void,
    pub number_of_pages: u64,
    pub attribute: u64,
}
  1. 验证结构体大小:修正后的结构体大小应与GetMemoryMap返回的描述符大小一致(UEFI规范中该结构固定为40字节)。
  2. 重新读取内存映射:修正结构后,物理地址与虚拟地址会显示正确的恒等映射(UEFI在Boot Services阶段确实保证物理地址和虚拟地址一一对应)。

页表异常的补充说明

之前观察到的页表异常是内存映射读取错误导致的误解:UEFI在Boot Services阶段维护的页表是完整的恒等映射,只要内存描述符读取正确,后续基于正确映射构建自定义页表即可。如果需要检查CR3,注意要在退出Boot Services前读取,且访问页表时需将页表的物理地址转换为虚拟地址(因为UEFI的恒等映射此时仍生效)。

内容的提问来源于stack exchange,提问作者gillo04

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 09:11:18