123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- /// 线程上下文。
- #[repr(C)]
- pub struct Thread {
- sctx: usize,
- x: [usize; 31],
- sepc: usize,
- }
- #[allow(unused)]
- impl Thread {
- /// 创建空白上下文。
- #[inline]
- pub const fn new(sepc: usize) -> Self {
- Self {
- sctx: 0,
- x: [0; 31],
- sepc,
- }
- }
- /// 读取通用寄存器。
- #[inline]
- pub fn x(&self, n: usize) -> usize {
- self.x[n - 1]
- }
- /// 修改通用寄存器。
- #[inline]
- pub fn x_mut(&mut self, n: usize) -> &mut usize {
- &mut self.x[n - 1]
- }
- /// 读取参数寄存器。
- #[inline]
- pub fn a(&self, n: usize) -> usize {
- self.x(n + 10)
- }
- /// 修改参数寄存器。
- #[inline]
- pub fn a_mut(&mut self, n: usize) -> &mut usize {
- self.x_mut(n + 10)
- }
- /// 读取栈指针。
- #[inline]
- pub fn sp(&self) -> usize {
- self.x(2)
- }
- /// 修改栈指针。
- #[inline]
- pub fn sp_mut(&mut self) -> &mut usize {
- self.x_mut(2)
- }
- /// 将 pc 移至下一条指令。
- ///
- /// # Notice
- ///
- /// 假设这一条指令不是压缩版本。
- #[inline]
- pub fn move_next(&mut self) {
- self.sepc = self.sepc.wrapping_add(4);
- }
- /// 执行此线程,并返回 `sstatus`。
- ///
- /// # Safety
- ///
- /// 将修改 `sscratch`、`sepc`、`sstatus` 和 `stvec`。
- #[inline]
- pub unsafe fn execute(&mut self) -> usize {
- unsafe {
- // 设置线程仍在 S 态并打开中断
- let mut sstatus: usize;
- core::arch::asm!("csrr {}, sstatus", out(reg) sstatus);
- const PREVILEGE_BIT: usize = 1 << 8;
- const INTERRUPT_BIT: usize = 1 << 5;
- sstatus |= PREVILEGE_BIT | INTERRUPT_BIT;
- // 执行线程
- // TODO support RV32 instruction set
- core::arch::asm!(
- " csrw sscratch, {sscratch}
- csrw sepc , {sepc}
- csrw sstatus , {sstatus}
- addi sp, sp, -8
- sd ra, (sp)
- call {execute_naked}
- ld ra, (sp)
- addi sp, sp, 8
- csrr {sepc} , sepc
- csrr {sstatus}, sstatus
- ",
- sscratch = in(reg) self,
- sepc = inlateout(reg) self.sepc,
- sstatus = inlateout(reg) sstatus,
- execute_naked = sym execute_naked,
- );
- sstatus
- }
- }
- }
- /// 线程切换核心部分。
- ///
- /// 通用寄存器压栈,然后从预存在 `sscratch` 里的上下文指针恢复线程通用寄存器。
- ///
- /// # Safety
- ///
- /// 裸函数。
- #[naked]
- unsafe extern "C" fn execute_naked() {
- unsafe {
- core::arch::naked_asm!(
- r" .altmacro
- .macro SAVE n
- sd x\n, \n*8(sp)
- .endm
- .macro SAVE_ALL
- sd x1, 1*8(sp)
- .set n, 3
- .rept 29
- SAVE %n
- .set n, n+1
- .endr
- .endm
- .macro LOAD n
- ld x\n, \n*8(sp)
- .endm
- .macro LOAD_ALL
- ld x1, 1*8(sp)
- .set n, 3
- .rept 29
- LOAD %n
- .set n, n+1
- .endr
- .endm
- ",
- // 位置无关加载
- " .option push
- .option nopic
- ",
- // 保存调度上下文
- " addi sp, sp, -32*8
- SAVE_ALL
- ",
- // 设置陷入入口
- " la t0, 2f
- csrw stvec, t0
- ",
- // 保存调度上下文地址并切换上下文
- " csrr t0, sscratch
- sd sp, (t0)
- mv sp, t0
- ",
- // 恢复线程上下文
- " LOAD_ALL
- ld sp, 2*8(sp)
- ",
- // 执行线程
- " sret",
- // 陷入
- " .align 2",
- // 切换上下文
- "2: csrrw sp, sscratch, sp",
- // 保存线程上下文
- " SAVE_ALL
- csrrw t0, sscratch, sp
- sd t0, 2*8(sp)
- ",
- // 切换上下文
- " ld sp, (sp)",
- // 恢复调度上下文
- " LOAD_ALL
- addi sp, sp, 32*8
- ",
- // 返回调度
- " ret",
- " .option pop",
- )
- }
- }
|