手动玩转虚拟地址到物理地址转化

Posted Loopers

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手动玩转虚拟地址到物理地址转化相关的知识,希望对你有一定的参考价值。

我们这次来根据dump动手来实际转化一个虚拟地址到物理地址,此次的地址不是线性地址映射。

Target_Address_|________________logical|_physical______________|
               |     C:FFFFFF8008015000|             A:C549F000
 

上面0xFFFFFF8008015000就是虚拟地址,而我们努力的方向就是物理地址:0xC549F000。 让我们朝这个方向一路高歌吧。

 

转化的原理:

  • 根据TTBR(0/1)寄存器获取到页表的基地址
  • 页表基地址+PGD_Index获取PGD表中的一项,此项就是PMD表的基地址
  • 根据PDM基地址+PMD_Index获取PMD中的一项,此项就是PTE表的基地址
  • 根据PTE基地址+PTE_Index获取直接页表的基地址
  • 根据直接页表的地址+offset就可以获取真正的物理地址

 

转化之前先确认的是此地址是属于用户空间还是内核空间。

  • 用户地址:页表的基地址是mm_struct→pgd
  • 内核空间:  页表的基地址是init_mm→pgd

 

很明显我们需要转化的地址是属于内核空间的,则首先需要确认init_mm→pgd的值,它来了

init_mm = (
    mmap = 0x0,
    mm_rb = (rb_node = 0x0),
    vmacache_seqnum = 0x0,
    mm_rb_lock = (raw_lock = (cnts = (counter = 0x0), wlocked = 0x0, __lstate = (0x0, 0x0, 0x0), wai
    get_unmapped_area = 0x0,
    mmap_base = 0x0,
    mmap_legacy_base = 0x0,
    task_size = 0x0,
    highest_vm_end = 0x0,
    pgd_=_0xFFFFFF9B4FCA7000 -> (  //虚拟地址
      pgd = 0x000000017AC05003),   //虚拟地址里面的值
    mm_users = (counter = 0x2),
    mm_count = (counter = 0x1),

前期条件: 

  • 虚拟地址:0xFFFFFF8008015000
  • init_mm→pgd的值:0xFFFFFF9B4FCA7000

 

PGD_Index = 虚拟地址>>30位 = (0xFFFFFF8008015000 >>30)&(0x200-1) = 0

PGD_entry_virt = 0xFFFFFF9B4FCA7000 + 0*8 = 0xFFFFFF9B4FCA7000

PGD_entry_phy = rd(0xFFFFFF9B4FCA7000) = 0x000000017AC05003

 

PMD_Index = 虚拟地址  >> 21位 = (0xFFFFFF8008015000 >>21)&(0x1ff) = 0x40

PMD_entry_virt = 0x000000017AC05003 + 0x40 * 8 = 0x000000017AC05000 + 0x40 *8 = 0x17AC05200

PMD_entry_phy = rd(0x17AC05200) = 0x17AC06003

 

PTE_Index = 虚拟地址 >> 12位 = (0xFFFFFF8008015000>>12)&(0x200-1)=0x15

PTE_entry_virt =  0x17AC06003 + 0x15 * 8 = 0x17AC06000 + 0x15*8= 0x17AC060A8

PTE_entry_phy = rd(0x17AC060A8) = 0xE00000C549F793

 

pfn = 0xE00000C549F793 >> 12 = 0xC549F

 

物理地址 = 0xC549F000 + 0x000 = 0xC549F000

上面之所以需要清空低12位,还有index*8都是因为页表的低12位存储着一些flag,这些flag如下,比如T32

  • present的意思是页是否是有效的,无效代表虚拟到物理地址之间的转化无效,当访问虚拟地址的时候就会page fault
  • protection :权限之类的,是否读写执行权限之类的。如果你访问一段虚拟地址,页表中是无法执行的权限,但是你想执行这段代码就会出错
  • reference: 引用之类的
  • cache: cache是否有效。有效就从cache取,无效从memory
  • dirty: 是否写过,写过就代表脏。在内存不够时需要写会处理的。

 

以上是关于手动玩转虚拟地址到物理地址转化的主要内容,如果未能解决你的问题,请参考以下文章

手动玩转虚拟地址到物理地址转化

内存寻址:逻辑地址到物理地址的转化

分段机制

嵌入式linux学习笔记1—内存管理MMU之虚拟地址到物理地址的转化

如何把物理路径转换成虚拟路径

启用PAE后虚拟地址到物理地址的转换