当我读head.s(Linux内核文件之一)时,我遇到了一个问题

时间:2015-07-29 07:58:16

标签: linux linux-kernel

head.s中的代码片段如下所示:

movl $swapper_pg_dir-0xc0000000,%eax
movl %eax,%cr3 /* set the page table pointer.. */
movl %cr0,%eax
orl $0x80000000,%eax
movl %eax,%cr0 /* ..and set paging (PG) bit */

在内核启用分页机制之前(当然,PE标志现在已经启用),它会将临​​时页面目录表的地址加载到%cr3

问题是:
我认为内核应该直接将$swapper_pg_dir值放入%eax而不是$swapper_pg_dir-0xc0000000。我知道我错了,但为什么呢?

2 个答案:

答案 0 :(得分:4)

内核看起来好像是基于0xC0000000。任何内存分配,指针或全局,位于0xC0000000到0xFFFFFFFF之间。 但是,对于HW控制器,例如MMU或任何协处理器,内存窗口可能基于0x00000000。

因此,当将指向表或描述符的指针加载到HW引擎时,它必须基于0x00000000

答案 1 :(得分:0)

OP询问Linux为什么从0xc0000000减去swapper_pg_dir。这种数学的原因是%cr3需要物理地址,而$swapper_pg_dir是虚拟地址。在内核页面初始化的初始阶段,有8MB RAM(0 to 0x007fffff)的两个映射。虚拟地址one to one的第一个映射为0x00000000-0x007fffff,而0xc0000000-0xcoo7fffff的映射为swapper_pg_dir。为了获得0xc0000000的实际地址,我们必须从swapper_pg_dir的地址中减去System.IO.Error