CR3值和pgd_t

时间:2019-03-03 19:51:39

标签: linux linux-kernel x86 x86-64 kernel-module

我正在玩耍,尝试在安装Linux的x86_64 CPU上手动执行页表遍历。

我想通过使用Linux API并手动查看页表值来尝试获得相同的值。

我在这里找到:https://www.kernel.org/doc/gorman/html/understand/understand006.html CR3的值应等于current-> mm-> pgd。但这不是:

current->mm->pgd = 0x457ec6067
cr3 = 0x45700a006

current-> mm-> pgd在整个运行过程中似乎保持不变。我想念什么?

谢谢!

编辑。这是我的代码:

 __asm__ __volatile__ (
    "mov %%cr3, %%rax\n\t"
    "mov %%rax, %0\n\t" 
    : "=m" (cr3)  
    :
    : "%rax"  
     );
pr_err("cr3 = 0x%lx ", (long)cr3);
pr_err("\tcurrent->mm->pgd = 0x%lx\n", current->mm->pgd->pgd);

1 个答案:

答案 0 :(得分:3)

从Linux 4.14开始,可以通过调用pgd并将其传递给{{1},将cr3转换为要在__sme_pa中使用的页面全局目录的物理页面地址。 }。请注意,返回值的最低有效12位(代表ASID)为零。因此,必须对ASID进行“或”运算。

在Linux 4.14之前,可以使用pgd代替不受支持的__pa。请注意,__sme_pa与Intel处理器上的__pa等效,因为SME仅在AMD处理器上可用。

至少从Linux 2.6开始,__sme_papgd可能相等,也可能不同,这取决于两个因素:

  • cr3是否大于内核映像pgd的虚拟基址。
  • __START_KERNEL_map,它是内核映像的编译时物理基址与映像的运行时物理基址之间的差。如果图像已重定位,则phys_base不会为零。

翻译过程由称为__phys_addr的函数执行,可以参考以下示例。

我已经在两个系统上对此进行了测试。在Linux 4.4.0上,我得到以下值:

phys_base

在这种情况下,cr3 = 0x3581E000 pgd = 0x3581E000 __pa(pgd) = 0x3581E000 __START_KERNEL_map = 0x80000000 phys_base = 0x00000000 pgd是等效的。在Linux 4.15上:

cr3