一个程序明白arm linux虚拟地址到物理地址的转换过程


static int bad_address(void *p)
{    
    unsigned long dummy;    
    //arm 体系没有这个函数实现
    return 0;
    //return probe_kernel_address((unsigned long *)p, dummy);
}

//该函数用于查询逻辑address 虚地址 对应的页表. 摘自arch/x86/mm/fault.c
static void dump_pagetable( unsigned long address )  
{    
    //pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK); 

    unsigned long pa;

    pgd_t *base = swapper_pg_dir;   
    //页目录表基址
    pgd_t *pgd = base + pgd_index(address);
    pud_t *pud;    //页表级数大于 3  [4]
    pmd_t *pmd;    //页表级数大于 2  [3]
    pte_t *pte;    //页表级数大于等于 1 小于等于2    x>=1 && x<=2  [1,2]


    printk( "in address = %lx\n", address );

    printk( "base = %lx\n", base );
    
    printk( "pgd_index(address) = 0x%lx\n", pgd_index(address) );
    printk( "PGD1 = %lx\n", pgd );
    printk( "PGD2 = %lx\n", pgd_val(*pgd) );
    
    if( !pgd_present(*pgd) ){
        goto out; 
    }

     
    pud = pud_offset(pgd, address);
    if( bad_address(pud) ){
        goto bad;
    }
    printk("PUD = %lx\n", pud_val(*pud));
    if (!pud_present(*pud) ){
        goto out;
    }
    pmd = pmd_offset(pud, address);
    if (bad_address(pmd)){
        goto bad;
    }
    printk("PMD = %lx\n", pmd_val(*pmd));
    if (!pmd_present(*pmd) || pmd_large(*pmd)){ 
        //值为空退出
        //虽然值不为空 但是他有段描述符属性 也退出 即他不是一级页描述符入口
        //段表的话 一级就可以定位到物理地址 只要前面的12bit, 以1M为单位
        goto out;
    }

    
    pte = pte_offset_kernel(pmd, address); 
    if (bad_address(pte)){
        goto bad;
    }
    printk("PTE = %lx\n", pte_val(*pte));
    //由二级页表定位到实际的物理地址   
    pa = (pte_val(*pte) & PAGE_MASK) | (address & ~PAGE_MASK);
    printk("pa = %lx\n", pa );        
    
    
out:
    printk("\n"); 
    return;
bad:
    printk("BAD!!!\n");
}

//版权声明:本文为CSDN博主「leolinux」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https://blog.csdn.net/leolinux/article/details/6100799v

static int pttest_show(struct seq_file *m, void *v)
{

    unsigned int pgd;
    printk("in pttest_show\n");

    pgd = cpu_get_pgd();

     printk("pgd = 0x%lx\n", pgd);
     printk("init_mm.pgd = 0x%lx\n", init_mm.pgd);


     dump_pagetable(0);
     dump_pagetable(0xc0000000);
     dump_pagetable(0xc0004000);
     dump_pagetable(0xffff0000);
     dump_pagetable(0xff000000);
    return 0;
}

 

https://www.cnblogs.com/pengdonglin137/p/7818386.html

关于内存映射方面 这哥们说的不错!

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值