nemu linux

Difftest 适配

在跑linux需要加入csr的检查,以测出特权指令执行的结果是否正确

首先需要做的就是维护一套csr寄存器,我个人做法就是设置一个csr_map结构体,然后查询这个结构体来找到csr是否实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
nemu_csr_t csr_map[] = { 
{0x100, "sstatus" ,true},
{0x104, "sie" ,true},
{0x105, "stvec" ,true},
{0x140, "sscratch",true},
{0x141, "sepc" ,true},
{0x142, "scause" ,true},
{0x143, "stval" ,true},
{0x144, "sip" ,true},
{0x180, "satp" ,true},
{0x300, "mstatus" ,true},
{0x301, "misa" ,false},
{0x302, "medeleg" ,true},
{0x303, "mideleg" ,true},
{0x304, "mie" ,true},
{0x305, "mtvec" ,true},
{0x310, "mstatush",true},
// {0x312, "medelegh",true},////2024 standard
{0x340, "mscratch",true},
{0x341, "mepc" ,true},
{0x342, "mcause" ,true},
{0x343, "mtval" ,true},
{0x344, "mip" ,true},
{0xf11, "mvendorid",true},
{0xf14, "mhartid" ,true}
}

然后每次增加一个csr寄存器,只需在difftest.cc和inst.c同时将寄存器加入map即可

之后我们需要实现非法指令异常,可以参考yield在nemu实现,当遇到一些没实现的csr时,就可以触发异常,然后sbi会自己处理这些没实现的csr,我们此时也要去将这个非法指令访问异常同步到spike中,具体可以参考spike的get_csr

完成上述,基本difftest改造完成

移植opensbi

首先下载opensbi

1
git clone https://github.com/riscv-software-src/opensbi

然后复制一份platform/templete,将这个改为适配nemu的平台,具体改动:

先设置objects.mk,然后

1
2
3
4
5
6
7
8
9
10
11
12
PLATFORM_RISCV_XLEN = 32
PLATFORM_RISCV_ABI = ilp32
PLATFORM_RISCV_ISA = rv32ima_zicsr_zifencei
PLATFORM_RISCV_CODE_MODEL = medany
FW_TEXT_START=0x80000000//如果这个不行,可以直接修改链接脚本,具体在firmware/fw_jump.elf.ldS
FW_JUMP=y
ifeq ($(PLATFORM_RISCV_XLEN), 32)
FW_JUMP_ADDR=0x0
else
FW_JUMP_ADDR=0x80200000
endif

然后设置platform.c,主要就是设置timer,uart的地址,这里可以根据自己的想法去设置设备地址,也可以使用nemu内部的地址,建议uart使用nemu的,只需稍微改动即可,改动可参考uart8250手册

之后就是debug过程,最后由于跳转到0x0,所以会直接段错误退出,注意最好看19年的手册,24年新出的手册会增加一些csr,从而导致spike触发非法指令

运行结果如下

1740061516016

如果不确定需要实现哪些寄存器,可以先抛出非法指令异常,之后opensbi会告诉你要设置哪些寄存器

移植linux

为什么执行到relocate_enable_mmu会访问无效地址?

因为指第一次写入satp并没有去执行sfence,所以导致系统仍然使用之前的映射关系

  • 需要去为ref传递异常号
  • 为什么会跳转到c000098,这里可能发生了嵌套异常(错误的行为)

终于可以跑起来一部分页表了:

发现之前的问题是因为自己的pte解析出错了

目前的问题是:

会访问0x80040000的数据,这个就是j指令