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



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

内核看到的内存好像是基于0xC0000000。任何内存分配,无论是指针还是全局,都位于0xC0000000到0xFFFFFFFF之间。然而,对于硬件控制器,如MMU或任何协处理器,内存窗口可能基于0x00000000。

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

OP问为什么Linux从swapper_pg_dir减去0xc0000000。这样计算的原因是%cr3需要物理地址,而$swapper_pg_dir是虚拟地址。在内核页初始化的初始阶段,有两个8MB RAM (0 to 0x007fffff)的映射。第一个映射是one to one,对应虚拟地址0x00000000-0x007fffff,另一个映射是0xc0000000-0xcoo7fffff。为了得到swapper_pg_dir的物理地址,我们必须从swapper_pg_dir的地址中减去0xc0000000

相关内容

最新更新