首先了解如何发现系统中的物理内存; 然后了解如何建立对物理内存的初步管理,即了解连续物理内存管理; 最后了解页表相关的操作,
即如何建立页表来实现虚拟内存到物理内存之间的映射,对段页式内存管
理机制有一个比较全面的了解。
分配内存空间前,必须获取物理内存空间的信息
e820map:
memory: 0009fc00, [00000000, 0009fbff], type = 1.
memory: 00000400, [0009fc00, 0009ffff], type = 2.
memory: 00010000, [000f0000, 000fffff], type = 2.
memory: 07ee0000, [00100000, 07fdffff], type = 1.
memory: 00020000, [07fe0000, 07ffffff], type = 2.
memory: 00040000, [fffc0000, ffffffff], type = 2.
1是可以使用的物理内存空间,
2是不能使用的物理内存空间。
注意, 2中的"不能使用"指的是这些地址不能映射到物理内存上, 但它们可以映射到ROM或者映射到其他设备,比如各种外设等。
实模式下进行探测,也就是在 bootloader 中添加了物理内存空间探测的功能。
一个内存映射地址描述符占 20字节
struct e820map { // 该数据结构保存于物理地址0x8000
int nr_map; // map中的元素个数
struct {
uint64_t addr; // 某块内存的起始地址
uint64_t size; // 某块内存的大小
uint32_t type; // 某块内存的属性。1标识可被使用内存块;2表示保留的内存块,不可映射。
} __attribute__((packed)) map[E820MAX];
};
00h 8字节 base address #系统内存块基地址
08h 8字节 length in bytes #系统内存大小
10h 4字节 type of address range #内存类型
INT 15h 进行物理内存空间探测
probe_memory:
movl $0, 0x8000 # 初始化,向内存地址0x8000,即uCore结构e820map中的成员nr_map中写入0
xorl %ebx, %ebx
movw $0x8004, %di # e820map的成员变量nr_map清零
start_probe:
movl $0xE820, %eax # BIOS 0x15中断的子功能编号 %eax == 0xE820
movl $20, %ecx # 存放地址范围描述符的内存大小,至少20
movl $SMAP, %edx # 签名, %edx == 0x534D4150h("SMAP"字符串的ASCII码)
int $0x15 # 调用0x15中断
jnc cont # 如果该中断执行失败,则CF标志位会置1,此时要通知UCore出错
movw $12345, 0x8000 # 向结构e820map中的成员nr_map中写入特殊信息,报告当前错误
jmp finish_probe
cont:
addw $20, %di # 下一个位置 对应 e820map 的20 字节
incl 0x8000 # e820::nr_map++
cmpl $0, %ebx # 如果%ebx为0,则说明当前内存探测完成
jnz start_probe
finish_probe: