Skip to content

调试现场:页表、开关顺序、L/D 位、重定位

进长模式这一段,坑几乎全在"顺序"和"标志位"上。下面是几个真实调出来的。

症状一——CR0.PG 一置位,当场三重故障重启。 最高频的原因是页表没搭对:要么某层表没清零(残留垃圾被 CPU 当有效项去查,查到 0 触发缺页),要么 PD 的大页项漏了 Large(PS)位,CPU 继续往下一层查一个不存在的 PT,当场缺页。定位:在置 CR0.PG 那条设断点,x/4gx 0x3000PD[0..3] 是不是 0x..83(带 PS 位)的 2MB 页;x/1gx 0x1000PML4[0] 是不是 0x2003

症状二——置 EFER.LME 就崩,或 CR0.PG 置位时 #GP。 顺序错了。常见是把 CR0.PG 放在 EFER.LME 之前(等于在还没"请求"长模式时就开分页),或忘了先开 CR4.PAE(长模式的前置)。Intel 对这条序列的检查很严:PAE 没开就置 LME、LME 没置就开 PG,都会 #GP。对着设计图的状态机核一遍顺序。

症状三——远跳进 long_mode_entry 后又三重故障。 多半是 64 位代码段描述符的 L/D 位错。L=1 时 D 必须为 0,0x00AF9A000000FFFF 里的 flags 是 0xA(1010: G=1,D=0,L=1)——写成 0xC(1100: D=1,L=0)就是普通的 32 位段,远跳进去 CPU 不认它是长模式,译码错位崩掉。核一遍那个 .quad 的字节。

症状四——链接时报 64 位重定位错误。 gdt64_ptr 用了 .quad gdt,而 Stage2 是 32 位 ELF。改成 .long gdt; .long 0 就好。这是个纯工具链问题,和 CPU 无关,但挺容易卡住第一次写的人。

035_multi_terminal-45-gf25de18 · f25de18 · 2026-08-04