代码改变世界

龙芯地址空间详解

2014-06-18 10:01  cmLighters  阅读(3722)  评论(0编辑  收藏  举报

概念解释


地址空间:指某一特定寻址摸下所能覆盖的所有可寻址范围。MIPS64架构下包含一个64位地址空间和一个32位地址空间。32位地址空间是64位地址空间的子集。

段:地址空间的子集,同一段内地址空间具有一致的映射方式和缓存方式等访问属性。在MIPS64架构中,其32位地址空间被分成四段,即常说的kuseg,kseg0~2。其64位地址空间可被分割成更多的段,段大小理论上不超过262字节。实际中不需要这么大的段,实际实现以SEGBITS表示段的大小,即2SEGBITS字节。

映射地址与非映射地址:映射地址的地址指该地址需要经过TLB进行虚实地址转换;非映射地址指该地址不需经过TLB进行虚实地址转换,虚地址被直接映射到物理地址的最低部分。上述两种地址都是CPU给出的虚拟地址。

 

 

地址空间划分与寻址


先分析MIPS64架构下的32位地址空间。

image
      地址空间被分成四段,低2G地址空间(kuseg)是用户模式下可用的地址空间,核心模式下4G地址空间都能被访问。kuseg和kseg2属于映射地址,kseg0和kseg1属于非映射地址,映射到物理地址的低512M处。kseg1是非缓存的,即不需经过cache访问,系统ROM和启动时入口向量就存于这个地址段内,因为系统启动时cache还未进行初始化。

再介绍64位地址空间划分:

image

其中最高2G地址空间划分类似32地址空间的kseg0~2,最低2G地址空间划分类似于32位地址空间的kuseg,这样划分有利于32位程序兼容。各段的具体划分如下:

image

在龙芯64位处理器中,以龙芯3A1500的64位地址划分如下,其段大小始终为48:imageimageimageimage

上图中kseg0 段与 kseg1 段直接映射到物理地址空间的最低 0.5G字节,即虚地址0xFFFF.FFFF.A000.000 ~ 0xFFFF.FFFF.BFFF.FFFF 映射至物理地址 0x0000.0000.0000.0000 ~ 0x0000.0000.1FFF.FFFF,虚地址 0xFFFF.FFFF.8000.000 ~ 0xFFFF.FFFF.9FFF.FFFF 也映射至物理地址0x0000.0000.0000.0000 ~ 0x0000.0000.1FFF.FFFF。kseg0 段的缓存一致属性由Config.K0 域决定,kseg1 段永远为非缓存属性(Uncached)。

xkphys 段采用非映射方式,其包含 8个子地址段,每个子地址段大小为 248字节。 xkphys段的虚地址解析方式如下图所示。虚地址的[58:48]必须为全 0,否则为非法地址。虚地址的[47:0]不经过TLB 或其它任何翻译过程。直接作为物理地址。虚地址的[61:59]位用于定义所对应的子地址段的缓存一致属性,其采用的编码方式下表给出。

xkphys段虚地址解析方式

image   

缓存一致属性解

image

当Status.ERL=1 时,kuseg段为非映射地址段,同时其缓存一致属性为非缓存,类似于kseg1段。这一特性是为了在处理Cache错例外时,软件在保存上下文时可以利用通用寄存器 R0 作为基址寄存器将其它通用寄存器存入内存,同时由于Cache 中存在错误,所以访存操作都不再进行缓存。

当处理器处于调试模式时( Debug.DM=1 ), kseg3 段中虚地址 0xFFFF.FFFF.FF20.0000 ~ 0xFFFF.FFFF.FF3F.FFFF的地址范围将作为特殊的内存地址映射区域——EJTAG的 dseg段。

用户模式下,在64位 MIPS 处理器上兼容运行32 位程序时,对于数据访问的虚地址要进行特殊处理。这是因为一个在32位MIPS处理器上能够得到合法地址的计算过程在64位MIPS处理器上可能会产生非预期的效果。例如,如下指令序列:

la r1, 0x80000000

lw r2, -4(r1)

在32位MIPS 处理器上执行时,lw指令的虚地址为0x80000000 + 0xFFFFFFFC = 0x7FFFFFFF。所得地址仍落在kuseg段。但是这段代码在64位MIPS处理器上执行时, lw指令的虚地址位0xFFFFFFFF80000000 + 0xFFFFFFFFFFFFFFFC = 0xFFFFFFFF7FFFFFFC。所得的地址已经不在 kuseg 段,将会导致地址错例外发生。为了保持 64位处理器对于 32位程序的兼容,当Status.UX=0 时,数据访问虚地址的计算进行了特殊处理。具体方式是,地址运算仍采用符号扩展后的两个 64 位数相加,但是将所得的结果的高 32 位丢弃,由结果的第 31位符号扩展至结果虚地址的 63..32位。这样特殊处理之后的虚地址结果才用于地址的合法性检查、 TLB 映射等操作。正常的取指操作不会涉及该问题,因为 32位用户模式下合法PC的第31位一定为0,不会出现上面所举的违例情况。

 

龙芯3A寻址详解


龙芯3号节点结构如下图左,内部具体结构如图右:

clip_image004clip_image002

在每个节点内部,通过8*8的交叉开关将4个处理器核连接到四个master开关上,再通过对应四个slave开关连接到四个交替存储二级缓存,第5、6主从交叉开关暂时不用,可用于以后扩展(如增加cpu数量达到片内6核或者增加HT数目),通过四对Master/Slave 端口连接东、南、西、北四个方向的其他结点或IO结点(图中 EM/ES、SM/SS、WM/WS、NM/NS)。

X2 交叉开关通过四个 Master 端口连接四个二级 Cache,至少一个 Slave 端口连接一个内存控制器,至少一个 Slave 端口连接一个交叉开关的配置模块(Xconf)用于配置本结点的X1和X2的地址窗口等。还可以根据需要连接更多的内存控制器和 IO端口等。

龙芯 3A 是一个配置为单节点 4 核的处理器,其内部有4个64 位的四发射超标量GS464高性能处理器核;片内集成4 MB的分体共享二级 Cache(由4 个体模块组成,每个体模块容量为1MB) ;通过目录协议维护多核及I/O DMA访问的Cache 一致性;片内集成2个64 位400MHz的DDR2/3控制器;片内集成2个16 位800MHz的HyperTransport 控制器;每个16位的HT端口拆分成两个 8 路的HT 端口使用;片内集成32位100MHz PCIX/66MHz PCI; 片内集成1个LPC、2个UART、1个 SPI、16路GPIO接口;通过以上信息,我们可以画出其内部结构框图如下:

image

3A芯片包含两级互连实现。第一级互连采用6*6开关,用于连接4个CPU核(作为主设备)、四个二级Cache(作为从设备)、两个IO端口(分别作一个主设备,一个从设备)。从图中可以看到第6、7Master/Slave连接HT控制器, 通过一个DMA 控制器和一级互联开关相连,DMA 控制器负责IO的DMA控制并负责片间一致性的维护,第4、5Master/Slave用于以后扩展(如连接更多设备或CPU核)。

第二级互连采用 5x4的交叉开关(上图连接PCI-DMA设备时可做主设备),连接4个二级 Cache模块(作为主设备),两个 DDR2内存控制器、低速高速 I/O(包括PCI、LPC、SPI等)以及芯片内部的控制寄存器模块。

上述两级互连开关都采用读写分离的数据通道,数据通道宽度为 128bit,工作在与处理器核相同的频率,用以提供高速的片上数据传输。

从上图可以看出CPU访问内存时的地址路由如下(以32位为例):

image

虚拟地址从CPU中发出,有三条路可以走:

第一条是r1,需经过 TLB,因此是映射地址,所以可能是kuseg或kseg2地址;

第二条是r2,不需经过TLB,但会经过Cache,所以是kseg0;

第三条是r3,不需经过TLB和Cache,所以是kseg1。

 

 

 

 

3A系统节点级物理地址分布

龙芯 3 号系列处理器整个系统的物理地址宽度为 48 位。按照地址的高4 位,整个地址空间被均匀分布到16个结点上,即每个结点分配 44位地址空间。 由于3A采用单节点4核配置,因此龙芯3A芯片集成的DDR内存控制器、HT总线、PCI总线的对应地址都包含在从 0x0(含)至 0x1000_0000_0000(不含)的 44 位地址空间内(如下图红框所示):

节点级物理地址空间分布

clip_image002[4]

在3A节点的内部,44 位地址空间又进一步均匀分布给结点内连接的可能最多8个设备。其中低43位地址由4个2级Cache模块所拥有,高43位地址则进一步按地址的[43:42]位分布给连接在4个方向端口的设备上。根据芯片和系统结构配置的不同,如果某端口上没有连接从设备,则对应的地址空间是保留地址空间(下图红框内地址空间),不允许访问。

节点内的地址分布

clip_image004[4]

例如节点0的东端口设备的基地址为0x0800_0000_0000,节点1的东端口设备的基地址为0x1800_0000_0000,依次类推。

不同于方向端口的映射关系,龙芯 3A 可以根据实际应用的访问行为,来决定二级Cache 的交叉寻址方式。节点内的 4 个 2 级 Cache 模块一共对应 43 位地址空间,而每个 2级模块所对应的地址空间根据地址位的某两位选择位确定,并可以通过软件进行动态配置修改。系统中设置了名为 SCID_SEL 的配置寄存器来确定地址选择位,如下表所示。在缺省情况下采用[6:5]地位散列的方式进行分布,即地址[6:5]两位决定对应的2级Cache编号。该寄存器地址0x3FF00400。

二级Cache地址路由选择

clip_image006

 

虚拟地址路由分布与配置

龙芯 3A 的路由主要通过系统的两级交叉开关实现。一级交叉开关地址路由一级交叉开关可以对每个 Master端口接收到的请求进行路由配置,每个Master端口都拥有 8个地址窗口,可以完成 8 个地址窗口的目标路由选择。每个地址窗口由 BASE、MASK和 MMAP三个 64 位寄存器组成,BASE以K字节对齐;MASK采用类似网络掩码高位为1的格式;MMAP的低三位表示对应目标Slave端口的编号,MMAP[4]表示允许取指,MMAP [5]表示允许块读,MMAP [7]表示窗口使能。

窗口命中公式: (IN_ADDR & MASK) == BASE

由于龙芯3号缺省采用固定路由,在上电启动时,配置窗口都处于关闭状态,使用时

需要系统软件对其进行使能配置。一级交叉开关地址窗口寄存器表参见龙芯3A用户手册表2-5。

下面分析地址路由过程,假设地址从CORE0的Master端口进入,那么有8个地址窗口进行选择,这时候会和8个地址窗口的CORE0_MASK0 ~ CORE0_MASK7进行与运算,若与运算结果等于CORE0_BASEi 且 CORE_MMAPi 的第7位使能窗口,则说明选择第i个窗口进行路由,然后再由MMAP的低三位选择Slave端口。


二级交叉开关地址路由

二级 XBAR中有CPU地址空间(包括 HT空间)、DDR2地址空间、以及 PCI地址空间共三个IP相关的地址空间。地址窗口是供CPU和PCI-DMA两个具有Master功能的IP 进行路由选择和地址转换而设置的。CPU 和 PCI-DMA 两者都拥有 8 个地址窗口(一级XBAR中每个CORE做主设备拥有8个地址窗口,而二级XBAR中连接四个二级Cache的四个主设备共用8个地址窗口),可以完成目标地址空间的选择以及从源地址空间到目标地址空间的转换。每个地址窗口由 BASE、MASK和 MMAP三个 64位寄存器组成,BASE 以 K字节对齐,MASK采用类似网络掩码高位为 1的格式,MMAP的低三位是路由选择。MMAP[4]表示允许取指,MMAP[5]表示允许块读,MMAP[7]表示窗口使能,MMAP低三位用于。

在二级XBAR处,标号与所述模块的对应关系如下表示对应新地址空间的编号(其中两个DDR2的标号为0与 1,PCI/Local IO编号为 2,配置寄存器模块连接在端口 3 上):

二级XBAR 处,标号与所述模块的对应关系

clip_image002[6]

二级 XBAR 的地址配置与一级 XBAR 的地址配置相比增加了地址转换的功能。相比之下,一级XBAR 的窗口配置不能对 Cache一致性的请求进行地址转换,否则在二级 Cache 处的地址会与处理器一级 Cache处的地址不一致,导致 Cache一致性的维护错误。

窗口命中公式: (IN_ADDR & MASK) == BASE

新地址换算公式: OUT_ADDR = (IN_ADDR & ~MASK) | {MMAP[63:10],10’h0}

地址窗口转换寄存器表参见龙芯3A用户手册表2-8。这里简单列出几项观察地址变化情况:

clip_image004[6]

clip_image006[4]

clip_image008

clip_image010

clip_image012

clip_image014

对于CPU窗口2~7和PCI窗口1~7的MMAP第7位缺省值为0,所以没用软件配置前,不用关注这些窗口。如下这段来自3A用户手册:

根据缺省的寄存器配置,芯片启动后,CPU的 0x00000000 - 0x0fffffff 的地址区间(256M)映射到 DDR2 的 0x00000000 - 0x0fffffff 的地址区间,CPU 的 0x10000000 - 0x1fffffff区间(256M)映射到PCI的0x10000000 - 0x1fffffff区间,PCIDMA的0x80000000 - 0x8fffffff的地址区间(256M)映射到DDR2的0x00000000 - 0x0fffffff的地址区间。软件可以通过修改相应的配置寄存器实现新的地址空间路由和转换。

­­“CPU的 0x00000000 - 0x0fffffff 的地址区间(256M)映射到 DDR2 的 0x00000000 - 0x0fffffff 的地址区间”: CPU的 0x00000000 - 0x0fffffff 的地址区间分别于CPU_WIN0_MASK和CPU_WIN1_MASK相与,结果是0x00000000,即CPU_WIN0_BASE,命中WIN0窗口。再看CPU_WIN0_MASK,其最低3位结果是0,选中标号0的slave,即0号DDR2/3控制器。再由地址转换公式得出其OUT_ADDR值范围在0x00000000 - 0x0fffffff。上段中其他地址映射的运算过程与本次计算过程相似。


内存的INTERLEAVE实现原理

INTERLEAVE:指数据在多个内存控制器之间交错存储固定大小的地址空间。举个栗子:龙芯3A有两个内存控制器,那么假设经过窗口配置后将0~8K存储在MC0中,8K~16K存储在MC1,16K~24K存储在MC0,24K~32K存储在MC1中。因此可以看出8K的偶数倍数据放在MC0中,8K的奇数倍数据存储在MC1中。空间大小可自己配置,如下是我的板子上的2级XBAR配置:

上图是二级XBAR CPU的8个地址窗口三组寄存器情况。0x900000003ff00000 ~ 0x900000003ff00038是CPU_WIN0_BASE ~ CPU_WIN7_BASE, 0x900000003ff00040 ~ 0x900000003ff00078 是CPU_WIN0_MASK ~ CPU_WIN7_MASK,0x900000003ff00080 ~ 0x900000003ff00b8是  CPU_WIN0_MMAP ~ CPU_WIN7_MMAP。可以看出8个MMAP的第7位都是1,也即窗口使能。看0x900000003ff00050 ~ 0x900000003ff00078的值,MASK一般都是高位全1,低位全0,这里比较奇怪的是如0x900000003ff00050值ffffffff f0010000。并不是高位全1,低位全0。这样的值会导致什么情况呢?下面分析。

以CPU_WIN2举例分析,前面说过地址命中公式:(IN_ADDR & MASK) == BASE,那么IN_ADDR & 0xffffffff f0010000 == 0x00000000 00000000。那么IN_ADDR 地址格式如下:

0x00000000 0**(***0)****

其中*号表示可0可1。括号()中的4个数每个数表示一个bit,四个表示占用16进制数表示中的一位。可以看出现在命中在CPU_WIN2中的地址范围是(高32bit全为0,忽略高32bit):

0000 0000 0000 0000 0000 0000 0000 0000

~

0000 1111 1111 1110 1111 1111 1111 1111

当红0左边为全0,右边任意的0~64K地址命中到窗口2中。按照地址转换公式,其转换后的OUT_ADDR: 0000 0000 0**(***0) ****再看MMAP低3位,选择了MC0,即映射到MC0中。同样,128K~192K也映射到MC0中。按照上述运算过程,64K~128K的地址命中窗口3,MMAP第三位选择了MC1,映射到MC1中,同样,192K~256K也映射到MC1中。最终,地址空间低256M中64K的偶数倍地址映射到了MC0的偶数倍64K中,有128M,按照上述的计算过程,CPU_WIN3将低256M的奇数倍64K映射到MC1上的偶数倍64K中,有128M。128M的计算过程是:  211 * 216 = 227 = 128M 。11是红0左边的可0可1位数,16是红0右边的可0可1的位数。

对于CPU_WIN4: 按照地址命中公式和地址转换公式,其IN_ADDR = 0000 0000 (1***)**(***0) ****, OUT_ADDR = 0000 0000 (0***)**(***0) ****。所以从虚地址0000 0000 8000 0000 ~ 0000 0000 fff(1110) ffff的2G空间中的64K的偶数倍(大小为1G)映射到了MC0的的偶数倍64K上,同理对于CPU_WIN5, 这段虚拟地址空间上64K的奇数倍映射到了MC1的偶数倍64K上。

对于CPU_WIN6和CPU_WIN7,可以看出他们的MMAP的第16位为1,这会造成什么影响呢?先看CPU_WIN6,求得IN_ADDR = 0000 0001 (0***)**(***0) ****, OUT_ADDR = 0000 0000 (0***)**(***1) ****,红色的1是由第16位MMAP的1在地址转换公式中引起的。这样从0000 0001 0000 0000 ~ 0000 0001 7ffe ffff 的大约2G的虚拟地址中64K的偶数倍(大小为1G)映射到了MC0的奇数倍64K上。对于CPU_WIN7,其IN_ADDR = 0000 0001 (0***)**(***1) ****, OUT_ADDR = 0000 0000 (0***)**(***1) ****,从0000 0001 0001 0000 ~ 0000 0001 7fff ffff 的大约2G的虚拟地址中64K的奇数倍(大小为1G)映射到了MC1的奇数倍64K上。

因此,CPU_WIN4~CPU_WIN7就把4G空间内存按照INTERLEAVE分散到MC0和MC1中去了。由此可以看出上述的内存INTERLEAVE实现细节。实现这个功能对系统的平均访问延迟和平均访问带宽都会带来好处。