Разница между значением CR3 и pgd_t - PullRequest
0 голосов
/ 03 марта 2019

Я играю и пытаюсь выполнить ручную прогулку по таблице страниц на моем процессоре x86_64 с установленным Linux.

Я хочу попробовать получить то же значение с помощью API Linux и вручнуюглядя на таблицу значений таблицы.

Я нашел здесь: https://www.kernel.org/doc/gorman/html/understand/understand006.html, что значение CR3 должно быть равно current-> mm-> pgd.Но это не так:

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

current-> mm-> pgd, кажется, остается постоянным на протяжении прогонов.Чего мне не хватает?

Спасибо!

edit.Это мой код:

 __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 голосов
/ 04 марта 2019

Начиная с Linux 4.14, pgd можно преобразовать в физический адрес страницы глобального каталога страниц, который будет использоваться в cr3, вызвав __sme_pa и передав ему pgd.Обратите внимание, что младшие 12 битов возвращаемого значения (которые представляют ASID) равны нулю.Таким образом, ASID должен быть ИЛИ с ним.

До Linux 4.14 можно использовать __pa вместо __sme_pa, который не поддерживается.Обратите внимание, что __pa эквивалентно __sme_pa на процессорах Intel, поскольку SME доступно только на процессорах AMD.

По крайней мере, начиная с Linux 2.6, pgd и cr3 могут быть или не быть эквивалентными в зависимости отдва фактора:

  • Является ли pgd больше, чем виртуальный базовый адрес образа ядра __START_KERNEL_map.
  • phys_base, что представляет собой разницу между временем компиляциифизический базовый адрес образа ядра и физический базовый адрес образа во время выполнения.Если изображение было перемещено, phys_base не будет равно нулю.

Процесс перевода выполняется с помощью функции __ phys_addr , к которой вы можете обратиться, чтобы следовать следующим примерам.

Я проверял это на двух системах.В Linux 4.4.0 я получил следующие значения:

cr3                 = 0x3581E000
pgd                 = 0x3581E000
__pa(pgd)           = 0x3581E000
__START_KERNEL_map  = 0x80000000
phys_base           = 0x00000000

В этом случае pgd и cr3 эквивалентны.В Linux 4.15:

cr3                 = 0x8980A005
pgd                 = 0xC980A000
__pa(pgd)           = 0x8980A000
__START_KERNEL_map  = 0x80000000
phys_base           = 0xEC000000
...