转自:http://blog.csdn.net/martree/article/details/3321578

虚拟存储器的基本思想是程序,数据,堆栈的总的大小可以超过物理存储器的大小,操作系统把当前使用的部分保留在内存中,而把其他未被使用的部分保存在磁盘上。比 如对一个16MB的程序和一个内存只有4MB的机器,OS通过选择,可以决定各个时刻将哪4M的内容保留在内存中,并在需要时在内存和磁盘间交换程序片 段,这样就可以把这个16M的程序运行在一个只具有4M内存机器上了。而这个16M的程序在运行前不必由程序员进行分割。一个物理存储块(通常为一个页框)被多个逻辑页映射。
    
    伴随着这种技术的出现,“virtual address,即VA”和“physical address, 即PA”也就出现了。一般来说,CPU看到的地址是VA,VA是有地址线来决定的。比如,s3c2410是32位的SoC,那么它的寻址空间为 2^32=4GB,那么VA空间也就是4GB。但是在嵌入式系统中,物理存储器是不会有这么大的。现在这块s3c2410的实际内存SDRAM也就 64MB,远远小于4GB。也就是说,VA4GB,PA是64MB,PA的地址空间是VA地址空间的子集。既然PA没有VA那么大,而且CPU只能看到 VA,那么CPU如何找到PA呢?这也正是MMU的基本作用之一,就是提供VA到PA的转换机制,除了硬件的支持外,软件上实际就是维护一张表,表中的内 容是VA到PA的转换法则。由于有了MMU,那么就可以实现利用VA找到实际物理内存区域。具体的转换方法将在以后介绍。

现在讨论为什么要实现VA到PA的映射。就ARM而言,系统上电后,CPU的PC指向0x00000000或者0xffff0000,这是由CPU的设计 者决定的。在这个位置,一般安排非易失性存储器地址空间,比如rom,flash等。但是flash等响应速度慢,这就称为提高系统性能的一个瓶颈。而 sdram则具有很高的响应速度,为了提高系统运行速度,可以把flash中的应用程序下载到sdram中执行,也就是一个简单的loader的功能实 现。这样就出现一个问题,ARM响应exception时,程序指针指向固定的VA,比如,假设发生了IRQ中断,那么PC执行0x00000018(如 果是高端启动,则指向0xffff0018处。)但是此处仍然为非易失性存储器,也就是说,程序的一部分仍然在flash或者rom中执行。这时可以利用 MMU,把sdram的地址映射到0x00000000起始的一片连续地址空间,而把原来flash映射到其他不相冲突的存储空间位置。例如,flash 的地址范围0x00000000-0x00ffffff,sdram的地址范围0x30000000-0x31ffffff。那么可以把sdram映射到 0x00000000-0x1fffffff(此处地址空间未被占用)。映射完成后,如果处理器异常,假设依然为IRQ中断,pc指向 0x00000018,但是pc实际上是从物理地址0x30000018处读取指令。通过mmu的映射,可以实现系统运行的加速。这个地方也可以说明 bootloader中常见的中断向量表的设置,为什么有些使用b,有些使用ldr了。这个我们在基本指令使用中有着详细的描述。

在实际的应用过程中,还可能会把两片不连续的物理地址空间分配给sdram,而在os中,习惯上把sdram的空间连续起来,方便实现动态内存管理。通过mmu可以实现不连续的物理地址空间映射为虚拟地址空间。

 
    另外一个需求就是,实现不同的运行级别,那么一些关键的代码可以设定不被普通应用程序访问。这也是通过mmu控制访问权限来实现的。
 
    综上三个阶段所述,可见MMU的作用主要就是两个:
 
    · 实现VA到PA的映射(可以因此实现方便的动态内存管理)
    · 实现不同的访问权限。

