在实现多核操作系统的时候, 有一个问题很重要, 就是如何存储并读取和处理器核(RISC-V的核也叫做hart)相关的数据结构(hart-local data structure / context)。
一种直接的实现方法是, 对该类数据结构, 开设一个数组, 用核编号作为下标。在访问的时候只需要通过某种办法, 获得核编号, 然后就可以直接访问了。例如, 在RISC-V中, 可以设法读取mhartid来获得核编号。不幸的是, mhartid是一个M态的寄存器, 在S态的操作系统无法直接读取, 若想要读取, 需要通过类似于系统调用的方式。由于核编号在操作系统中使用非常频繁, 所以通过系统调用来读取mhartid会有很大的性能损失。
注意到sscratch是一个S态可以随意读写的不会产生副作用的CSR(寄存器), 并且不会被用户修改。事实上, RISC-V的特权指令集规范[A. Waterman. et al. 2017]已经大致说明了如何使用sscratch解决这个问题:
Typically, sscratch is used to hold a pointer to the hart-local supervisor context while the hart is executing user code. At the beginning of a trap handler, sscratch is swapped with a user register to provide an initial working register.
通常, 在运行用户态代码时, sscratch用来存储一个hart相关的S态上下文的指针。在中断处理程序的开始, sscratch会和一个通用寄存器交换来提供首个可用的通用寄存器。
我的实现与Linux类似。
参考文献:
A. Waterman, K. Asanovic, SiFive Inc. 2017. The RISC-V Instruction Set Manual Volume II: Privileged Architecture Privileged Architecture Version 1.10 https://riscv.org/specifications/
强强!已阅。
强强!已阅。
原文提到“mhartid是一个M态的寄存器, 在S态的操作系统无法直接读取, 若想要读取, 需要通过类似于系统调用的方式。”这一表述或许与SBI Spec有误。
经观察SBI Spec,并未提供有关获取hartid的调用。且Spec中HSM Hart Start Register State指出会将hartid放在a0寄存器中,因此S-Mode软件只在启动时拿到自己的hartid并自己通过某些方式维护。
谢谢指出!!