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
。我知道我错了,但为什么呢?
答案 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
。