结合s3c2410来分析MMU的几处硬件特点
 
    首先看看ARM920T的框图:
    可以验证前面的几个概念:
 
    ·位于中心的ARM9TDMI Processor Core发出的地址有两种,IVA和DVA,都是VA。其中I代表Instruction, D代表Data。也就是说,CPU核心看到的都是32bits的VA。
    ·Dcache、Icache、Dmmu、Immu看到的都是对应的MVA(modified virtual address),这个是比较复杂的地方,下面专门拿出这个来讲解。
    ·MMU处理后的输出地址都是对应的PA,通过AMBA Bus Interface连接到ASB总线上面。
 
    这样,从硬件上对地址的概念就比较清晰了。也可以很明显的看出MMU的功能:将VA转换成PA。但是现在存在的一个问题是,MVA是什么,为什么要用到MVA?
 
    可以看CP15协处理器的register 13。这个寄存器是进程识别寄存器,主要的操作如下:
 

Reading from CP15 register 13 returns the value of the process identifier. Writing CP15register 13 updates the process identifier to the value in bits [31:25]. Bits [24:0] should be zero.

 
    寄存器的字格式为:
 
    很清晰,ProcID为7bits,剩下的25bits should be zero,也就是可以实现2^25=32M的地址对齐。从这个道理上讲,每个进程拥有32M的MVA地址空间,而最多支持的进程数为2^7=128个。这 样,128*32M=4GB,正是全部的虚拟地址空间。但是,英文的datasheet上却并非如此,写的记录数字为64个进程,同样每个进程32M,怎 么可能达到4GB?参看下图:
 
 
    我觉得上图中的63应该改为127。因为这个63处不可能对应4GB,而应该对应2GB。判断此处属于datasheet的错误。
 
    还有,这个procID是何时,有谁写入的?有谁来维护?根据推断,在bootloader阶段,只需要一个进程就可以了,所以,procID一直都是复 位后默认的0,不需要改变。但是后面有了OS后,要想实现多进程,那么就需要对此维护了。所以procID的维护者是系统软件OS。在创建一个新进程的时 候,要把进程号写入procID。
 
    另外,关于MVA部分的转换公式,实际上还是有疑问的。
 

Addresses issued by the ARM9TDMI core in the range 0 to 32MB are translated by CP15 register13, the ProcID register. Address A becomes A + (ProcID x 32MB). It is this translated address that is seen by both the Caches and MMU. Addresses above 32MB undergo no translation.

 
    写成伪代码,可以参考《s3c2410完全开发》。
 

if VA < 32M then
        MVA = VA | (ProcID << 25)
else
        MVA = VA

 
    thisway.diy说利用PID来生成MVA的目的是为了减少切换进程时的代价:如果两个进程占用的VA有重叠,不进行上述处理的话,当进行进程切换 时必须进行VA到PA的重新映射,这就需要重新建立页表,使无效cache和TLB等等,代价很大。但是如果进行上述处理的话,进程切换就省事多了:假设 两个进程1、2运行时的VA都是0-32M,则它们的MVA分别是 (0x02000000-0x03ffffff)、(0x04000000-0x05ffffff),前面看到的MMU、cache使用MVA而不是使用 VA,这样就不必进行重建页表等工作了。
 
    但是这里带来的一个问题是,如果进程运行时的VA小于32M,那么根据PID的不同,可以达到4GB空间的任意部分,也就是,虽然可以避免运行VA小于 32M时的不同进程的“撞车”,但是同时带来的是VA小于32M可能与VA大于32M的进程产生了“撞车”。这样不是更为普遍吗?现在从原理上还不能理 解。翻看《ARM Architecture Reference Manual》,发现对于ARM核,如果采用MVA,那么进程切换实际上对应着Fast context switch extension,不知道原理是什么。对于研究bootloader来说,现在不设计到多进程,整个系统就是一个独立的单进程,PID就是默认的 0x0。这个问题可能要后推了。
 
