从CPU RTL到GCC expmed Cost Model

背景 最近和朋友讨论一个编码算法的问题的时候意外发现,当前 RISC-V 的 GCC 即使使用-O3优化的情况下,也不会将 divide by const 优化为Barrett reduction。但我测试了默认参数的 x86 、 aarch64 、 mips32 ,均存在该优化。且通常来说, CPU…

调试sfence.vma,12天之差错过Linux Patch一个

起因 最近造了个RISC-V CPU模拟器——CEMU,并实现了软件模拟TLB来加速地址翻译。而TLB和页表并不自带一致性,在RISC-V上需使用sfence.vma这样的指令来刷掉TLB和Page Table Cache(如果存在)和硬件流水线上的指令来确保页表修改生效。并通过了RISC-V Test中的所有测试,然而在启动Linux进入Busybox却遇到如下问题: 尽管Busybox能跑起来并正常使用,但同样的内核在qemu和Rocket上都是完全正常的,因此我继续探索了一下可能的问题。后来objdump了一下busybox的这个地址,发现是一条ret(jalr)指令,而跳转的地址是从栈上ld的。 因此我就怀疑是页表出现了问题导致fork的时候这个进程的栈对别的进程的栈产生了破坏。 第一次尝试 我首先怀疑了TLB查找出现问题,因此我修改了sfence.vma指令的实现,将sfence.vma实现为不管asid和va,全刷TLB,结果用户进程正常载入了。 后续继续做了些尝试,发现只要在执行sfence.vma的时候忽略ASID,但保留va的判断,用户进程依然正常运行。 第二次尝试 这次在实验室里twd2和dram一起来看我调试了。我在每次TLB Hit的情况下都重新进行一遍Page Table Walk,并检查Walk出来的PTE结果和TLB的区别。 结果发现Linux Kernel在一个Hart启动的时候会出现一次页表的W位不同的问题,但那是一条sfence.vma指令的fetch,所以没有对运行结果产生影响。…

U-Boot RISC-V M Mode的灵车SMP启动

为了方便运行任意M Mode软件,同时不想自制Bootloader。我决定在我的RISC-V SoC上使用M Mode U-Boot。然后再上面跑OpenSBI再把Linux作为OpenSBI的Payload运行。但U-Boot的go命令只会修改当前Hart的PC,并不会让其他Hart进行跳转。这就导致后续OpenSBI启动Linux一发送IPI就不断进入Trap Handler。 最后我想了个简单解决方法是,一旦进入Trap Handler且发现是当前无法解决的Trap就跳转到DRAM_BASE(也就是OpenSBI的TEXT段开始地址),并将a0寄存器设置上hartid(符合OpenSBI要求)。这样当IPI产生时其他核就会进入OpenSBI。配合Rocket Chip开双核,经过多次测试,Linux SMP均正常工作。不过比较灵车,理论上正确做法应该修改U-Boot代码控制其他核的IPI跳转。 修改在此:https://github.com/cyyself/u-boot/commit/c637a978068c434691899f1139b8b3e6c45efc93 在这种方法下,只需要保证设备树科学,然后使用u-boot通过tftp/串口将OpenSBI编译的fw_payload.bin载入到DRAM_BASE,然后使用go 0x80000000即可完成SMP启动。不过这种灵车做法需要确保的是,启动过程发送IPI之前不会对U-Boot使用的内存地址进行任何破坏。

修改binutils在RISC-V上添加汇编指令

1. 起源 最近给学长打工做的相关研究需要对RISC-V指令集进行扩展,因此需要魔改编译器添加指令。 而RISC-V架构上做到这一点其实非常容易,官方提供了一个riscv-opcodes工具,它可以用于生成编译器所需的opcode宏来添加所需的指令。 2. 准备环境 我的实验基于Debian Bullseye发行版进行。(写这篇文章之时Bullseye还处于Testing状态) 首先我们需要编译安装riscv-gnu-toolchain. sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev…

Back to Top