移除恒等内存映射后访问内存触发系统反复重启问题求助
针对你遇到的问题,结合你已经排除的GDT、IDT和重定位因素,下面是几个核心排查方向:
先查直接映射区域的页表覆盖范围
内核重定位到高地址后,别只想着映射代码和数据段,栈(RSP/RBP指向的地址)、当前正在用的临时内存区域也必须被正确映射到高地址虚拟空间。如果栈对应的物理页没在新页表里映射好,移除恒等映射后一访问栈就会触发页错误,没处理的话直接就重启了。
验证方法:移除恒等映射前,打印RSP/RBP的物理地址,核对对应的高地址虚拟页是否已经在页表中完成映射。确认页表切换是否彻底生效
x86-64下加载CR3切换页表后,必须加一条内存屏障指令(比如lfence或mfence)确保页表更新同步到CPU,不然CPU可能还在沿用旧的页表条目。正确的切换代码示例:mov cr3, rax ; rax指向新页表的物理地址 lfence ; 强制同步页表更新排查UEFI残留的内存依赖
就算禁用了中断,UEFI可能留下了依赖恒等映射的硬件状态或内存区域。比如有没有彻底调用ExitBootServices退出UEFI引导服务?有没有还在使用UEFI提供的内存或服务?这些残留都可能导致移除恒等映射后出问题。检查页表项的权限与标志位
直接映射区域的页表项如果权限不对,比如需要写的区域设成了只读,或者忘了设存在位(P位),访问时会触发页错误导致重启。要确保页表项的P位为1,RW位根据内存用途设置,U/S位设为0(内核空间)。验证TLB刷新是否到位
移除恒等映射时,要是没刷新TLB,CPU缓存里可能还留着旧的恒等映射条目,导致地址翻译出错。虽然加载CR3会自动刷新TLB,但可以手动用invlpg指令刷新特定页的TLB,或者确认CR3加载操作确实执行成功。
内容的提问来源于stack exchange,提问作者Jack Zhao

