"); //-->
MMU的作用:
虚拟地址到物理地址的映射(虚存系统通过将大的虚拟地址空间中的地址转换成物理内存空间,而扩充程序可使用的地址空间)
保护内存,定义高速缓存(Cache)协议
重定位(Reloaction):程序的函数方法和预先声明的数据地址均在编译期间决定,MMU允许程序在任何物理地址运行
为程序分配内存:MMU可以从物理内存里许多零散的页中创建连续的程序空间,使我们能从一个充满固定大小页面的池里分配内存。如果我们不停分配释放大小不一的内存块,就会碰上内存碎片问题:我们不得不止步于一个布满“小孤岛”的内存空间,无法满足对较大块内存的申请要求,哪怕此时所有的空闲空间之和是足够的。
隐藏和保护:用户级程序只能访问kuseg内存区域(较低的程序地址)内的数据。这类程序只能在操作系统所许可的内存区域中取得数据。此外,每一页可以独立的指定为可写权限或者写保护权限;操作系统甚至可以停止一个意外的写覆盖代码空间的应用程序。
扩展地址空间: 有些CPU不能直接访问它们拥有的全部物理空间。尽管MIPS I 系列CPU是真正的32位体系结构,它们却布局了地址映射,使得未被映射的地址空间窗口kseg0和kseg1(它们不依赖MMU进行地址转换)落在了物理内存的开头的512M内。如果你要访问更高地址,则必须通过MMU。
内存映射对程序的适应化:在MMU的帮助下,你的程序能够去使用适合它的地址。同一段程序的许多份拷贝可能会同时运行在一个庞大的操作系统里,令它们去使用相同的程序地址变得更容易。
调页能力:程序可以好像已经得到它们所申请分配的所有资源一样正常的运行,而操作系统实际上只分配给它们当前所需的资源。访问未分配空间的程序会导致一个交由操作系统处理的异常(exception),操作系统此时才在这块内存中装入适当数据并令应用程序继续运行。
下面先看看MIPS的地址空间(32bit):
我们就主要说一下kseg0 & kseg1这两段空间:
kseg0: 0x8000 0000 - 0x9FFF FFFF(512M)
只需要把最高位清零(&0x7fffffff),这些地址就被转换为物理地址,然后把它们连续地映射到物理内存的低端512M(0x0000 0000 - 0x1FFF FFFF)空间。
因为这种映射是很简单的,不需要MMU转换,通常把这些地址称为“非翻译无需转换的”(Unmapped)地址区域。
对这段地址的存取都会通过高速缓存(cached)。因此在缓存(cache)未进行初始化之前,不要使用这段地址。
通常在没有MMU的系统中,这段空间用于存放大多数程序和数据。对于有MMU的系统,操作系统的内核会存放在这个区域。
kseg1: 0xA000 0000 - 0xBFFF FFFF(512M)
过将最高3位清零(&0x1fffffff)的方法来把这些地址映射为相应的物理地址,与kseg0映射的物理地址一样,都映射到物理内存的低端512M(0x0000 0000 - 0x1FFF FFFF)空间,也是“非翻译无需转换的”(Unmapped)地址区域。但要注意,kseg1不使用缓存(Uncached)。
kseg1是唯一的在系统重启时能正常工作的内存映射地址空间,这也是为什么重新启动时的入口向量是(0xBFC0 0000)会在这个区域。这个向量对应的物理地址是0x1FC0 0000。
因此你可以使用这段地址空间来访问你的初始化程序的ROM。还有大多数人把它用来访问I/O寄存器。如果你的硬件工程师要把这段地址映射到非低端512M空间,你应该试图说服他们。
对于简单的嵌入式软件而言,在使用kseg0和kseg1这两段区域内的地址时,其程序地址和物理地址之间的关系是很密切的。
大多数的简单系统会对512MB以下的空间完全映射,对于MIPS平台上的物理地址空间(>=32位),工业界长期形成的惯例是将0x0000 0000 ~ 0x1000 0000给内存(512M的前256M映射到kseg0),而将0x1000 0000 ~ 0x1FFF FFFF留给I/O(512M的后256M映射到kseg1,用作I/O)。
从物理地址0x2000 0000(512MB)以上的地址空间不能被映射到任何地址,但是在需要时,可以通过在MMU内设置转换入口(TLB)的方式,或者使用64位CPU中的一些额外空间对较高的地址进行访问。
当系统内存大于256MB时,kseg0的空间不够用,则需要启用High Memory机制,使用kseg2的空间,通过TLB建立映射去访问。对64位情形,则不存在这个问题,因为64位Linux使用xkphys区域访问物理内存,cached和uncached区域与整个物理地址空间一样大,足够用矣。
所以真正使用时kseg0一般给内核使用,kseg1一般作为设备地址空间使用。划分的话,可以各占一半,譬如在mips32里,kseg0使用0x8000_0000到0x9000_0000;kseg1使用0xB000_0000到0xC000_0000,各256M即可。
现在对这512M的空间的划分总算明白,也即是我们在看Code时候发现Device的Base都是BXXXXXXX的原因了,下面具体一个Datasheet看看512M的具体分配:
0x00000000---0x0FFFFFFF 256M SDRAM空间
0x10000000---0x11FFFFFF 32M IO Device
0x12000000---0x13FFFFFF 32M Reserved
0x14000000---0x17FFFFFF 64M IO Device/mem
0x18000000---0x1FFFFFFF 128M mem(boot)
0-256MB是SDRAM(DDR)
256MB-512MB是外设寄存器(所谓的memory maped register)
再次确认我们在Code看到:
#define UART_BASE_U_VIRTUAL ( 0xB0030000 )
B0000000 - A0000000 = 10000000 = 256M 所以说256M是给sdram使用的
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。