Cavium MIPS的内存布局
这里主要想讨论MIPS架构的内存分配问题,对Cavium的了解比较多,所以从熟悉的芯片开始做衍生。Cavium的架构基本上会遵循MIPS的内存分配规则,不会有太大的差异。所以以下讨论均基于Cavium的MIPS架构。
一、物理地址的分配
关于物理内存的讨论,也是基于64bit架构的。MIPS的64bit架构在上世纪90年代开始了。其技术一直都领先于其他的架构处理器。MIPS中采用统一编址架构,IO和Memory使用同样的访问方式。在64bit中实际使用49bits来实现物理地址的访问,其中包括system memory(DRAM) 和IO space。PABITS=49,也就是bits<48::0>。
49bits物理地址格式
其中
IO---I/O bit,决定是访问memory 还是IO space
DID---直接访问的hardware block,映射到芯片中的不同的IO 部件上。
Offset –memory或者IO空间的地址值。
那么以这种方式实现的设计是如何的呢?下图中可以大概的列出物理地址的分配问题。
IO部分的分配:
System memory部分的分配:
针对system memory这一块,系统实际上只使用了36bits来寻址16G的system memory,所以,Cavium MIPS只支持到16G的物理内存大小。但是我们从图上可以看到,真正起作用的也只有35bits而已,这个足以实现16G system memory的访问了。
值得注意的是,图中这这16G 物理内存的寻址空间是有非连续的,分成了三部分:
DR0:256MB [0x0 – 0xfff_ffff]
DR1:256MB [0x4_1000_0000 – 0x4_1fff_ffff]
DR2:15.5GB [0x2000_0000 – 0x3_ffff_ffff]
好像是,DR1部分本来该在[0x1000_0000 – 0x1fff_ffff]段的,但是被抠出来放到了高端地址部分了。但是实际上这里有个转换动作,由于在启动的时候bootbus部分bfc0_0000会映射到物理内存的低端地址处,也就是0x1000_0000 –0x1fff_ffff中间一段。所以,system memory不会使用这段地址,而是在等待bootbus的寻址已经完成之后,比如启动稳定之后,系统对memory的访问,Dram controller会将bit[35:34]屏蔽掉,那么对DR1的访问自然就会映射到地址段0x1000_0000 – 0x1fff_ffff部分了。所以这时候DRAM controller看16G的system memory是连续的。
二、32bit的虚拟内存的讨论(本节为转载,写的很好,就没有自己另外去写了)
在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 AddressingSpace
上图是MIPS处理器的逻辑寻址空间分布图。我们看到,2GB以下的地址空间,也就是从0x00000000到0x7FFFFFFF的这一段空间,为User Space,可以在User Mode下访问,当然,在Kernel Mode下也是可以访问的。程序在访问UserSpace的内存时,会通过MMU的TLB,映射到实际的物理地址上。也就是说,这一段逻辑地址空间和物理地址空间的对应关系,是由MMU中的TLB表项决定的。
从0x80000000到0xFFFFFFFF的一段为Kernel Space,仅限于KernelMode访问。如果在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,与KernelSpace Unmapped Uncached重叠。因为通过Cache,这段地址空间的访问速度比前者为快。一般地,这段内存空间用于内核代码段,或者内核中的堆栈。
显然地,当工程师们换算Kernel Space中的这两段的物理地址和逻辑地址时,只需要改变地址的高3bit就可以了。
三、64bit的虚拟内存的讨论
MIPS的虚拟内存的划分是以‘segments’来实现的,但不是所有的segments都是可以映射的。虚拟地址的转换需要依赖这些条件:
1、 地址空间使用的address bits :64bit 或者32bit 地址空间。
2、 Segment 的选址
3、 权限级别:kernel、supervisor 或者user。
对于64bit的虚拟地址映射,虚拟地址的高位的两个bit用来选择四个segment中的一个,当然这些地址位的转换都是由Hardware来完成的。剩下的62bits则有部分bit是忽略被处理器忽略的。如下图所示:
在64bit的虚拟地址空间中,可以划分为四个segment:xkseg、xkphys、xsseg、suseg等。如下图所画,分别所处的地址空间为:
Xkseg:0xc000_0000_0000_0000 –- 0xffff_ffff_ffff_ffff :kernel mapped
Xkphys: 0x8000_0000_0000_0000 -– 0xbfff_ffff_ffff_ffff ;kernel unmapped
Xsseg: 0x4000_0000_0000_0000 -– 0x7fff_ffff_ffff_ffff ;supervisor mapped
Suseg: 0x0000_0000_0000_0000 -– 0x3fff_ffff_ffff_ffff ;user mapped
而64bit是兼容32bit的,处理方式就是将32bit的虚拟地址的高位进行扩展。比如32地址0x7fff_fff0,最高位是0,扩展到64bit之后,变成了0x0000_0000_7fff_fff0;而比如地址0x8000_fff0,最高位是1,扩展到64bit之后,变成了0xfff_ffff_8000_fff0. 依据这种方式,那么32bit的地址空间扩展到64bit的地址空间是怎么样的呢? 下图也有划分出来。之前的低字节的2G部分user space 依然扩展到64bit地址空间的低字节部分2G。而之前的高字节部分2G kernel space 扩展到64bit空间的最高端2G。