From 5530549a54fb1893f3b6d0047276b591cb028f3a Mon Sep 17 00:00:00 2001 From: WangRunji Date: Thu, 12 Jul 2018 18:56:29 +0800 Subject: [PATCH] Recover `process` `thread` `sync` mod for RV32. Pass compile. --- crate/riscv | 2 +- src/arch/riscv32/context.rs | 155 +++++++++++++++++++++++++++ src/arch/riscv32/interrupt.rs | 41 +++---- src/arch/riscv32/paging.rs | 4 + src/arch/riscv32/timer.rs | 2 +- src/arch/x86_64/interrupt/handler.rs | 4 +- src/consts.rs | 5 + src/lib.rs | 13 ++- src/process/process.rs | 4 +- src/sync/mutex.rs | 14 ++- 10 files changed, 212 insertions(+), 32 deletions(-) create mode 100644 src/arch/riscv32/context.rs diff --git a/crate/riscv b/crate/riscv index 08d4a2e..b979c91 160000 --- a/crate/riscv +++ b/crate/riscv @@ -1 +1 @@ -Subproject commit 08d4a2e96399cef5985a85a035e1ac222f8d5bef +Subproject commit b979c91db3bcfd9c9e9edabf45ef04e41dc4f659 diff --git a/src/arch/riscv32/context.rs b/src/arch/riscv32/context.rs new file mode 100644 index 0000000..b108322 --- /dev/null +++ b/src/arch/riscv32/context.rs @@ -0,0 +1,155 @@ +use super::super::riscv::register::*; + +#[derive(Debug, Clone)] +#[repr(C)] +pub struct TrapFrame { + pub x: [usize; 32], + pub sstatus: sstatus::Sstatus, + pub sepc: usize, + pub sbadaddr: usize, + pub scause: scause::Scause, +} + +/// 用于在内核栈中构造新线程的中断帧 +impl TrapFrame { + fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, rsp: usize) -> Self { + use core::mem::zeroed; + let mut tf: Self = unsafe { zeroed() }; + tf.x[10] = arg; // a0 + tf.sepc = entry as usize; + tf + } + fn new_user_thread(entry_addr: usize, rsp: usize) -> Self { + unimplemented!() + } + pub fn is_user(&self) -> bool { + unimplemented!() + } +} + +/// 新线程的内核栈初始内容 +#[derive(Debug)] +#[repr(C)] +pub struct InitStack { + context: ContextData, + tf: TrapFrame, +} + +impl InitStack { + unsafe fn push_at(self, stack_top: usize) -> Context { + let ptr = (stack_top as *mut Self).offset(-1); + *ptr = self; + Context(ptr as usize) + } +} + +extern { + fn trap_ret(); +} + +/// The entry point of new thread +extern fn forkret() { + debug!("forkret"); + // Will return to `trapret` +} + +#[derive(Debug, Default)] +#[repr(C)] +struct ContextData { + ra: usize, + satp: usize, + s: [usize; 12], +} + +impl ContextData { + fn new(satp: usize) -> Self { + ContextData { ra: forkret as usize, satp, ..ContextData::default() } + } +} + +#[derive(Debug)] +pub struct Context(usize); + +impl Context { + /// Switch to another kernel thread. + /// + /// Defined in `trap.asm`. + /// + /// Push all callee-saved registers at the current kernel stack. + /// Store current sp, switch to target. + /// Pop all callee-saved registers, then return to the target. + #[naked] + #[inline(never)] + pub unsafe extern fn switch(&mut self, target: &mut Self) { + asm!( + " + // save from's registers + sub sp, -14*4 + sw sp, (a0) + sw ra, 0*4(sp) + sw s0, 2*4(sp) + sw s1, 3*4(sp) + sw s2, 4*4(sp) + sw s3, 5*4(sp) + sw s4, 6*4(sp) + sw s5, 7*4(sp) + sw s6, 8*4(sp) + sw s7, 9*4(sp) + sw s8, 10*4(sp) + sw s9, 11*4(sp) + sw s10, 12*4(sp) + sw s11, 13*4(sp) + csrrs s11, 0x180, x0 // satp + sw s11, 1*4(sp) + + // restore to's registers + lw sp, (a1) + lw s11, 1*4(sp) + csrrw x0, 0x180, s11 // satp + lw ra, 0*4(sp) + lw s0, 2*4(sp) + lw s1, 3*4(sp) + lw s2, 4*4(sp) + lw s3, 5*4(sp) + lw s4, 6*4(sp) + lw s5, 7*4(sp) + lw s6, 8*4(sp) + lw s7, 9*4(sp) + lw s8, 10*4(sp) + lw s9, 11*4(sp) + lw s10, 12*4(sp) + lw s11, 13*4(sp) + add sp, 14*4 + + sw zero, (a1) + ret" + : : : : "intel" "volatile" ) + } + + pub unsafe fn null() -> Self { + Context(0) + } + + pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, cr3: usize) -> Self { + InitStack { + context: ContextData::new(cr3), + tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top), + }.push_at(kstack_top) + } + pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, is32: bool, cr3: usize) -> Self { + InitStack { + context: ContextData::new(cr3), + tf: TrapFrame::new_user_thread(entry_addr, ustack_top), + }.push_at(kstack_top) + } + pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, cr3: usize) -> Self { + InitStack { + context: ContextData::new(cr3), + tf: { + let mut tf = tf.clone(); + tf.x[1] = 0; // ra + tf + }, + }.push_at(kstack_top) + } +} \ No newline at end of file diff --git a/src/arch/riscv32/interrupt.rs b/src/arch/riscv32/interrupt.rs index 591a591..63e2376 100644 --- a/src/arch/riscv32/interrupt.rs +++ b/src/arch/riscv32/interrupt.rs @@ -1,13 +1,32 @@ use super::riscv::register::*; +pub use self::context::*; + +#[path = "context.rs"] +mod context; pub fn init() { unsafe { // Set the exception vector address stvec::write(__alltraps as usize, stvec::TrapMode::Direct); - // Enable interrupt + } + info!("stvec: init end"); +} + +#[inline(always)] +pub unsafe fn enable() { + sstatus::set_sie(); +} + +#[inline(always)] +pub unsafe fn disable_and_store() -> usize { + sstatus::read().sie() as usize +} + +#[inline(always)] +pub unsafe fn restore(flags: usize) { + if flags != 0 { sstatus::set_sie(); } - println!("interrupt: init end"); } #[no_mangle] @@ -20,26 +39,10 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { } fn timer() { - static mut TICK: usize = 0; - unsafe { - TICK += 1; - if TICK % 100 == 0 { - println!("timer"); - } - } + ::timer_interrupt(); super::timer::set_next(); } -#[derive(Debug, Clone)] -#[repr(C)] -pub struct TrapFrame { - x: [usize; 32], - sstatus: sstatus::Sstatus, - sepc: usize, - sbadaddr: usize, - scause: scause::Scause, -} - extern { fn __alltraps(); } \ No newline at end of file diff --git a/src/arch/riscv32/paging.rs b/src/arch/riscv32/paging.rs index ffea89b..a07fa18 100644 --- a/src/arch/riscv32/paging.rs +++ b/src/arch/riscv32/paging.rs @@ -198,6 +198,10 @@ impl InactivePageTable for InactivePageTable0 { } } + fn token(&self) -> usize { + self.p2_frame.number() | (1 << 31) // as satp + } + fn alloc_frame() -> Option { alloc_frame() } diff --git a/src/arch/riscv32/timer.rs b/src/arch/riscv32/timer.rs index 962ca2c..b668238 100644 --- a/src/arch/riscv32/timer.rs +++ b/src/arch/riscv32/timer.rs @@ -23,7 +23,7 @@ pub fn init() { unsafe { sie::set_stimer(); } set_next(); - println!("timer: init end"); + info!("timer: init end"); } pub fn set_next() { diff --git a/src/arch/x86_64/interrupt/handler.rs b/src/arch/x86_64/interrupt/handler.rs index 9c95f98..0de47ed 100644 --- a/src/arch/x86_64/interrupt/handler.rs +++ b/src/arch/x86_64/interrupt/handler.rs @@ -146,9 +146,7 @@ fn com2() { } fn timer() { - use process::PROCESSOR; - let mut processor = PROCESSOR.try().unwrap().lock(); - processor.tick(); + ::timer_interrupt(); } fn to_user(tf: &mut TrapFrame) { diff --git a/src/consts.rs b/src/consts.rs index 01df210..ba1e7a9 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -21,6 +21,10 @@ mod riscv { pub const KERNEL_HEAP_SIZE: usize = 1 * 1024 * 1024; pub const MEMORY_OFFSET: usize = 0x8000_0000; pub const MEMORY_END: usize = 0x8080_0000; + pub const USER_STACK_OFFSET: usize = 0x70000000; + pub const USER_STACK_SIZE: usize = 1024 * 1024; + // 1 MB + pub const USER32_STACK_OFFSET: usize = USER_STACK_OFFSET; } #[cfg(target_arch = "x86_64")] @@ -80,6 +84,7 @@ mod x86_64 { /// Offset to user stack pub const USER_STACK_OFFSET: usize = USER_GRANT_OFFSET + PML4_SIZE; + pub const USER32_STACK_OFFSET: usize = 0xB000_0000; pub const USER_STACK_PML4: usize = (USER_STACK_OFFSET & PML4_MASK) / PML4_SIZE; /// Size of user stack pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB diff --git a/src/lib.rs b/src/lib.rs index 68affee..348c2a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,15 +71,12 @@ mod memory; mod lang; mod util; mod consts; -#[cfg(target_arch = "x86_64")] mod process; #[cfg(target_arch = "x86_64")] mod syscall; #[cfg(target_arch = "x86_64")] mod fs; -#[cfg(target_arch = "x86_64")] mod thread; -#[cfg(target_arch = "x86_64")] mod sync; #[allow(dead_code)] @@ -91,11 +88,19 @@ mod arch; #[path = "arch/riscv32/mod.rs"] mod arch; +fn timer_interrupt() { + use process::PROCESSOR; + let mut processor = PROCESSOR.try().unwrap().lock(); + processor.tick(); +} + #[no_mangle] #[cfg(target_arch = "riscv")] pub extern fn rust_main() -> ! { arch::init(); - println!("RISCV init end"); + process::init(); + info!("RISCV init end"); + unsafe { arch::interrupt::enable(); } loop {} } diff --git a/src/process/process.rs b/src/process/process.rs index c91dd76..5d096c1 100644 --- a/src/process/process.rs +++ b/src/process/process.rs @@ -67,9 +67,9 @@ impl Process { }; // User stack - use consts::{USER_STACK_OFFSET, USER_STACK_SIZE, USER_TCB_OFFSET}; + use consts::{USER_STACK_OFFSET, USER_STACK_SIZE, USER32_STACK_OFFSET}; let (user_stack_buttom, user_stack_top) = match is32 { - true => (USER_TCB_OFFSET, USER_TCB_OFFSET + USER_STACK_SIZE), + true => (USER32_STACK_OFFSET, USER32_STACK_OFFSET + USER_STACK_SIZE), false => (USER_STACK_OFFSET, USER_STACK_OFFSET + USER_STACK_SIZE), }; diff --git a/src/sync/mutex.rs b/src/sync/mutex.rs index e6e657a..e288602 100644 --- a/src/sync/mutex.rs +++ b/src/sync/mutex.rs @@ -212,7 +212,12 @@ impl MutexSupport for Spin { fn new() -> Self { Spin } fn cpu_relax(&self) { - unsafe { asm!("pause" :::: "volatile"); } + unsafe { + #[cfg(target_arch = "x86_64")] + asm!("pause" :::: "volatile"); + #[cfg(target_arch = "riscv")] + asm!("nop" :::: "volatile"); + } } fn before_lock() -> Self::GuardData {} fn after_unlock(&self) {} @@ -237,7 +242,12 @@ impl MutexSupport for SpinNoIrq { SpinNoIrq } fn cpu_relax(&self) { - unsafe { asm!("pause" :::: "volatile"); } + unsafe { + #[cfg(target_arch = "x86_64")] + asm!("pause" :::: "volatile"); + #[cfg(target_arch = "riscv")] + asm!("nop" :::: "volatile"); + } } fn before_lock() -> Self::GuardData { FlagsGuard(unsafe { interrupt::disable_and_store() })