总结关于x86物理内存布局和real mode/protect mode相关的基本知识
1 x86 physical address layout
1 |
|
8086的16位架构,操作系统只能利用2^20的地址,也就是1MB,也就是上图中0x0000000到0x00100000的区域。其中0x0到0xA0000的640KB是RAM使用,0xA0000到0xF0000的320KB是设备使用比如VGA,0xF0000到0x100000的64KB是BIOS使用。
在扩展到80386的32位架构后,系统可以收用2^32的4GB的地址。为了兼容16位系统,0xA0000到0x100000的区域(原先BIOS和设备区域)不再使用而空出。把原来0x0到0xA0000的RAM区域称为Low memory区域,1MB之后的RAM区域称为Extended Memory区域。BIOS和设备内存区域移动到32位区域的顶部。
可想而知当扩展到64位架构之后,为了系统向后兼容,又会产生第二个空闲区域。
2 real mode和protect mode
2.1 real mode
real mode wiki
real mode是x86系统都兼容的一个运行模式,出现在早期的8086/8088架构时期。
- real mode支持20位寻址,也就是1MB的内存空间。
- 使用段寄存器(16位)和偏移寄存器(16位)计算地址: segment * 16 + offset
- 运行程序可以直接访问物理内存,I/O地址和外部设备
- 因此不提供内存保护(memory protection)/多任务(multitasking)和权限(code privilege levels)
2.2 protect mode
protect mode wiki
80286引进protect mode, 80386加强
1 | Selector +--------------+ +-----------+ |
2.2.1 提供
- 虚拟内存(virtual memory)
- 页表(page)(386引进)
- 安全的多任务(multi-tasking)处理(286引进)
- 无需重置CPU切换回real mode(386引入)
2.2.2 段寻址(80286开始)
- real mode中段部分替换为16位的选择器(selector), 高13位代表GDT的条目索引, 最低2位确定了请求的权限等级(0代表最高等级/3代表最低等级)
- GDT介绍
- GDT条目(segment descriptor)有8字节长,定义了段的基地址(base address 32位),段的大小(limit 20位)以及权限(access rights)
注意base的32bits是分成8bits, 8bits和16bits的, limit的20bits是分成16bits和4bits的 - GDT的位置存在GDTR寄存器中,可以使用LGDT指令写,只有一个GDT
- GDT条目(segment descriptor)有8字节长,定义了段的基地址(base address 32位),段的大小(limit 20位)以及权限(access rights)
- 如果开启paging,则将计算出的linear address输入page table,否则直接映射到物理地址
2.2.3 paging(80386开始)
- page管理使用page directories和page tables。
- page directory是1个page的大小(4K)包含1024 page directories entries(PDE), PDE指向page table
- page table同样是4K大小,包含1024个page tables entries(PTE),PTE指向实际的物理地址
- page directories的地址存在控制寄存器CR3的高20位之中(参考控制寄存器)
- 开启paging需要设置CR0的PG位
- 一个时间内只会有1个page directory在使用中
2.2.4 flat mode
没有必要使用segment translation, 但是没有直接可以关闭segment translation的方式。
C 指针就是虚拟地址(virtual address)的偏移部分。 在boot/boot.S, 我们可以设置一个Global Descriptor Table (GDT)来通过使得所有segment base address为0而limit为0xffffffff来有效关闭segment translation。 因此selector部分就没有作用了,linear address总是等于虚拟地址(virtual address)的offset。
2.2.5 兼容real mode
为了提供向后兼容,286以real mode开始运行, 当系统程序设置了descriptor table(至少设置null descriptor/code segment descriptot和data segment descriptor)且开启控制寄存器CR0中的Protection Enable(PE)位之后,才可以进入protect mode。
1 | ; set PE bit |
2.3 关于在real mode下的寻址能力
8086/8088/80186的地址总线是20位,用段寄存器和偏移寄存器寻址方式能产生21位,如果超过$2^{20}$则取模$2^{20}$,即偏移地址 - 0x10(A20line关闭)
80286的地址总线是24位也就是16MB的寻址能力,可以容纳21位,用段寄存器和偏移寄存器的方式寻址,最大寻址能力为0xFFFF0 + 0xFFFF = 0x10FFEF = 1MB + 64KB - 16(A20line打开)
2.4 80286下从protect mode切回real mode
直接重置CPU,由于RAM没有重置,CPU可以重新以real mode开始运行。