四、提出几个问题
 
    1、在vivi中为什么使用了MMU?是否可以不用?
 
    这个问题已经解决。实际上,在nand flash启动的情况下,vivi中可以不使用MMU。因为一是中断向量表是放在sram里,响应速度比sdram还要快。另外,在bootloader 阶段,只有一个进程,不存在多进程的内存空间重叠的问题。也因为一个进程,所以单纯的PA就满足需求,没有必要用VA。开始时,也不需要区分访问权限。大 量的工作,比如进程切换、权限访问等等,都是在EOS中处理的。所以,这种情况下,可以不使用MMU。我把vivi中关于MMU的部分去除,编译下载,可 以正常引导内核启动,没有问题。
 
    那么,vivi为什么要开启MMU呢?原因也是比较简单的,就是追求系统运行的高效。因为s3c2410的Icache不受MMU的影响,而Dcache 和write buffer则必须开启了MMU功能之后,才能使用。而使用Dcache和write buffer后,对系统运行速度的提高是非常明显的,后面还将通过实验来验证这一点。也就是说,在nand flash启动时,vivi使用了MMU,主要是为了获得Dcache和write buffer的使用权,借此提高系统运行的性能。
 
    2、使用了MMU,那么软硬件是如何分工协作的?
 
    这个基本搞清楚了,但是还有一个遗留问题。针对于s3c2410,可以分为如下几个阶段:
 
    · 第一阶段  软件准备
 
    MMU在软件上的实现过程,实际上就是一个查表映射的过程。建立页表(translation table)是MMU功能的重要的一步。页表就是内存的一块区域,由一个个固定格式的entry组成。其中每个entry对应一个VA到PA的转换,每一 项的长度是一个word,还可以完成访问权限和缓冲特性的限定。在软件上,就是要把这个表填好。重映射就是修改相应的entry,改变了原来的映射规则, 很简单。
 
    这步工作是要软件提前准备的。需要注意的是,明确如何找到这个页表。对于表的查找,需要知道表的基地址和偏移地址,在cp15的register 2用于保存页表的基地址,这样就可以查找到相应的PA了。
 
    · 第二阶段 硬件完成VA-MVA
 
    硬件根据ARM9TDMI发出的VA和CP15的register 13来自动生成MVA。
 
    · 第三个阶段
 
    硬件自动实现cache查询,如果没有,则根据cp15的register 2和MVA找到translation table中的entry,实现相应的PA转换,读取内存,然后根据cache算法更新cache。也就是说,这个阶段也是硬件实现的。不过软件上对 cache要进行相应的管理,这个地方的算法相对还是比较复杂的。
 
    综上,对单进程而言,软件操作上就是维护translation table,并且处理好cache相关操作。
 
五、实验
 
    实验内容比较简单,综合了前面的串口实验,灯循环点亮实验,中断实验,nand flash实验,另外,加入了MMU功能。利用MMU功能的开启,观察灯循环点亮实验,如果开启了Dcache和write buffer,灯闪的速度明显快的多,几乎看不出间隔,而把其关闭,则还能够看出间隔。这还是在12MHz的前提下,还没有把PLL功能开启。如果把 PLL功能开启,还需要进行相应的调整。
 
    源代码如下,完全仿照vivi的架构,另外,mmu部分基本是采用vivi的源代码,具体的分析留待vivi源代码分析时解决。其实,如果开启了 mmu,cache和write buffer是否能够合理有效的使用还是一个问题。如果使用不当,带来的问题可能会比较奇怪,而且难以解决。在这个过程中,需要对照现有的较好的代码进行 分析,总结规律,然后应用到自己的设计中去。

