分类: 嵌入式
2015-10-20 07:48:25
//在网上寻了很久,没有找到原创者。此文可以解决编程者很多"Why"的问题;
在32位MIPS体系结构下,最多可寻址4GB地址空间。这4GB空间的分配是怎样的呢?让我们看下面这张图:
+----------------------------------------------+
| | 0xFFFFFFFF
| |
| |
| Kernel Space Mapped Cached (Kseg2) |
| |
| |
0xC0000000 | |
+----------------------------------------------+
| | 0xBFFFFFFF
| Kernel Space Unmapped UnCached (Kseg1) |
| |
0xA0000000 +----------------------------------------------+
| | 0x9FFFFFFF
| Kernel Space Unmapped
cached (Kseg0) |
| |
0x80000000 +----------------------------------------------+
| | 0x7FFFFFFF
| |
| |
| |
| User Space |
| |
| |
| |
| |
| |
0x00000000 +----------------------------------------------+
Figure 2-1 MIPS Logical Addressing Space
上图是MIPS处理器的逻辑寻址空间分布图。我们看到,2GB以下的地址空间,也就是从0x00000000到0x7FFFFFFF的这一段空间,为User
Space,可以在User Mode下访问,当然,在Kernel Mode下也是可以访问的。程序在访问User
Space的内存时,会通过MMU的TLB,映射到实际的物理地址上。也就是说,这一段逻辑地址空间和物理地址空间的对应关系,是由MMU中的TLB表项决定的。
从0x80000000到0xFFFFFFFF的一段为Kernel Space,仅限于Kernel Mode访问。如果在User
Mode下试图访问这一段内存,将会引发系统的一个Exception。MIPS的 Kernel
Space又可以划分为三部分。首先是通过MMU映射到物理地址的1GB空间,地址范围从0xC0000000到0xFFFFFFFF。这1GB空间可以用来访问实际的DRAM内存,可以为操作系统的内核所用。
MIPS的Kernel Space中,还有两段特殊的地址空间,分别是从0x80000000到0x9FFFFFFF的Kernel
Space Unmapped Uncached和0xA0000000到0xBFFFFFFF的Kernel Space Unmapped
Cached。之所以说它们特殊,是因为这两段逻辑地址到物理地址的映射关系是硬件直接确定的,不通过MMU,而且两段实际上是重叠的,均对应
0x00000000到0x20000000的物理地址。那么,为什么一段同样的物理地址有两个逻辑地址对应呢?它们的区别又在哪里呢?
原来,这是MIPS的设计特色之一。软件在访问Kernel Space Unmapped
Uncached这段地址空间的时候,不经过MIPS的Cache。这样,虽然速度会比较慢,但是,对于硬件I/O寄存器来说,就不存在所谓的Cache
一致性问题。Cache一致性问题,是指硬件将某个地址的内容跳过软件而改变了,Cache中的内容尚未同步。这样,如果软件读取该地址,有可能从
Cache中获取到错误的内容。将硬件I/O寄存器设定在这段地址空间,就可以避免Cache一致性带来的问题。MIPS的程序上电启动地址
0xBFC00000,也落在这段地址空间内。——上电时,MMU和Cache均未初始化,因此,只有这段地址空间可以正常读取并处理。
另一段特殊的地址Kernel Space Unapped
Cached,与前者类似,直接映射到0x00000000到0x20000000,与Kernel Space Unmapped
Uncached重叠。因为通过Cache,这段地址空间的访问速度比前者为快。一般地,这段内存空间用于内核代码段,或者内核中的堆栈。
显然地,当工程师们换算Kernel Space中的这两段的物理地址和逻辑地址时,只需要改变地址的高3bit就可以了。
那么,什么时候需要使用物理地址,什么时候需要使用逻辑地址呢?我们知道,逻辑地址是程序中访问的内存地址,譬如,下面的这条指令:
lw a0, 128(t2)
这条指令的内容是从t2寄存器内的地址 + 偏移128字节处,读取一个word
(4Byte)到寄存器a0内。如果t2的值为0x88200100,则最终访问的物理地址为0x88200180。
而物理地址,从工程上可以理解为,将逻辑分析仪连接到内存总线(Memory
Bus)上,逻辑分析仪指示的地址,就是物理地址。假如,在上一个例子中,我们把逻辑分析仪接到处理器的前端内存总线,我们就可以看到,执行该指令时,系
统访问的物理地址为0x08200180。物理地址和逻辑地址的换算,不仅限于电子工程师在设计硬件线路时需要。在内核工程师编写支持DMA的外部设备驱
动时,需要将向操作系统申请到的数据缓冲区地址(当然,这是一个逻辑地址)转换为物理地址,并“告诉”相关外设。这样,外设就可以在收到数据后,使用
DMA模式储存在系统的主存中,并向系统发起一个IRQ。操作系统在IRQ的handler中,从外设的相应IO寄存器读取到这段内存的地址(当然,是物
理地址)并转换为逻辑地址并处理之。这个过程中,如果没有正确使用和分辨物理地址和逻辑地址,驱动程序便会导致内核的一个panic错误。
物理地址到逻辑地址的映射关系是由什么决定的呢?除了上面提到的两段Unmapped的地址空间,其余都是由TLB确定的,由MMU来执行。这是后话。