diff --git a/ostd/src/arch/loongarch/task/mod.rs b/ostd/src/arch/loongarch/task/mod.rs new file mode 100644 index 000000000..a7a21e32c --- /dev/null +++ b/ostd/src/arch/loongarch/task/mod.rs @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MPL-2.0 + +//! The architecture support of context switch. + +use crate::task::TaskContextApi; + +core::arch::global_asm!(include_str!("switch.S")); + +#[derive(Debug, Default, Clone, Copy)] +#[repr(C)] +pub(crate) struct TaskContext { + pub regs: CalleeRegs, + pub ra: usize, + /// Thread-local storage pointer. + pub tp: usize, +} + +/// Callee-saved registers. +#[derive(Debug, Default, Clone, Copy)] +#[repr(C)] +pub struct CalleeRegs { + /// sp + pub sp: usize, + /// fp + pub fp: usize, + /// s0 + pub s0: usize, + /// s1 + pub s1: usize, + /// s2 + pub s2: usize, + /// s3 + pub s3: usize, + /// s4 + pub s4: usize, + /// s5 + pub s5: usize, + /// s6 + pub s6: usize, + /// s7 + pub s7: usize, + /// s8 + pub s8: usize, +} + +impl CalleeRegs { + /// Creates new `CalleeRegs` + pub const fn new() -> Self { + CalleeRegs { + sp: 0, + fp: 0, + s0: 0, + s1: 0, + s2: 0, + s3: 0, + s4: 0, + s5: 0, + s6: 0, + s7: 0, + s8: 0, + } + } +} + +impl TaskContext { + pub const fn new() -> Self { + TaskContext { + regs: CalleeRegs::new(), + ra: 0, + tp: 0, + } + } + + /// Sets thread-local storage pointer. + pub fn set_tls_pointer(&mut self, tls: usize) { + self.tp = tls; + } + + /// Gets thread-local storage pointer. + pub fn tls_pointer(&self) -> usize { + self.tp + } +} + +impl TaskContextApi for TaskContext { + fn set_instruction_pointer(&mut self, ip: usize) { + self.ra = ip; + } + + fn instruction_pointer(&self) -> usize { + self.ra + } + + fn set_stack_pointer(&mut self, sp: usize) { + self.regs.sp = sp; + } + + fn stack_pointer(&self) -> usize { + self.regs.sp + } +} + +unsafe extern "C" { + pub(crate) unsafe fn context_switch(cur: *mut TaskContext, nxt: *const TaskContext); +} diff --git a/ostd/src/arch/loongarch/task/switch.S b/ostd/src/arch/loongarch/task/switch.S new file mode 100644 index 000000000..c120b89cd --- /dev/null +++ b/ostd/src/arch/loongarch/task/switch.S @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: MPL-2.0 */ + +.text +.global context_switch +context_switch: # (cur: *mut TaskContext, nxt: *TaskContext) + # Save cur's register + st.d $sp, $a0, 0x0 + st.d $fp, $a0, 0x8 + st.d $s0, $a0, 0x10 + st.d $s1, $a0, 0x18 + st.d $s2, $a0, 0x20 + st.d $s3, $a0, 0x28 + st.d $s4, $a0, 0x30 + st.d $s5, $a0, 0x38 + st.d $s6, $a0, 0x40 + st.d $s7, $a0, 0x48 + st.d $s8, $a0, 0x50 + st.d $ra, $a0, 0x58 # return address + st.d $tp, $a0, 0x60 # thread-local storage pointer + + # Restore nxt's registers + ld.d $sp, $a1, 0x0 + ld.d $fp, $a1, 0x8 + ld.d $s0, $a1, 0x10 + ld.d $s1, $a1, 0x18 + ld.d $s2, $a1, 0x20 + ld.d $s3, $a1, 0x28 + ld.d $s4, $a1, 0x30 + ld.d $s5, $a1, 0x38 + ld.d $s6, $a1, 0x40 + ld.d $s7, $a1, 0x48 + ld.d $s8, $a1, 0x50 + ld.d $ra, $a1, 0x58 # return address + ld.d $tp, $a1, 0x60 # thread-local storage pointer + ret