本文共 2790 字,大约阅读时间需要 9 分钟。
目录
说明1:VMSA即虚拟地址系统架构(Virtual Memory System Architecture),该系统架构在MMU之上。目的是在复杂的系统中,给不同进程提供独立且受保护的地址空间。
说明2:地址转换表和TLB的关系
① 地址转换表(Translation Table)由用户设置并存储在内存中,其基地址(TTB,Translation Table Base)需要载入cp15的c2寄存器方可控制MMU的工作
② 地址转换表中的每个表项记录了VA到PA的转换规则,但是如果每次地址转换都去检索Translation Table代价太大(因为Translation Table在内存中,访问他需要访问内存),因此引入了TLB(Translation Lookaside Buffers)
只有当要查找的表项不在TLB时(即TLB miss),硬件才会执行translation table walk,并根据算法更新TLB
说明3:TLB表项内容
① 虚拟地址到物理地址的映射关系
MVA(Modified Virtual Address) + page size + 物理地址
注:每个VA和PA的对应关系都描述的是一段区域,所以指定起始对应的VA和PA,再加上page size就可以描述一个地址映射的关系
② 内存访问控制属性
用于控制一个进程对该内存区域是否有访问权限以及有怎样的访问权限(无权限 / 只读权限 / 读写权限)
③ 内存区域属性
用于描述该内存区域的特性,比如是否可以进入cache或write buffer
说明4:对于冯诺依曼结构的ARM核,只有一个TLB;对于哈佛结构的ARM核,可以实现独立的I / D TLB
根据上文描述,MMU主要具有如下2点功能:
① 将虚拟地址转换为物理地址
② 内存访问权限管理
注意:一旦开启MMU,在软件层面就不存在物理地址了,此时ARM核产生的所有地址都是虚拟地址,都会经过MMU实现转换
补充:上图中,每个进程的虚拟地址相同,但是实际使用的物理地址不同。实现这点,是因为每个进程有自己的地址转换页表
说明:由于只有ARM920T的内核手册比较详细,所以本节基于该架构进行说明。但是ARM920T使用VMSAv4架构MMU,而从VMSAv6架构开始MMU的配置有较大变化,在行文中会根据实际情况加以说明
在实现中我们也仿照uboot设置.mmudata段存储一级页表
在映射方式上选择段式线性映射,注意在对应内存的映射区域使用cache和write buffer
最后在初始化过程中增加对MMU的设置
经上机测试,各外设及中断可以正常运行~~
时间:2018/5/20
现象:由于x210开发板USB OTG接口损坏,无法使用dnw下载代码运行,只能通过eMMC或SD卡启动,在使用SD卡启动的过程中发现在dnw模式中可用的代码在SD卡启动中无法使用
① 通过增加LED点灯debug,发现在enable_icache之后点灯可以,但是在clock_init之后点灯失败
② 之后将点灯调用点放在clock_init函数起始处,发现点灯依然失败,可见bl clock_init调用并未进入clock_init函数
clock_init函数在单独的clock.S文件中实现,而并未指定该文件的链接顺序,因此可能不在16KB之内,因此修改链接器脚本,指定其链接顺序
修改后发现在clock_init函数起始处点灯依然失败,也就是说依然没有成功调用到clock_init函数
③ 由于clock.o的链接顺序仅次于start.o,所以可能的问题就是start.o本身就超过16KB,那么无论如何是无法在BL1阶段调用到clock_init函数的
之后发现start.o已经 > 50KB,因此从cc_bootloader.bin中截取16KB,根本无法调用到clock_init函数
④ start.o文件较大的原因主要在于MMU的Translation Table定义在该文件,而且Translation Table还要求16KB对齐,因此更加扩大了start.o的体积
特别注意:x210 uboot中的Translation Table应该被链接至.mmudata段,而非.text段
从反汇编结果看,mmu_table确实被链接至该段,整个uboot.bin大小为384KB,而mmu_table的链接地址较链接起始地址(0xc3e00000)相距368KB
上面"mmu_table确实被链接至该段"的理解是错误的,在uboot的反汇编文件中并未找到mmudata段,后文中有描述,在.text & .mmudata混合代码编译的目标文件中确实没有.mmudata段
需要注意的是,cc_bootloader中也将mmu_table链接至.mmudata段,但是从反汇编看并未成功。原因应该是在.mmudata段之后仍有代码部分,导致2个段混编,结果均链接到了.text段(在反汇编中确实找不到.mmudata段)
我们尝试将mmu_table的定义放在start.S的最后,但从反汇编结果看依然没有成功
① x210 uboot如何配置MMU
我们先分析一下实现该任务的依赖项,
a. 在前16KB完成内存初始化和代码重定位、设置MMU,最后跳转到内存中运行
b. 设置并使能MMU后,软件层面均为VA,需要查找Translation Table确定PA
这就要求在使能MMU之前需要先将Translation Table重定位到内存中
因此x210 uboot中采用了如下的代码布局,
a. 在lowlevel_init.S中定义mmu_table,并链接至.mmudata段
b. 遵循如下操作顺序,
代码重定位(SD --> DDR) --> 设置并使能MMU --> 跳转到DDR继续运行
② cc_bootloader的MMU布局
a. 新建init/mmu.S文件,在其中定义mmu_table,并将其链接到.mmudata段
b. 使能MMU的函数enable_mmu仍保留在init/start.S中
经过验证,此时SD卡启动可正常运行,且mmu_table确实被链接到.mmudata端,链接地址距链接起始地址32KB
tips:cc_bootloader能在start.S中使能MMU并运行,是因为cc_bootloader中仅进行了线性映射
转载地址:http://bhwx.baihongyu.com/