You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3.5 KiB

RISCV 移植记录

开发环境

具体配置过程详见Dockerfile

Rust-RISCV

目标指令集RISCV32IMA

target: riscv32ima_unknown_none

由于工具链二进制版本尚未内置此target因此需提供配置文件riscv32-blog_os.json

理想情况下目标指令集应为RISCV32G即使用全部扩展。但考虑到要把它跑在我们自己实现的CPU上指令集应该尽量精简即最好是RISCV32I。此外

  • 为什么用原子指令扩展?

    RustOS依赖的库中大部分都使用了Rust核心库的原子操作core::sync::atomic

    如果目标指令集不支持原子操作,会导致无法编译。

    然而LLVM后端尚不完全支持原子指令扩展因此这条路可能走不通需要魔改Rust标准库。

  • 为什么用乘除指令扩展?

    Rust核心库中fmt模块会使用乘除运算若不使用乘除指令则会依赖LLVM提供的内置函数进行软计算导致链接错误。这一问题理论上可以通过在xargo中设置依赖compiler-builtin解决。但如此操作后仍有一个函数__mulsi3缺失32×32。经查compiler-builtin中实现了类似的__muldi3函数64×64),所以理论上可以用它手动实现前者。但如此操作后,还是不对,实验表明__muldi3本身也是不正确的。

    总之没有成功配置不使用M扩展的编译环境不过日后解决这一问题并不困难。

BootLoader

参考bbl-ucore及后续的ucore_os_lab for RISCV32,使用bbl作为BootLoader。

然而官方版本和bbl-ucore中的fork版本都无法正常编译使用的是ucore_os_lab中的修改版本

bbl-ucore使用RISCV1.9的bblucore_os_lab使用RISCV1.10的bbl。后者相比前者去掉了对内核的内存映射因此需保证虚实地址一致。

事实上ucore_os_lab中的虚实地址并不一致且没有内存映射但依然能够运行应该是由于编译器生成的所有跳转都使用相对偏移。而Rust编译器会生成绝对地址跳转因此若虚实不一致会导致非法访存。

Trap

参考资料:

Trap

  • 中断帧32个整数寄存器 + 4个S-Mode状态寄存器
  • 开启中断:
    • stvec设置中断处理函数地址
    • sstatusSIE bit 开启中断

Timer

  • 开启时钟中断:

    • sieSTIE bit 开启时钟中断
    • sbi::set_timer设置下次中断时间
  • 读取时间:

    • mtime可读出当前时间低32bit

    • mtimeh当前时间高32bit仅RV32有效

      因此RV32下要读取完整时间u64需循环读取判等因为指令之间可能被中断要保证原子性。详见get_cycle()

  • 触发中断:

    • mtimecmp(h):下次触发时钟中断的时间

      当time>=timecmp时触发中断

      可通过sbi::set_timer设置