打印内核的页表条目

时间:2013-11-19 10:57:48

标签: linux

具有4级页表的虚拟内存映射:

0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
ffffc80000000000 - ffffc8ffffffffff (=40 bits) hole
ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space
ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole
ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
ffffffff80000000 - ffffffffa0000000 (=512 MB)  kernel text mapping, from phys 0
ffffffffa0000000 - fffffffffff00000 (=1536 MB) module mapping space

我知道内核会尝试直接将物理地址映射到从PAGE_OFFSET开始直接映射区域的虚拟地址

ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory

但我不知道内核中的代码保持页表管理这个直接映射区域的位置,以及如何在这个直接映射区域中打印出4级页表的所有页表项。你知道怎么打印吗?

2 个答案:

答案 0 :(得分:21)

鸣:

我也有兴趣打印Linux的页面表,我偶然发现了内核源代码中的漂亮实用程序

arch/x86/mm/dump_pagetables.c

如果build your kernel设置了CONFIG_X86_PTDUMP,则可以执行

cat /sys/kernel/debug/kernel_page_tables

它将遍历内核的页表层次结构并将其打印出来。但是输出有两个问题:

  1. 它仅列出虚拟地址,其关联的物理地址。这令我很失望,因为我最感兴趣的是非RAM系统地址(如PCI空间等)的虚拟映射 - 在其他工作中,我希望通过/ sys /在视觉上匹配我在/ proc / iomem中看到的内容内核/调试/ kernel_page_tables。
  2. 它不提供打印每个进程页表的方法。据我所知,每个linux进程和init_level_4_pgt(内核的原始(启动后)页面表)共享其虚拟地址空间的很大一部分:从病房的PAGE_OFFSET到精确。我想这样做是因为在用户进程的上下文中运行的内核代码(通过系统调用)可以访问内核内存。无论如何,我认为看到所有这一切都非常简洁。
  3. 以下是我修补的3.13.11内核的link,修复了这两个问题(修复的分支是page_table_print)。

    要使用,只需执行

    echo <pid_of_interest> > /proc/sys/debug/pgt_dump_process_id
    

    其中pid_of_interest如果您希望监视其页表的进程的pid。注意:通过执行

    echo -1 > /proc/sys/debug/pgt_dump_process_id
    

    这将转储内核的页表。以下是内核页表的示例输出:

    cat /sys/kernel/debug/kernel_page_tables  | more
    CR3= 0x196b70000, va_CR3 = 0xffff880196b70000
    Page tables for kernelPGT localtion in memory: phs = 0x1c0e000, virt  = 0xffffffff81c0e000
    ---[ User Space ]---
    0x0000000000000000-0xffff800000000000, phy: 0x0000000000000000-0x0000800001c0e000 16777088T                           pgd
    ---[ Kernel Space ]---
    0xffff800000000000-0xffff880000000000, phy: 0x0000800001c0e000-0x0000000001fe1000        8T                           pgd
    ---[ Low Kernel Mapping ]---
    0xffff880000000000-0xffff880000096000, phy: 0x0000000001fe1000-0x0000000002077000      600K     RW             GLB NX pte
    0xffff880000096000-0xffff880000097000, phy: 0x0000000002077000-0x0000000002078000        4K     ro             GLB NX pte
    0xffff880000097000-0xffff880000098000, phy: 0x0000000002078000-0x0000000002079000        4K     ro             GLB x  pte
    0xffff880000098000-0xffff880000200000, phy: 0x0000000002079000-0x00000000021e0000     1440K     RW             GLB NX pte
    0xffff880000200000-0xffff880001000000, phy: 0x00000000021e0000-0x0000000002fe0000       14M     RW         PSE GLB NX pmd
    0xffff880001000000-0xffff880001600000, phy: 0x0000000002fe0000-0x00000001b14a1000        6M     ro         PSE GLB NX pmd
    0xffff880001600000-0xffff880001734000, phy: 0x00000001b14a1000-0x00000001b15d5000     1232K     ro             GLB NX pte
    0xffff880001734000-0xffff880001800000, phy: 0x00000001b15d5000-0x00000000037e0000      816K     RW             GLB NX pte
    0xffff880001800000-0xffff880001a00000, phy: 0x00000000037e0000-0x00000001b14a2000        2M     ro         PSE GLB NX pmd
    

    这是执行

    后的输出
    echo 1 > /proc/sys/debug/pgt_dump_process_id
    
    
    cat /sys/kernel/debug/kernel_page_tables  | more
    CR3= 0x17312f000, va_CR3 = 0xffff88017312f000
    Page tables for process id = 1
    PGT localtion in memory: phs = 0x3623f000, virt  = 0xffff88003623f000
    ---[ User Space ]---
    0x0000000000000000-0x00007f8000000000, phy: 0x0000000000000000-0x0000000036277000   130560G                           pgd
    0x00007f8000000000-0x00007ff200000000, phy: 0x0000000036277000-0x000000003627a000      456G                           pud
    0x00007ff200000000-0x00007ff207800000, phy: 0x000000003627a000-0x0000000036097000      120M                           pmd
    0x00007ff207800000-0x00007ff2079b5000, phy: 0x0000000036097000-0x000000003624c000     1748K                           pte
    0x00007ff2079b5000-0x00007ff2079b8000, phy: 0x000000003624c000-0x000000003624f000       12K USR ro                 x  pte
    0x00007ff2079b8000-0x00007ff207bbf000, phy: 0x000000003624f000-0x00000000363c3000     2076K                           pte
    0x00007ff207bbf000-0x00007ff207bc1000, phy: 0x00000000363c3000-0x00000000363c5000        8K USR ro                 NX pte
    0x00007ff207bc1000-0x00007ff207bc4000, phy: 0x00000000363c5000-0x00000000363c8000       12K USR ro                 x  pte
    0x00007ff207bc4000-0x00007ff207bc6000, phy: 0x00000000363c8000-0x00000000363ca000        8K                           pte
    0x00007ff207bc6000-0x00007ff207bc7000, phy: 0x00000000363ca000-0x00000000363cb000        4K USR ro                 x  pte
    0x00007ff207bc7000-0x00007ff207dcb000, phy: 0x00000000363cb000-0x00000000363d0000     2064K                           pte
    0x00007ff207dcb000-0x00007ff207dcd000, phy: 0x00000000363d0000-0x00000000363d2000        8K USR ro                 NX pte
    0x00007ff207dcd000-0x00007ff207dd2000, phy: 0x00000000363d2000-0x00000000363d7000       20K USR ro                 x  pte
    0x00007ff207dd2000-0x00007ff207fe3000, phy: 0x00000000363d7000-0x00000000363fe000     2116K                           pte
    0x00007ff207fe3000-0x00007ff207fe5000, phy: 0x00000000363fe000-0x0000000036400000        8K USR ro                 NX pte
    0x00007ff207fe5000-0x00007ff207fe7000, phy: 0x0000000036400000-0x0000000036402000        8K                           pte
    0x00007ff207fe7000-0x00007ff207fec000, phy: 0x0000000036402000-0x0000000036407000       20K USR ro                 x  pte
    0x00007ff207fec000-0x00007ff207fed000, phy: 0x0000000036407000-0x0000000036408000        4K                           pte
    0x00007ff207fed000-0x00007ff207fef000, phy: 0x0000000036408000-0x000000003640a000        8K USR ro                 x  pte
    0x00007ff207fef000-0x00007ff2081ef000, phy: 0x000000003640a000-0x0000000036214000        2M                           pte
    0x00007ff2081ef000-0x00007ff2081f1000, phy: 0x0000000036214000-0x0000000036216000        8K USR ro                 NX pte
    

    我觉得这很漂亮,我希望别人也这么认为。 :)

答案 1 :(得分:3)

每个进程都有自己的页面全局目录(PGD),其指针存储在CR3寄存器中,当内核运行进程时会加载该指针。内核还为进程交换器保留了自己的PGD(如果我没记错的话),它存储在init_mm.pgd结构成员中。您应该能够在此PGD中找到您要查找的页面。

不幸的是,除非您在VM中运行,否则我知道没有简单的方法可以访问CR3。您可以使用GDB获取init_mm结构,如下所示:

  • 获取一个内核,其中包含与当前内核匹配的调试符号。匹配必须准确,因此最好使用相应的分发包。有关Ubuntu说明,请参阅How to get Ubuntu debug kernel

  • 假设您正在运行具有正常/ proc / kcore功能的发行版(例如Ubuntu),您可以执行此操作 gdb <debugguing kernel image> /proc/kcore

  • 现在做 p init_mm.pgd 获取内核的PGD地址。

  • 您现在可以使用转储 dump mem <file name> <pgd start> <pgd start + 0x1000> (如果PGD适合4K页面,那就是

要获得与您感兴趣的内存范围相对应的所有较低级别表,您必须从PGD开始,手动或在GDB中使用python脚本编写它们。