一、背景
按照MIPS的规范,在32位系统中程序地址(虚拟地址)空间分成4个部分:
其中,kseg0与kseg1指向的地址空间指向的是同一块512MB物理地址,即0x00000000~0x20000000的物理地址,这一块地址在龙芯1b的地址划分中,是作为ddr的地址与I/O设备地址
这两段地址不需要经过MMU即可访问,其中kseg0需要经过cache,所以在cache初始化之前不能访问。也就是说不经过MMU的情况下,只能访问到最多512MB的内存空间。
如果需要使用超过512MB空间则需要使用MMU进行程序地址(虚拟地址)与物理地址的转换,否则未作映射的内存不能使用,这个时候就需要将TLB初始化。
二、TLB初始化配置方法
假设:首先确定需要做映射的内存空间大小以及起始位置,假设需要将kuseg的2G内存空间都用上,那么虚拟地址的大小就是2G,起始地址为0x00000000;需要映射到的物理地址大小也为2G,起始地址为0x30000000。
从手册可以知道,gs232共有32个TLB表项,所以按照页式的虚拟内存管理机制,2G的内存需要每页的大小为:2048MB/32=64MB。
几个寄存器
1、Index寄存器:写TLB索引项
配置方式:由于31~6位默认为0,所以写这个寄存器的时候直接写低位值即可,如第4项,则赋值为4(0x00000004)即可;
2、Pagemask寄存:配置内存页的大小
配置方式:根据寄存器的定义,只在28~13位进行有效赋值,所以这里给mask寄存器的赋值只有9中:
页尺寸 | 赋值 |
---|---|
4Kbytes | 0 |
16Kbytes | 6000 |
64Kbytes | 1E000 |
256Kbytes | 7E000 |
1MBytes | 1FE000 |
4MBytes | 7FE000 |
16MBytes | 1FFE000 |
64MBytes | 7FFE000 |
256MBytes | 1FFFE000 |
3、EntryHi寄存器:入口地址,即虚拟地址(页帧号),一个入口项对应的是连续的两个虚拟地址页帧号(内存页首地址的高18位)
配置方法:有效的地址位是31~13位,一般12 ~ 0位设置成0,所以写寄存器赋值范围:0x00000000 ~ 0xffffe000。
4、EntryLo0、EntryLo1寄存器:出口地址,即物理地址页帧号,分别对应入口地址的两个虚拟地址页帧号(配置的时候一个EntryHi对应两个EntryLo)
配置方法:第25~6位是有效地址位,将需要指向的物理地址首地址右移6位,使地址位对齐寄存器的25 ~ 6位,之后将其余位先置零(与上一个0x3fffffc0,这里之所以将29 ~ 26 也保留,是因为这几位一般作为页帧号的一部分,但是实际上直接写0,所以开始就右移6位补零)。随后根据定义对其余为赋值。按照ls1b中的例子,将0、1、2、5四位置1,其余保持0即可。
配置实例:
根据假设的条件,参照pmon源码中的TLB配置程序,重写TLB的配置程序
li a1,0x80000000 //设置需要映射的地址空间大小
li a0,0x00000000 //设置虚拟地址的起始地址,即首页的起始地址
li a4,0x30000000 //设置映射到的物理地址的首地址
li a3,0 //设置TLB index,起始为0
li a2,0x07FFE000 //设置内存页大小,因为这里设置的64MB,查看寄存器的说明可知需要赋值7FFE000
MTC0 a2,COP_0_TLB_PG_MASK //将值写入寄存器
1://循环点
and a2,a0,0x0xfffff000 //将a0的虚拟页首地址取高20位放到a2中
MTC0 a2,COP_0_TLB_HI //写入EntryHi寄存器。这里相当于同时配置了两个虚拟页的首地址(原因查看EntryHi寄存器的说明)
//将上面两个虚拟地址页需要对应的物理页地址
move a2,a4 //第一个物理地址,先放入a2寄存器
srl a2,a2,6 //将地址右移6位,准备写入EntryLo0寄存器
and a2,a2,0x3fffffc0 //取29~6位
ori a2,0x00000017 //将0、1、2、5位置1
MTC0 a,COP_0_TLB_LO0 //写入EntryLo0寄存器
addu a2,(0x01000000 >> 6) //配置第二个物理页帧号,所以需要加上一个页的大小,这里大小为64MB,所以是0x01000000,同时要与寄存器的地址位对齐,所以右移6位
MTC0 a2,COP_0_TLB_LO1 //写入EntryLo1寄存器
MTC0 a3,COP_0_TLB_INDEX //将开始设置的TLB索引号写入Index寄存器
addiu a3,1
li a2,0x08000000 //设置步长,由于一次配置了两个内存页,所以步长为128MB,即0x08000000
subu a1,a2 //将需要配置的内存空间减少128MB
nop
tlbwi //配置好的寄存器写入TLB
bgtz a1,1b //判断内存是否已经配置完毕,即看a1是否为0,否则跳转到1处继续配置
addu a0,a2 //如果配置完毕,将多减去的128MB加回
jr ra //跳转回主程序
nop
配置完毕
参考:
see mips run
龙芯 1B 处理器用户手册
LS232用户手册
http://xenyinzen.wikidot.com/code-research:pmon:start-functions
https://wenku.baidu.com/view/013ba5f9700abb68a982fb3a.html?sxts=1535682681686&pn=1
https://bbs.csdn.net/topics/390776135