Chinaunix首页 | 论坛 | 博客
  • 博客访问: 82747
  • 博文数量: 13
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 175
  • 用 户 组: 普通用户
  • 注册时间: 2013-03-04 13:28
个人简介

君子求诸己,小人求诸人。

文章分类
文章存档

2014年(6)

2013年(7)

我的朋友

分类: 嵌入式

2014-04-25 23:33:55



0x51000000为真实的物理内存地址


上面确定了,猎户座4412想使用异常向量表,只能打开mmu。

点击(此处)折叠或打开

  1. #include <common.h>
  2. #include <mmu.h>

  3. void mmu_enable(void)
  4. {
  5.     __asm__ __volatile__(
  6.         "mrc p15, 0, r0, c1, c0, 0\n"
  7.         "orr r0, r0, #1\n"
  8.         "mcr p15, 0, r0, c1, c0, 0\n"
  9.         :::"r0"
  10.     );
  11. }

  12. void mmu_disable(void)
  13. {
  14.     __asm__ __volatile__(
  15.         "mrc p15, 0, r0, c1, c0, 0\n"
  16.         "bic r0, r0, #1\n"
  17.         "mcr p15, 0, r0, c1, c0, 0\n"
  18.         :::"r0"
  19.     );
  20. }
  21. /*eg:虚拟地址0x123456789想要访问物理地址,则用c2+0x123找到页表对应的条目,取出高12位(&0xfff00000)+0x56789=真实物理地址*/
  22. void my_mmap(unsigned int *ttb, unsigned int va, unsigned int pa)
  23. {
  24.      /*页表条目基地址[偏移] = 页表内容,也就是物理地址的高12位 | 2,或2,表示此条目是段映射*/
      /*用虚拟地址的前3位来寻找条目的原因:一个条目可以寻址1M,那么3位hex,2^12是4k,4K*1M=4G*/
  25.     ttb[va >> 20] = (pa & 0xfff00000) | 2;
  26. }

  27. void ttb_init(unsigned int *ttb)
  28. {
  29.     int va, pa;
  30. /*va从0开始的原因:就是bootlader起来之后开启MMU想把全部虚拟地址=物理地址*/
     /*va每次+0x100000的原因:条目只保存物理地址的高12位,也就是低20位都补0x0~0xfffff(2^20=1M)*/ 
  31.     for(va = 0; va < 0x80000000; va += 0x100000){
  32.         pa = va;
  33.         my_mmap(ttb, va, pa);
  34.     }

  35.     __asm__ __volatile__(
  36.         "mcr p15, 0, %0, c2, c0, 0\n"
  37.         "mvn r0, #0\n"
  38. /*c3寄存器表示虚拟地址的访问权限(读?写?之类),c3寄存器每2位表示一个权限(00,01,10,11)总过有16个,如果段页表条目的5-8位是3,那么就去c3寄存器的第4个去查看相应的权限。*/
  39.         "mcr p15, 0, r0, c3, c0, 0\n"
  40.         :    
  41.         :"r"(ttb)
  42.         :"r0"
  43.     );
  44. }



以下代码是小页映射

点击(此处)折叠或打开

  1. #include <common.h>
  2. #include <mmu.h>

  3. void mmu_enable(void)
  4. {
  5.     __asm__ __volatile__(
  6.         "mrc p15, 0, r0, c1, c0, 0\n"
  7.         "orr r0, r0, #1\n"
  8.         "mcr p15, 0, r0, c1, c0, 0\n"
  9.         :::"r0"
  10.     );
  11. }

  12. void mmu_disable(void)
  13. {
  14.     __asm__ __volatile__(
  15.         "mrc p15, 0, r0, c1, c0, 0\n"
  16.         "bic r0, r0, #1\n"
  17.         "mcr p15, 0, r0, c1, c0, 0\n"
  18.         :::"r0"
  19.     );
  20. }

  21. //运行一次映射4K内存
  22. //my_mmap(sssss, aaaa, 0x12345000, 0x56789000);
  23. void my_mmap(unsigned int *ttb1, unsigned int *ttb2, unsigned int va, unsigned int pa)
  24. {
  25.     ttb1[va >> 20] = ((unsigned int)ttb2 & (~0x3ff)) | 1;
  26.     ttb2[(va >> 12) & 0xff] = (pa & (~0xfff)) | 2;
  27. }

  28. void ttb_init(unsigned int *ttb1, unsigned int *ttb2)
  29. {
  30.     int va, pa;
  31.     int va1;
  32. /*va从0开始,每次加0x100000和段映射一样,表示0-2G的内容全部映射。而且物理地址和虚拟地址一样*/
  33.     for(va = 0; va < 0x80000000; va += 0x100000){
  34.         //0----1M,ttb1[va>>20]就是把0x100000*0-0x100000*0x800>>20位,右移后相当于i=0;ttb1[i++]
  35.         //figure10-3表明一级页表的内容为二级页表的基地址的高22位|表明是页映射
  36.         ttb1[va >> 20] = ((unsigned int)ttb2 & (~0x3ff)) | 1;
  37.         //0-4K 4K-8K 8K-12K 1M
  38.         /*va1=va是因为外循环一次就映射了1M的物理内存,而pa=va1主要是为了得到正确的物理内存偏移值;va1
  39.         for(va1 = va; va1 < va + 0x100000; va1 += 0x1000){
  40.             pa = va1;
  41.             //求得虚拟地址的中间8位 = 物理地址的高20位
  42.             ttb2[(va1 >> 12) & 0xff] = (pa & (~0xfff)) | 2;
  43.         }
  44.         ttb2 += 0x100;//二级页表每执行一次需要移动256个条目=1k=256*4
  45.     }    

  46.     __asm__ __volatile__(
  47.         "mcr p15, 0, %0, c2, c0, 0\n"
  48.         "mvn r0, #0\n"
  49.         "mcr p15, 0, r0, c3, c0, 0\n"
  50.         :    
  51.         :"r"(ttb1)
  52.         :"r0"
  53.     );
  54. }

关于对这张表格的理解:
一级页表基地址(Translation table base address)高18位 + 虚拟地址(Vlrtual Address)高12位,查找到一级页表对应的条目,为什么这么说呢?4G空间全部映射为虚拟地址,需要多少个一级页表条目呢(每一个条目代表1M空间)?4G :x个一级条目 = 1M : 1个一级条目。那么x = 1024 *4M/1M = 4096个。也就是说只需要4096=2^12个一级条目就可以表示了4G空间了,而虚拟地址的高12位正好可以寻址,这就对上了。你可能疑惑那一级页表的物理地址的第0和第1位为什么不用呢,这是因为一个条目占用4个字节,地址最后俩位不填,表示4字节对齐。

我们根据虚拟地址和一级页表基地址找到了一级页表中对应的条目,那这个条目里放的是什么东西呢?如上图,放的是二级页表的高22位物理地址,然后用这22位地址 + 虚拟地址的12到19位(8bit)就可以找到二级页表对应的物理地址了。这里的虚拟地址8个bit也是表示偏移,表示每一个一级条目对应2^8=256个二级条目,每一个二级条目表示真实的4K空间大小。然后用二级条目的12到31位 + 虚拟地址的低12位,找到了真实的虚拟地址对应的物理地址,可以精确到每一个字节。


TLB:Translation lookaside buffer,即旁路转换缓冲,或称为缓冲
TTB:Translation Table Base


阅读(4418) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~