diff --git a/os/Cargo.toml b/os/Cargo.toml index 43768d78..0d1bb342 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -8,4 +8,8 @@ edition = "2018" [dependencies] riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } -lazy_static = { version = "1.4.0", features = ["spin_no_std"] } \ No newline at end of file +lazy_static = { version = "1.4.0", features = ["spin_no_std"] } + +[features] +board_qemu = [] +board_k210 = [] \ No newline at end of file diff --git a/os/Makefile b/os/Makefile index 217a0c41..1d13ccee 100644 --- a/os/Makefile +++ b/os/Makefile @@ -29,7 +29,7 @@ $(KERNEL_BIN): kernel kernel: @cd ../user && make build - @cargo build --release + @cargo build --release --features "board_$(BOARD)" clean: @cargo clean diff --git a/os/src/config.rs b/os/src/config.rs index 9bc7a3d2..07c30246 100644 --- a/os/src/config.rs +++ b/os/src/config.rs @@ -2,4 +2,10 @@ pub const USER_STACK_SIZE: usize = 4096 * 2; pub const KERNEL_STACK_SIZE: usize = 4096 * 2; pub const MAX_APP_NUM: usize = 4; pub const APP_BASE_ADDRESS: usize = 0x80100000; -pub const APP_SIZE_LIMIT: usize = 0x20000; \ No newline at end of file +pub const APP_SIZE_LIMIT: usize = 0x20000; + +#[cfg(feature = "board_k210")] +pub const CPU_FREQ: usize = 10000000; + +#[cfg(feature = "board_qemu")] +pub const CPU_FREQ: usize = 12500000; \ No newline at end of file diff --git a/os/src/main.rs b/os/src/main.rs index 0b55c6f7..64855732 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -14,6 +14,7 @@ mod trap; mod loader; mod config; mod task; +mod timer; global_asm!(include_str!("entry.asm")); global_asm!(include_str!("link_app.S")); @@ -34,6 +35,9 @@ pub fn rust_main() -> ! { println!("[kernel] Hello, world!"); trap::init(); loader::load_apps(); + trap::enable_interrupt(); + trap::enable_timer_interrupt(); + timer::set_next_trigger(); task::run_first_task(); panic!("Unreachable in rust_main!"); } \ No newline at end of file diff --git a/os/src/sbi.rs b/os/src/sbi.rs index 9fc74a97..36e15fcc 100644 --- a/os/src/sbi.rs +++ b/os/src/sbi.rs @@ -24,6 +24,10 @@ fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { ret } +pub fn set_timer(timer: usize) { + sbi_call(SBI_SET_TIMER, timer, 0, 0); +} + pub fn console_putchar(c: usize) { sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0); } diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index d64bc73c..da411680 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -1,7 +1,7 @@ const SYSCALL_WRITE: usize = 64; const SYSCALL_EXIT: usize = 93; const SYSCALL_YIELD: usize = 124; -//const SYSCALL_GET_TIME: usize = 169; +const SYSCALL_GET_TIME: usize = 169; mod fs; mod process; @@ -14,6 +14,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]), SYSCALL_EXIT => sys_exit(args[0] as i32), SYSCALL_YIELD => sys_yield(), + SYSCALL_GET_TIME => sys_get_time(), _ => panic!("Unsupported syscall_id: {}", syscall_id), } } diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index 9e83ffe8..e0bdebae 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -1,18 +1,20 @@ use crate::task::{ - mark_current_suspended, - mark_current_exited, - run_next_task + suspend_current_and_run_next, + exit_current_and_run_next, }; +use crate::timer::get_time; pub fn sys_exit(xstate: i32) -> ! { println!("[kernel] Application exited with code {}", xstate); - mark_current_exited(); - run_next_task(); + exit_current_and_run_next(); panic!("Unreachable in sys_exit!"); } pub fn sys_yield() -> isize { - mark_current_suspended(); - run_next_task(); + suspend_current_and_run_next(); 0 +} + +pub fn sys_get_time() -> isize { + get_time() as isize } \ No newline at end of file diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index b05485f2..f1d0afaa 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -94,7 +94,7 @@ impl TaskManager { ); } } else { - panic!("[kernel] All applications completed!"); + panic!("All applications completed!"); } } } @@ -103,14 +103,24 @@ pub fn run_first_task() { TASK_MANAGER.run_first_task(); } -pub fn run_next_task() { +fn run_next_task() { TASK_MANAGER.run_next_task(); } -pub fn mark_current_suspended() { +fn mark_current_suspended() { TASK_MANAGER.mark_current_suspended(); } -pub fn mark_current_exited() { +fn mark_current_exited() { TASK_MANAGER.mark_current_exited(); +} + +pub fn suspend_current_and_run_next() { + mark_current_suspended(); + run_next_task(); +} + +pub fn exit_current_and_run_next() { + mark_current_exited(); + run_next_task(); } \ No newline at end of file diff --git a/os/src/timer.rs b/os/src/timer.rs new file mode 100644 index 00000000..7522e708 --- /dev/null +++ b/os/src/timer.rs @@ -0,0 +1,13 @@ +use riscv::register::time; +use crate::sbi::set_timer; +use crate::config::CPU_FREQ; + +const TICKS_PER_SEC: usize = 100; + +pub fn get_time() -> usize { + time::read() +} + +pub fn set_next_trigger() { + set_timer(get_time() + CPU_FREQ / TICKS_PER_SEC); +} \ No newline at end of file diff --git a/os/src/trap/mod.rs b/os/src/trap/mod.rs index a6288997..650b6cac 100644 --- a/os/src/trap/mod.rs +++ b/os/src/trap/mod.rs @@ -7,10 +7,18 @@ use riscv::register::{ self, Trap, Exception, + Interrupt, }, stval, + sstatus, + sie, }; use crate::syscall::syscall; +use crate::task::{ + exit_current_and_run_next, + suspend_current_and_run_next, +}; +use crate::timer::set_next_trigger; global_asm!(include_str!("trap.S")); @@ -21,6 +29,14 @@ pub fn init() { } } +pub fn enable_interrupt() { + unsafe { sstatus::set_sie(); } +} + +pub fn enable_timer_interrupt() { + unsafe { sie::set_stimer(); } +} + #[no_mangle] pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext { let scause = scause::read(); @@ -33,13 +49,15 @@ pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext { Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) => { println!("[kernel] PageFault in application, bad addr = {:#x}, bad instruction = {:#x}, core dumped.", stval, cx.sepc); - panic!("[kernel] Cannot continue!"); - //run_next_app(); + exit_current_and_run_next(); } Trap::Exception(Exception::IllegalInstruction) => { println!("[kernel] IllegalInstruction in application, core dumped."); - panic!("[kernel] Cannot continue!"); - //run_next_app(); + exit_current_and_run_next(); + } + Trap::Interrupt(Interrupt::SupervisorTimer) => { + set_next_trigger(); + suspend_current_and_run_next(); } _ => { panic!("Unsupported trap {:?}, stval = {:#x}!", scause.cause(), stval); diff --git a/user/src/bin/00power_3.rs b/user/src/bin/00power_3.rs new file mode 100644 index 00000000..a4b62ab5 --- /dev/null +++ b/user/src/bin/00power_3.rs @@ -0,0 +1,28 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +const LEN: usize = 100; + +#[no_mangle] +fn main() -> i32 { + let p = 3u64; + let m = 998244353u64; + let iter: usize = 100000; + let mut s = [0u64; LEN]; + let mut cur = 0usize; + s[cur] = 1; + for i in 1..=iter { + let next = if cur + 1 == LEN { 0 } else { cur + 1 }; + s[next] = s[cur] * p % m; + cur = next; + if i % 10000 == 0 { + println!("power_3 [{}/{}]", i, iter); + } + } + println!("{}^{} = {}", p, iter, s[cur]); + println!("Test power_3 OK!"); + 0 +} \ No newline at end of file diff --git a/user/src/bin/00write_a.rs b/user/src/bin/00write_a.rs deleted file mode 100644 index f7ada612..00000000 --- a/user/src/bin/00write_a.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -use user_lib::sys_yield; - -const WIDTH: usize = 10; -const HEIGHT: usize = 5; - -#[no_mangle] -fn main() -> i32 { - for i in 0..HEIGHT { - for _ in 0..WIDTH { print!("A"); } - println!(" [{}/{}]", i + 1, HEIGHT); - sys_yield(); - } - println!("Test write_a OK!"); - 0 -} \ No newline at end of file diff --git a/user/src/bin/01power_5.rs b/user/src/bin/01power_5.rs new file mode 100644 index 00000000..dfd27522 --- /dev/null +++ b/user/src/bin/01power_5.rs @@ -0,0 +1,28 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +const LEN: usize = 100; + +#[no_mangle] +fn main() -> i32 { + let p = 5u64; + let m = 998244353u64; + let iter: usize = 70000; + let mut s = [0u64; LEN]; + let mut cur = 0usize; + s[cur] = 1; + for i in 1..=iter { + let next = if cur + 1 == LEN { 0 } else { cur + 1 }; + s[next] = s[cur] * p % m; + cur = next; + if i % 10000 == 0 { + println!("power_5 [{}/{}]", i, iter); + } + } + println!("{}^{} = {}", p, iter, s[cur]); + println!("Test power_5 OK!"); + 0 +} diff --git a/user/src/bin/01write_b.rs b/user/src/bin/01write_b.rs deleted file mode 100644 index e16b79da..00000000 --- a/user/src/bin/01write_b.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -use user_lib::sys_yield; - -const WIDTH: usize = 10; -const HEIGHT: usize = 2; - -#[no_mangle] -fn main() -> i32 { - for i in 0..HEIGHT { - for _ in 0..WIDTH { print!("B"); } - println!(" [{}/{}]", i + 1, HEIGHT); - sys_yield(); - } - println!("Test write_b OK!"); - 0 -} diff --git a/user/src/bin/02power_7.rs b/user/src/bin/02power_7.rs new file mode 100644 index 00000000..5cf13696 --- /dev/null +++ b/user/src/bin/02power_7.rs @@ -0,0 +1,28 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +const LEN: usize = 100; + +#[no_mangle] +fn main() -> i32 { + let p = 7u64; + let m = 998244353u64; + let iter: usize = 80000; + let mut s = [0u64; LEN]; + let mut cur = 0usize; + s[cur] = 1; + for i in 1..=iter { + let next = if cur + 1 == LEN { 0 } else { cur + 1 }; + s[next] = s[cur] * p % m; + cur = next; + if i % 10000 == 0 { + println!("power_7 [{}/{}]", i, iter); + } + } + println!("{}^{} = {}", p, iter, s[cur]); + println!("Test power_7 OK!"); + 0 +} diff --git a/user/src/bin/02write_c.rs b/user/src/bin/02write_c.rs deleted file mode 100644 index 771f6447..00000000 --- a/user/src/bin/02write_c.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -use user_lib::sys_yield; - -const WIDTH: usize = 10; -const HEIGHT: usize = 3; - -#[no_mangle] -fn main() -> i32 { - for i in 0..HEIGHT { - for _ in 0..WIDTH { print!("C"); } - println!(" [{}/{}]", i + 1, HEIGHT); - sys_yield(); - } - println!("Test write_c OK!"); - 0 -} diff --git a/user/src/bin/03sleep.rs b/user/src/bin/03sleep.rs new file mode 100644 index 00000000..f3d9f31b --- /dev/null +++ b/user/src/bin/03sleep.rs @@ -0,0 +1,18 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use user_lib::{sys_get_time, sys_yield}; + +#[no_mangle] +fn main() -> i32 { + let current_timer = sys_get_time(); + let wait_for = current_timer + 10000000; + while sys_get_time() < wait_for { + sys_yield(); + } + println!("Test sleep OK!"); + 0 +} \ No newline at end of file