MMU介绍【转】的更多相关文章

  1. 第七章 内存管理单元MMU介绍

    7.1 内存管理单元MMU介绍 7.1.1 S3C2410/S3C2440 MMU特性 负责虚拟地址到物理地址的映射,并提供硬件机制的内存访问权限检查 特性: 与ARM V4兼容的映射长度.域.访问权 ...

  2. mmu介绍

    arm exynos4412平台mmu配置以及的简单创建. 1.mmu的全称是Memory Management Unit(内存管理单元) 2.mmu所在位置.mmu再arm核心.他不是一个外设,他是 ...

  3. 转 s3c2440硬件学习----内存管理单元MMU

    本篇基本是韦东山书上的 一.内存管理单元MMU介绍 内存管理单元简称MMU,它负责虚拟地址到物理地址的映射,并提供硬件机制的内存访问权限检查.MMU使得每个用户进程拥有自己独立的地址空间,并通过内存访 ...

  4. 三、内存管理单元---MMU

    3.1 MMU介绍 3.1.1 MMU 特性 内存管理单元(Memory Management Unit)简称MMU,它负责虚拟地址到物理地址的映射,并提供硬件机制的内存访问权限检查.现在的多用户多进 ...

  5. u-boot移植(八)---代码修改---存储控制器--MMU

    一.MMU介绍 1.1 虚拟地址与物理地址 建立两个应用程序,hello1.c和hello2.c,然后运行: hello1.c hello2.c 运行结果如下: 可以看到两个结果打印的地址是一样的,都 ...

  6. MMU实验

    内存管理单元 MMU介绍:权限管理:地址映射 权限管理:内核->A->B 地址空间各不相同 地址映射:多任务系统也是分时系统 虚拟地址(地址空间)->MMU->物理地址 SDR ...

  7. JZ2440 裸机驱动 第7章 内存管理单元MMU

    本章目标:     了解虚拟地址和物理地址的关系:     掌握如何通过设置MMU来控制虚拟地址到物理地址的转化:     了解MMU的内存访问权限机制:     了解TLB.Cache.Write ...

  8. 十三、S3C2440 裸机 — 初始化代码及MMU

    13.1 NOR FLASH 搬运 把程序从 nor flash 上搬运到 SDRAM 中 程序存储在 nor flash 上,运行时将程序搬运到 SDRAM 中运行 nor flash 启动:nor ...

  9. 内存管理单元(MMU)和协处理器CP15介绍(转)

    内存管理单元(MMU)和协处理器CP15介绍内存管理单元(MMU)介绍嵌入式系统中,存储系统差别很大,可包含多种类型的存储器件,如FLASH,SRAM,SDRAM,ROM等,这些不同类型的存储器件速度 ...

随机推荐

  1. Django runserver支持https

    创建自签名ssl证书 1.下载软件openssl-0.9.8k_WIN32 2.解压后进入bin目录,双击打开openssl.exe,依次运行如下命令 genrsa -des3 -out server ...

  2. stark组件(1):动态生成URL

    项目启动时自动生成URL 效果图: 知识点: Django启动前通过apps下的ready方法执行一个可以生成URL的py文件 include函数主要返回有三个元素的一个元组.第一个是url配置(ur ...

  3. 【PyTorch深度学习】学习笔记之PyTorch与深度学习

    第1章 PyTorch与深度学习 深度学习的应用 接近人类水平的图像分类 接近人类水平的语音识别 机器翻译 自动驾驶汽车 Siri.Google语音和Alexa在最近几年更加准确 日本农民的黄瓜智能分 ...

  4. shell脚本杀掉指定进程下所有子进程(包括子进程的子进程)

    搜索了网上好像并没有杀掉指定进程下所有子进程(包括子进程的子进程)的脚本,自己琢磨写了一版,虽说比较简单,但希望分享大家,帮助需要的人 #!/bin/sh # 递归找到进程最底层子进程并杀除. mai ...

  5. Eclipse主题更换方法

    1.打开Eclipse的Help->Eclipse Marketplace 2.在Find里搜索Eclipse Color Theme,点击Install按钮 3.打开Window->Pr ...

  6. Redis实现之对象(四)

    类型检查与命令多态 Redis中用于操作键的命令基本上可以分为两种类型:其中一种命令可以对任何类型的键执行,比如DEL命令.EXPIRE命令.RENAME命令.TYPE命令.OBJECT命令等.举个栗 ...

  7. Java-读取txt生成excel

    本段代码的目的是从txt文本中读取相应格式的数据,然后写入到对应格式的excel文档中 在敲本段代码的时候,也学习了一些其它知识点,如下: 1.byte[] b_charset= String.get ...

  8. vs code 快捷键总结

    返回上个光标:alt + ←列编辑模式:shift + alt + 鼠标左键

  9. luoguT30204 偷上网

    \(n=1\) 时特判四角,其余时刻圆的面积和必小于正方形面积,随机点出来判断就行了. stm 随机算法-- #include <iostream> #include <cstdli ...

  10. IOS开发---菜鸟学习之路--(十四)-将BASE64图片转换成Image

    本文基本全部都是代码 首先是.H文件 #import <Foundation/Foundation.h> @interface Base64AndImageHelp : NSObject ...