在32位MIPS体系结构下,最多可寻址4GB地址空间。这4GB空间的分配是怎样的呢?让我们看下面这张图:
+----------------------------------------------+ | | 0xFFFFFFFF | | | | | Kernel Space Mapped Cached | | | | | 0xC0000000 | | +----------------------------------------------+ | | 0xBFFFFFFF | Kernel Space Unmapped Uncached | | | 0xA0000000 +----------------------------------------------+ | | 0x9FFFFFFF | Kernel Space Unmapped Cached | | | 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 Cached 和 0xA0000000到0xBFFFFFFF的Kernel Space Unmapped Uncached。之所以说它们特殊,是因为这两段逻辑地址到物理地址的映射关系是硬件直接确定的,不通过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来执行。这是后话。