正常
设计图:临时页表与长模式状态机
先看这套临时分页长什么样。我们用四级页表里最粗粒度的2MB 大页,只填三张表、映射前 8MB:
text
地址 表 作用
0x1000 PML4 PML4[0] → 指向 PDPT
0x2000 PDPT PDPT[0] → 指向 PD
0x3000 PD PD[0..3] → 4 个 2MB 大页,恒等映射 0~8MB为什么三张表就够?因为我们用 2MB 大页,到 PD 这一层就终止了(大页标志位 PS=1 表示"这一项是页,不用再往下查 PT")。一个 PD 项映射 2MB,4 个就盖 8MB。恒等映射的意思是"虚拟地址 = 物理地址"——我们的 bootloader 和内核都在低地址跑,这种最省事的映射刚好够用。
再看进入长模式的状态机,顺序是 Intel 定死的,调换一个就三重故障:
text
32 位 PM
│ CR3 = 0x1000 # 装载 PML4 基址(让 CPU 知道页表在哪)
│ CR4 |= PAE (bit 5) # 开物理地址扩展(长模式的前置条件)
│ EFER |= LME (bit 8) # 开"长模式使能"——但此刻还没生效
│ lgdt gdt64_ptr # 换上带 64 位代码段的 GDT
▼
CR0 |= PG (bit 31) # ★ 开分页:LME 此刻"激活",长模式真正生效
│
▼
ljmp $0x18, $long_mode_entry # 远跳到 64 位代码段,刷新 CS
│
▼
长模式(64 位)EFER.LME 设了之后并不会立刻生效——它要等到 CR0.PG 被置位的那一拍才真正激活(因为长模式绑死在分页上)。这个"先 LME 后 PG"的顺序是 Intel 的规定,反了就会触发 #GP。