从零写OS(三):进入 64 位,CPU 真正醒了
上一章切到了保护模式,32 位,最多 4GB 内存。 听起来挺多,但现代系统动不动就几十 GB 内存,4GB 根本不够用。所以还得再往前走一步:进入长模式(Long Mode,x86_64 的 64 位工作模式,支持 128TB 虚拟地址空间)。 现在跑在你电脑上的 Linux、macOS、Windows,全都在长模式里。 长模式比保护模式多了什么 最直接的:寻址空间从 4GB 扩展到理论上的 16EB(16 × 10¹⁸ 字节),实际当前 CPU 支持 128TB,够用很久了。 但更重要的变化是强制引入了分页(Paging,把物理内存切成固定大小的页,通过页表做虚拟地址到物理地址的映射)。 保护模式下分页是可选的,长模式下分页是必须开启的。没有页表,CPU 根本不让你进长模式。 先建页表 切换之前,必须在内存里建好页表(Page Table,记录虚拟地址到物理地址映射关系的数据结构)。 x86_64 用四级页表,一个虚拟地址的翻译路径是: 虚拟地址 → PML4 → PDPT → PD → PT → 物理地址 每级都是一张表,每张表 512 项,每项 8 字节。 启动阶段不需要映射所有内存,先映射前 2MB 就够了——把四张表放在物理地址 0x1000 开始的位置,让虚拟地址和物理地址一一对应(恒等映射,虚拟地址和物理地址相同,是启动阶段最简单的映射策略)。 切换步骤 在 32 位保护模式下,按顺序操作: 建好页表,把 PML4 地址写入 CR3(页表根寄存器) 开启 PAE(Physical Address Extension,物理地址扩展,让 32 位系统支持超过 4GB 的物理地址,长模式必须开启):CR4.PAE=1 设置 EFER.LME=1(通过 MSR 寄存器(Model Specific Register,CPU 内部的特殊寄存器,用 rdmsr/wrmsr 读写)开启长模式使能位) 开启分页:CR0.PG=1,CPU 正式进入长模式兼容态 far jump 跳入 64 位代码段,彻底进入 64 位模式 顺序不能乱。尤其是第 3 步必须在开启分页之前,不然 CPU 会拒绝。 ...