Linux通过查询页表实现虚拟地址到物理地址的转换

virt_to_phys.c

Makefile

v2p_va.c

实验环境:
Ubuntu 14.04 x86
(Ubuntu 14.04 x86-64也经过了测试,但不知为何,pte_val得出的值最高位始终为1,清零最高位也可得出正确的结果。)

ubunntu@ubunntu-virtual-machine:~/v2p$ ./v2p_va &
[1] 2613
ubunntu@ubunntu-virtual-machine:~/v2p$ pid=2613, &i=0xbff460ac

ubunntu@ubunntu-virtual-machine:~/v2p$ sudo insmod virt_to_phys.ko pid=2613 va=0xbff460ac
[sudo] password for ubunntu:
ubunntu@ubunntu-virtual-machine:~/v2p$ dmesg | tail –n 100

查看如下结果:

[ 1503.774647] PAGE_OFFSET = 0xc0000000
[ 1503.774651] PGDIR_SHIFT = 30
[ 1503.774653] PUD_SHIFT = 30
[ 1503.774654] PMD_SHIFT = 21
[ 1503.774656] PAGE_SHIFT = 12
[ 1503.774657] PTRS_PER_PGD = 4
[ 1503.774658] PTRS_PER_PUD = 1
[ 1503.774659] PTRS_PER_PMD = 512
[ 1503.774660] PTRS_PER_PTE = 512
[ 1503.774661] PAGE_MASK = 0xfffff000
[ 1503.774663] PAGE_SIZE = 0x1000
[ 1503.774664] current->pid=2645.
[ 1503.774665] vmalloc————–.
[ 1503.774671] pgd = 0xe1d1b000
[ 1503.774672] cr3=0x21d1b000.
[ 1503.774673] pgd_tmp = 0xe1d1b018
[ 1503.774675] pgd_val(*pgd_tmp) = 0x1af3001
[ 1503.774676] pud_tmp = 0xe1d1b018
[ 1503.774677] pud_val(*pud_tmp) = 0x1af3001
[ 1503.774678] pmd_tmp = 0xc1af3e00
[ 1503.774679] pmd_val(*pmd_tmp) = 0x35425067
[ 1503.774681] pte_tmp = 0xf5425130
[ 1503.774682] pte_val(*pmd_tmp) = 0x21ce8163
[ 1503.774684] virt_addr 0xf8026000 in RAM is 0x21ce8000 .
[ 1503.774685] vmalloc: virt_to_phy success.
[ 1503.774686] alloc_pages (hign memory)————–.
[ 1503.774688] pgd = 0xe1d1b000
[ 1503.774689] cr3=0x21d1b000.
[ 1503.774690] pgd_tmp = 0xe1d1b018
[ 1503.774701] pgd_val(*pgd_tmp) = 0x1af3001
[ 1503.774702] pud_tmp = 0xe1d1b018
[ 1503.774703] pud_val(*pud_tmp) = 0x1af3001
[ 1503.774704] pmd_tmp = 0xc1af3870
[ 1503.774706] pmd_val(*pmd_tmp) = 0x2916a063
[ 1503.774707] pte_tmp = 0xe916a530
[ 1503.774708] pte_val(*pmd_tmp) = 0x21ca6163
[ 1503.774710] virt_addr 0xe1ca6000 in RAM is 0x21ca6000 .
[ 1503.774711] alloc_pages (hign memory): virt_to_phy success.
[ 1503.774712] __get_free_page————–.
[ 1503.774714] pgd = 0xe1d1b000
[ 1503.774715] cr3=0x21d1b000.
[ 1503.774716] pgd_tmp = 0xe1d1b018
[ 1503.774717] pgd_val(*pgd_tmp) = 0x1af3001
[ 1503.774718] pud_tmp = 0xe1d1b018
[ 1503.774720] pud_val(*pud_tmp) = 0x1af3001
[ 1503.774721] pmd_tmp = 0xc1af3870
[ 1503.774722] pmd_val(*pmd_tmp) = 0x2916a063
[ 1503.774723] pte_tmp = 0xe916a6f8
[ 1503.774724] pte_val(*pmd_tmp) = 0x21cdf163
[ 1503.774726] virt_addr 0xe1cdf000 in RAM is 0x21cdf000 .
[ 1503.774727] virt_to_phys(vaddr2)=0x21cdf000
[ 1503.774728] __get_free_page: virt_to_phy success.
[ 1503.774730] pgd = 0xeb527000
[ 1503.774731] cr3=0x21d1b000.
[ 1503.774733] pgd_tmp = 0xeb527010
[ 1503.774735] pgd_val(*pgd_tmp) = 0x23aa3001
[ 1503.774755] pud_tmp = 0xeb527010
[ 1503.774757] pud_val(*pud_tmp) = 0x23aa3001
[ 1503.774758] pmd_tmp = 0xe3aa3ff8
[ 1503.774759] pmd_val(*pmd_tmp) = 0x21e0e067
[ 1503.774760] pte_tmp = 0xe1e0ea30
[ 1503.774762] pte_val(*pmd_tmp) = 0x1ef1f067
[ 1503.774763] virt_addr 0xbff460ac in RAM is 0x1ef1f0ac .
[ 1503.774764] virt_to_phy success.

2 Comments

  1. phybio

    您好,您用这个程序试过lowmem(低端内存)虚拟地址计算到物理地址的值的情况吗?
    比如init_mm这个结构的虚拟地址(c11478a0),它一定是在内核空间的虚拟地址,应该一一映射,也就是线性映射到物理地址(应该是x11478a0,x表示去掉一位偏移)。但通过代码计算pte_present返回是假,表示init_mm的pte不在内存中?这样可以解释吗?谢谢。

    Reply

  2. 颜如玉美图

    实用

    Reply

Leave a Reply

*