关于韦东山MMU实验

这本书在讲解MMU的时候,构造段描述符地址的语句是否有误~!?

我指的是例子代码那里,例如:

*(mmu_tlb_base+virtuladdr>>20)

书上就是这样构造一级页表的段描述符存储地址,但是此处的virtual address在向右移动了20位之后并没有再向左移动4位~!

virtual address右移8位的意思应该是要找出地址所在的段,然后再向左移4位应该是使得最后构造的段描述符存储地址的低两位为0,从而提取段描述符,但是书上例子并没有这样做,可是我看Linux内核的启动代码的时候发现了在构造一级页表的时候这个virtual address只移动了18位,就因为这两者的不同,我困惑了很久,望高手解答~!
 
解答:由这个式子:段描述符的地址=Translation base(高18位)+Table index(低12位)+00(低两位)不少人会以为
*(mmu_tlb_base+virtuladdr>>18)才是正确的。

其实不然,这其实是指针操作的问题,主要是要注意到(mmu_tlb_base+1)的正确含义。结合者汇编的知识理解,它不是指移动了一个字节,而是移动了一个存储单元,即4个字节。所以原式中virtuladdr>>20多移了2位,即缩小了4倍,而在进行(mmu_tlb_base+virtuladdr>>2)时会将这4倍补回来,正好符合va向右移动18的要求。

书中部分源码如下:

    1、unsigned long virtuladdr, physicaladdr;
    2、unsigned long *mmu_tlb_base = (unsigned long *)0x30000000;
    
    /*
     * Steppingstone的起始物理地址为0,第一部分程序的起始运行地址也是0,
     * 为了在开启MMU后仍能运行第一部分的程序,
     * 将0~1M的虚拟地址映射到同样的物理地址
     */
    8、virtuladdr = 0;
    9、physicaladdr = 0;
    *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | \
                                            MMU_SECDESC_WB;

    /*
     * 0x56000000是GPIO寄存器的起始物理地址,
     * GPBCON和GPBDAT这两个寄存器的物理地址0x56000010、0x56000014,
     * 为了在第二部分程序中能以地址0xA0000010、0xA0000014来操作GPBCON、GPBDAT,
     * 把从0xA0000000开始的1M虚拟地址空间映射到从0x56000000开始的1M物理地址空间
     */
    18、virtuladdr = 0xA0000000;
    19、physicaladdr = 0x56000000;
    *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | \
                                            MMU_SECDESC;

    /*
     * SDRAM的物理地址范围是0x30000000~0x33FFFFFF,
     * 将虚拟地址0xB0000000~0xB3FFFFFF映射到物理地址0x30000000~0x33FFFFFF上,
     * 总共64M,涉及64个段描述符
     */
    27、virtuladdr = 0xB0000000;
    28、physicaladdr = 0x30000000;
    while (virtuladdr < 0xB4000000)
    {
        *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | \
                                                MMU_SECDESC_WB;
        virtuladdr += 0x100000;
        physicaladdr += 0x100000;
    }



程序的执行分析

首先,程序第2行指定了页表基址为0x30000000,意思是页表从0x30000000这个地址开始存放,由于页表有4096个条目,所以大小为4*4096=16k。

当我们拿到一个32位的虚拟地址,取出其前12位,在页表中寻找条目(如:12位二进制组成的数字是1,就是页表中第一个条目,是2就是第二个条目,依次类推),2的12次方刚好够找4096个。找到条目后,条目的内容大致是这样的:段基址(12位)+控制位(这里具体哪一位是做什么的先不管)。得到的段基址是12位的,从后20位全0到后20位全F,一共表示了1M大小的地址范围。之前我们不是用了虚拟地址的前12位在页表中寻找条目吗,现在用剩下的20位在从段基址开始的1M地址中找到具体的单元。因此,物理地址就应该是:段基址+虚拟地址的后20位;

现在我们再看看程序

第8行开始要完成的功能在注释里有,我们现在主要看看程序是什么意思,韦工这里讲的很简略;

如:*(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | MMU_SECDESC_WB;

        mmu_tlb_base 表示页表基址,页表从这里开始存放,也就是sdram刚开始的16k;

        virtuladdr>>20 实际上就得到了虚拟地址的前12位。

        两个加起来就确定了页表中的一个条目;一个条目能寻址1M大小的物理地址;

        等号右边 (physicaladdr & 0xFFF00000) 表示物理地址的前12位,对应上面说的段基址。

        MMU_SECDESC_WB 对后面位赋值。(具体在宏定义里有)

       整句话就完成了对页表中一个条目的赋值。

       18行开始的程序类似;

       27行开始有

        virtuladdr += 0x100000;
        physicaladdr += 0x100000;

        因为一个条目能寻址1M,sdram有64M。所以每次赋值完递增1M。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值