本项目基于ucore-thumips,将其移植到了LoongArch 32上。并成功跑通了所有的用户进程。
我们同样移植了去除答案的实验教学版本与实验指导书,实验版本位于本项目的no_answer分支,实验指导书在此。
我们已经过测试,本移植版本可以在chiplab的loongarch32软核上运行。
我们已经将实验环境打包为Docker镜像,并发布到Docker Hub,可以使用docker pull chenyy/la32r-env
进行安装,并在该容器内完成编译即可。
make
make qemu
在一个终端执行以下内容,它将以debug模式启动qemu,并监听在1234端口:
make debug
在另一个终端启动gdb:
make gdb
这一点对于操作系统而言影响并不是很大,但是对于处理器核设计是非常重要的一点。
在LoongArch32中,CSR寄存器的作用相当于MIPS的CP0寄存器。
这里需要注意,csrwr rd, csr_num
指令是将rd寄存器与csr_num进行对调,而非MIPS时代的mtc0
只是单纯将值写入CP0寄存器。
在MIPS中,我们通过CP0的Status
寄存器的EXL
位来表示正在处理异常,因此当EXL为1时强制为内核态。
而LoongArch32的CSR中,取消了Status
类似的寄存器,而分为了PRMD
与CRMD
。表示例外前状态和当前状态,而使用ertn
指令(类似MIPS的eret
)则会自动将PRMD
还原到CRMD
。这一点上比MIPS更加科学。
在MIPS架构中,我们熟悉的固定地址空间kseg0
和kseg1
等被舍弃。在LoongArch32中,被改为了通过CSR中的DMW寄存器配置地址映射窗口。这一部分代码位于kern/init/entry.S
。考虑到以后可能需要在chiplab上使用PMON进行载入,因此我们按照了PMON相同的方式映射了一段内核的内存地址,也就是0xa0000000-0xbfffffff
直接映射到0x00000000-0x1fffffff
。而对于IO设备,以及载入用户进程需要进行的Uncached操作,配置了0x80000000-0x9fffffff
直接映射到0x00000000-0x1fffffff
。
对MIPS了解的同学不难看出,我们采用的配置方式非常类似于MIPS的KSEG0与KSEG1,但是对地址进行了对调。
LoongArch32中有一个比较特殊的地方,v0
与a0
,v1
与a1
寄存器尽管别名不同,但使用了相同的地址。这就导致uCore的MIPS版本原有的一些设计与它存在冲突,例如系统调用我们需要通过a
寄存器传递参数,然后通过v0
寄存器拿回系统的返回值。而对于一个特殊的系统调用SYS_exec
需要通过a
寄存器传递参数,如果我们把它的返回值直接写入v0
会造成参数被覆盖。而由于LoongArch32中设计了8个a
寄存器,因此这里直接将a7
作为系统调用返回值的存储寄存器。
尽管LoongArch32的syscall
指令含有15位立即数,但是在文档中并没有找到例外处理时如何读取这个系统调用号,因此这里将这一部分立即数全部设置为0。并使用a7
寄存器传递系统调用号。
如果硬件未保证I-D Cache一致性,需要正确实现CACOP指令,并修改kern/include/loongarch.h
中的缓存行大小宏定义。