gs232/ls1b——pmon配置TLB学习实例

时间:2024-03-29 10:23:16

一、背景

按照MIPS的规范,在32位系统中程序地址(虚拟地址)空间分成4个部分:
gs232/ls1b——pmon配置TLB学习实例
其中,kseg0与kseg1指向的地址空间指向的是同一块512MB物理地址,即0x00000000~0x20000000的物理地址,这一块地址在龙芯1b的地址划分中,是作为ddr的地址与I/O设备地址
gs232/ls1b——pmon配置TLB学习实例
这两段地址不需要经过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索引项

gs232/ls1b——pmon配置TLB学习实例
配置方式:由于31~6位默认为0,所以写这个寄存器的时候直接写低位值即可,如第4项,则赋值为4(0x00000004)即可;

2、Pagemask寄存:配置内存页的大小

gs232/ls1b——pmon配置TLB学习实例
配置方式:根据寄存器的定义,只在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位)

gs232/ls1b——pmon配置TLB学习实例
配置方法:有效的地址位是31~13位,一般12 ~ 0位设置成0,所以写寄存器赋值范围:0x00000000 ~ 0xffffe000。

4、EntryLo0、EntryLo1寄存器:出口地址,即物理地址页帧号,分别对应入口地址的两个虚拟地址页帧号(配置的时候一个EntryHi对应两个EntryLo)

gs232/ls1b——pmon配置TLB学习实例
配置方法:第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