diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/os/run.sh b/os/run.sh index bed9ec8..2188894 100755 --- a/os/run.sh +++ b/os/run.sh @@ -1,3 +1,4 @@ +#!/usr/bin/env bash cargo build --release qemu-system-riscv64 \ diff --git a/os/src/batch.rs b/os/src/batch.rs deleted file mode 100644 index 2b09e78..0000000 --- a/os/src/batch.rs +++ /dev/null @@ -1,162 +0,0 @@ -use core::arch::asm; - -use lazy_static::lazy_static; - -use crate::log_information; -use crate::sbi::shutdown; -use crate::sync::single_cell::SingleCell; -use crate::trap::context::TrapContext; - -const MAX_APP_NUMBER: usize = 32; -const APP_BASE_ADDRESS: usize = 0x80400000; -const APP_SIZE_LIMIT: usize = 0x20000; - -struct AppManager { - app_count: usize, - current: usize, - start_addresses: [usize; MAX_APP_NUMBER + 1], -} - -lazy_static! { - static ref APP_MANAGER: SingleCell = unsafe { - SingleCell::new({ - extern "C" { - fn _num_app(); - } - - let num_app_ptr = _num_app as usize as *const usize; - let num_app = num_app_ptr.read_volatile(); - let mut start_addresses: [usize; MAX_APP_NUMBER + 1] = [0; MAX_APP_NUMBER + 1]; - let start_addresses_raw: &[usize] = - core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1); - start_addresses[..=num_app].copy_from_slice(start_addresses_raw); - AppManager { - app_count: num_app, - current: 0, - start_addresses, - } - }) - }; -} - -impl AppManager { - pub fn print_app_information(&self) { - log_information!("[kernel] Application count is {}.", self.app_count); - - for i in 0..self.app_count { - log_information!( - "[kernel] Application_{} ({:#x} -> {:#x})", - i, - self.start_addresses[i], - self.start_addresses[i + 1] - ); - } - } - - pub fn get_current_app(&self) -> usize { - self.current - } - - pub fn move_to_next_app(&mut self) { - self.current += 1; - } - - unsafe fn load_app(&self, app_id: usize) { - if app_id >= self.app_count { - panic!("Application id is invalid!"); - } - - log_information!("[kernel] Loading application_{}...", app_id); - - core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, APP_SIZE_LIMIT).fill(0); - - let app_source = core::slice::from_raw_parts( - self.start_addresses[app_id] as *const u8, - self.start_addresses[app_id + 1] - self.start_addresses[app_id], - ); - let app_destination = - core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, app_source.len()); - app_destination.copy_from_slice(app_source); - - // 保证指令缓存的更新 - // 因为上述代码会修改指令数据段 - asm!("fence.i"); - } -} - -const USER_STACK_SIZE: usize = 4096 * 2; -const KERNEL_STACK_SIZE: usize = 4096 * 2; - -#[repr(align(4096))] -struct UserStack { - data: [u8; USER_STACK_SIZE], -} - -impl UserStack { - fn get_sp(&self) -> usize { - self.data.as_ptr() as usize + USER_STACK_SIZE - } -} - -#[repr(align(4096))] -struct KernelStack { - data: [u8; KERNEL_STACK_SIZE], -} - -impl KernelStack { - fn get_sp(&self) -> usize { - self.data.as_ptr() as usize + KERNEL_STACK_SIZE - } - - pub fn push_context(&self, context: TrapContext) -> &'static mut TrapContext { - let context_pointer = (self.get_sp() - size_of::()) as *mut TrapContext; - unsafe { - *context_pointer = context; - context_pointer.as_mut().unwrap() - } - } -} - -static KERNEL_STACK: KernelStack = KernelStack { - data: [0; KERNEL_STACK_SIZE], -}; -static USER_STACK: UserStack = UserStack { - data: [0; USER_STACK_SIZE], -}; - -pub fn print_app_information() { - let app_manager = APP_MANAGER.exclusive_borrow(); - app_manager.print_app_information(); -} - -pub fn run_next_application() -> ! { - let mut app_manager = APP_MANAGER.exclusive_borrow(); - let current_app = app_manager.get_current_app(); - if current_app >= app_manager.app_count { - log_information!("Run out of applications, the os will stop!"); - shutdown(true); - } - - unsafe { - app_manager.load_app(current_app); - } - app_manager.move_to_next_app(); - - // We must drop resource manually - // As this function will never return! - drop(app_manager); - - extern "C" { - fn __restore(context_address: usize); - } - - unsafe { - let context_address = KERNEL_STACK.push_context(TrapContext::init_application_context( - APP_BASE_ADDRESS, - USER_STACK.get_sp(), - )) as *const _ as usize; - __restore(context_address); - - unreachable!() - } -} diff --git a/os/src/boards.rs b/os/src/boards.rs new file mode 100644 index 0000000..1d6396d --- /dev/null +++ b/os/src/boards.rs @@ -0,0 +1 @@ +pub mod qemu; \ No newline at end of file diff --git a/os/src/boards/qemu.rs b/os/src/boards/qemu.rs new file mode 100644 index 0000000..ed95dd0 --- /dev/null +++ b/os/src/boards/qemu.rs @@ -0,0 +1 @@ +pub const CLOCK_FREQUENCY: usize = 10000000; \ No newline at end of file diff --git a/os/src/config.rs b/os/src/config.rs new file mode 100644 index 0000000..1c7c317 --- /dev/null +++ b/os/src/config.rs @@ -0,0 +1,8 @@ +pub const USER_STACK_SIZE: usize = 4096; +pub const KERNEL_STACK_SIZE: usize = 4096 * 2; + +pub const MAX_APP_NUM: usize = 4; +pub const APP_BASE_ADDRESS: usize = 0x80400000; +pub const APP_SIZE_LIMIT: usize = 0x20000; + +pub use crate::boards::qemu::CLOCK_FREQUENCY; \ No newline at end of file diff --git a/os/src/loader.rs b/os/src/loader.rs new file mode 100644 index 0000000..e33e14b --- /dev/null +++ b/os/src/loader.rs @@ -0,0 +1,98 @@ +use crate::config::{ + APP_BASE_ADDRESS, APP_SIZE_LIMIT, KERNEL_STACK_SIZE, MAX_APP_NUM, USER_STACK_SIZE, +}; +use core::arch::asm; +use crate::trap::context::TrapContext; + +#[repr(align(4096))] +#[derive(Copy, Clone)] +struct KernelStack { + data: [u8; KERNEL_STACK_SIZE], +} + +#[repr(align(4096))] +#[derive(Copy, Clone)] +struct UserStack { + data: [u8; USER_STACK_SIZE], +} + +static KERNEL_STACK: [KernelStack; MAX_APP_NUM] = [KernelStack { + data: [0; KERNEL_STACK_SIZE], +}; MAX_APP_NUM]; + +static USER_STACK: [UserStack; MAX_APP_NUM] = [UserStack { + data: [0; USER_STACK_SIZE], +}; MAX_APP_NUM]; + +impl KernelStack { + fn get_sp(&self) -> usize { + self.data.as_ptr() as usize + KERNEL_STACK_SIZE + } + + pub fn push_context(&self, trap_context: TrapContext) -> usize { + let pointer = (self.get_sp() - core::mem::size_of::()) as *mut TrapContext; + + unsafe { + *pointer = trap_context; + } + + pointer as usize + } +} + +impl UserStack { + fn get_sp(&self) -> usize { + self.data.as_ptr() as usize + USER_STACK_SIZE + } +} + +pub fn get_app_num() -> usize { + extern "C" { + fn _num_app(); + } + + let app_num_ptr = _num_app as usize as *const usize; + + unsafe { app_num_ptr.read_volatile() } +} + +pub fn load_apps() { + extern "C" { + fn _num_app(); + } + + let app_num_ptr = _num_app as usize as *const usize; + let app_num = unsafe { app_num_ptr.read_volatile() }; + let app_start = unsafe { core::slice::from_raw_parts(app_num_ptr.add(1), app_num + 1) }; + + for i in 0..app_num { + let base_address = APP_BASE_ADDRESS + i * APP_SIZE_LIMIT; + + // 清除目标的内存区域 + for address in base_address..base_address + APP_SIZE_LIMIT { + unsafe { + (address as *mut u8).write_volatile(0); + } + } + + // 将程序从数据段复制过来 + let source = unsafe { + core::slice::from_raw_parts(app_start[i] as *const u8, app_start[i + 1] - app_start[i]) + }; + let destination = + unsafe { core::slice::from_raw_parts_mut(base_address as *mut u8, source.len()) }; + + destination.copy_from_slice(source); + } + + unsafe { + asm!("fence.i"); + } +} + +pub fn initialize_app_context(app_id: usize) -> usize { + KERNEL_STACK[app_id].push_context(TrapContext::init_application_context( + APP_BASE_ADDRESS + app_id * APP_SIZE_LIMIT, + USER_STACK[app_id].get_sp() + )) +} \ No newline at end of file diff --git a/os/src/main.rs b/os/src/main.rs index c2e2c42..b1f37a1 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -4,13 +4,17 @@ use crate::utils::clear_bss; use core::arch::global_asm; -mod batch; mod console; mod sbi; mod sync; mod syscall; mod trap; mod utils; +mod loader; +mod boards; +mod config; +mod task; +mod timer; global_asm!(include_str!("entry.asm")); global_asm!(include_str!("link_app.asm")); @@ -20,6 +24,8 @@ fn rust_main() -> ! { clear_bss(); log_information!("[kernel] Hello, rCore!"); trap::init(); - batch::print_app_information(); - batch::run_next_application(); + loader::load_apps(); + task::run_first_task(); + + unreachable!() } diff --git a/os/src/sbi.rs b/os/src/sbi.rs index 73c351c..cda8d70 100644 --- a/os/src/sbi.rs +++ b/os/src/sbi.rs @@ -14,3 +14,7 @@ pub fn shutdown(failure: bool) -> ! { unreachable!() } + +pub fn set_timer(timer: usize) { + sbi_rt::set_timer(timer as _); +} diff --git a/os/src/syscall.rs b/os/src/syscall.rs index 91cf8d9..03dcfbe 100644 --- a/os/src/syscall.rs +++ b/os/src/syscall.rs @@ -1,18 +1,22 @@ use crate::syscall::fs::sys_write; -use crate::syscall::process::sys_exit; +use crate::syscall::process::{sys_exit, sys_get_time, sys_yield}; mod fs; mod process; const SYSCALL_WRITE: usize = 64; const SYSCALL_EXIT: usize = 93; +const SYSCALL_YIELD: usize = 124; +const SYSCALL_GET_TIME: usize = 169; pub fn syscall(syscall_id: usize, args: [usize; 3]) -> usize { match syscall_id { 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: {}", syscall_id) - } + }, } } diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index 859e998..97d129b 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -8,7 +8,7 @@ pub fn sys_write(fd: usize, buffer: *const u8, len: usize) -> usize { let slice = unsafe { core::slice::from_raw_parts(buffer, len) }; let str = core::str::from_utf8(slice).unwrap(); print!("{}", str); - len as usize + len } _ => { panic!("Unsupported file descriptor in sys_write"); diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index 619c197..54059cd 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -1,7 +1,20 @@ -use crate::batch::run_next_application; use crate::println; +use crate::task::{exit_current_and_run_next, suspend_current_and_run_next}; +use crate::timer::get_time_ms; pub fn sys_exit(exit_state: i32) -> ! { println!("[kernel] Application exited with code {}.", exit_state); - run_next_application() + exit_current_and_run_next(); + + unreachable!() +} + +pub fn sys_yield() -> usize { + suspend_current_and_run_next(); + + 0 +} + +pub fn sys_get_time() -> usize { + get_time_ms() } diff --git a/os/src/task.rs b/os/src/task.rs new file mode 100644 index 0000000..e65477c --- /dev/null +++ b/os/src/task.rs @@ -0,0 +1,133 @@ +use crate::config::MAX_APP_NUM; +use crate::loader::{get_app_num, initialize_app_context}; +use crate::log_information; +use crate::sbi::shutdown; +use crate::sync::single_cell::SingleCell; +use crate::task::context::TaskContext; +use crate::task::switch::__switch; +use lazy_static::lazy_static; + +mod context; +mod switch; + +#[derive(Copy, Clone, PartialEq)] +pub enum TaskStatus { + NotInitialized, + Ready, + Running, + Exited, +} + +#[derive(Copy, Clone)] +pub struct TaskControlBlock { + pub status: TaskStatus, + pub context: TaskContext, +} + +pub struct TaskManagerInner { + tasks: [TaskControlBlock; MAX_APP_NUM], + current_task: usize, +} + +pub struct TaskManager { + app_numer: usize, + inner: SingleCell, +} + +lazy_static! { + static ref TASK_MANAGER: TaskManager = { + let app_num = get_app_num(); + let mut tasks = [TaskControlBlock { + context: TaskContext::new(), + status: TaskStatus::NotInitialized, + }; MAX_APP_NUM]; + + for (i, task) in tasks.iter_mut().enumerate() { + task.context = TaskContext::goto_restore(initialize_app_context(i)); + task.status = TaskStatus::Ready; + } + + TaskManager { + app_numer: app_num, + inner: unsafe { + SingleCell::new(TaskManagerInner { + tasks, + current_task: 0, + }) + }, + } + }; +} + +pub fn run_first_task() { + TASK_MANAGER.run_first_task(); +} + +pub fn suspend_current_and_run_next() { + TASK_MANAGER.mark_current_suspended(); + TASK_MANAGER.run_next_task(); +} + +pub fn exit_current_and_run_next() { + TASK_MANAGER.mark_current_exited(); + TASK_MANAGER.run_next_task(); +} + +impl TaskManager { + /// status from running to ready + fn mark_current_suspended(&self) { + let mut inner = self.inner.exclusive_borrow(); + let current = inner.current_task; + inner.tasks[current].status = TaskStatus::Ready; + } + + /// status from running to exited + fn mark_current_exited(&self) { + let mut inner = self.inner.exclusive_borrow(); + let current = inner.current_task; + inner.tasks[current].status = TaskStatus::Exited; + } + + fn find_next_task(&self) -> Option { + let inner = self.inner.exclusive_borrow(); + (inner.current_task + 1..inner.current_task + self.app_numer + 1) + .map(|id| id % self.app_numer) + .find(|id| inner.tasks[*id].status == TaskStatus::Ready) + } + + fn run_next_task(&self) { + if let Some(next) = self.find_next_task() { + let mut inner = self.inner.exclusive_borrow(); + let current = inner.current_task; + + inner.tasks[next].status = TaskStatus::Running; + inner.current_task = next; + + let current_task_context = &mut inner.tasks[current].context as *mut TaskContext; + let next_task_context = &inner.tasks[next].context as *const TaskContext; + drop(inner); + + unsafe { + __switch(current_task_context, next_task_context); + } + } else { + log_information!("All application completed!"); + shutdown(false); + } + } + + fn run_first_task(&self) -> ! { + let mut inner = self.inner.exclusive_borrow(); + let task0 = &mut inner.tasks[0]; + task0.status = TaskStatus::Running; + let next_task_context = &task0.context as *const TaskContext; + drop(inner); + + let mut unused = TaskContext::new(); + unsafe { + __switch(&mut unused as *mut TaskContext, next_task_context); + } + + unreachable!(); + } +} diff --git a/os/src/task/context.rs b/os/src/task/context.rs new file mode 100644 index 0000000..9b0b887 --- /dev/null +++ b/os/src/task/context.rs @@ -0,0 +1,31 @@ + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct TaskContext { + ra: usize, + sp: usize, + s: [usize; 12] +} + +impl TaskContext { + pub fn new() -> Self { + Self { + ra: 0, + sp: 0, + s: [0; 12] + } + } + + /// set the task context { __restore function, kernel stack, s_0 -> s_12 } + pub fn goto_restore(kernel_stack_pointer: usize) -> Self { + extern "C" { + fn __restore(); + } + + Self { + ra: __restore as usize, + sp: kernel_stack_pointer, + s: [0; 12] + } + } +} diff --git a/os/src/task/switch.asm b/os/src/task/switch.asm new file mode 100644 index 0000000..72abfa6 --- /dev/null +++ b/os/src/task/switch.asm @@ -0,0 +1,33 @@ +.altmacro +.macro SAVE_SN n + sd s\n, (\n+2)*8(a0) +.endm +.macro LOAD_SN n + ld s\n, (\n+2)*8(a1) +.endm + .section .text + .globl __switch +__switch: + # __switch( + # current_task_cx_ptr: *mut TaskContext, + # next_task_cx_ptr: *const TaskContext + # ) + # save kernel stack of current task + sd sp, 8(a0) + # save ra & s0~s11 of current execution + sd ra, 0(a0) + .set n, 0 + .rept 12 + SAVE_SN %n + .set n, n + 1 + .endr + # restore ra & s0~s11 of next execution + ld ra, 0(a1) + .set n, 0 + .rept 12 + LOAD_SN %n + .set n, n + 1 + .endr + # restore kernel stack of next task + ld sp, 8(a1) + ret \ No newline at end of file diff --git a/os/src/task/switch.rs b/os/src/task/switch.rs new file mode 100644 index 0000000..6ef6dcf --- /dev/null +++ b/os/src/task/switch.rs @@ -0,0 +1,10 @@ +use crate::task::context::TaskContext; +use core::arch::global_asm; + +global_asm!(include_str!("switch.asm")); + +extern "C" { + pub fn __switch(current_task_context: *mut TaskContext, next_task_context: *const TaskContext); +} + + diff --git a/os/src/timer.rs b/os/src/timer.rs new file mode 100644 index 0000000..6c0ec82 --- /dev/null +++ b/os/src/timer.rs @@ -0,0 +1,18 @@ +use riscv::register::time; +use crate::config::CLOCK_FREQUENCY; +use crate::sbi::set_timer; + +pub fn get_time() -> usize { + time::read() +} + +/// 每秒执行100次,即10ms执行一次 +const TICKS_PRE_SECOND: usize = 100; + +pub fn get_time_ms() -> usize { + time::read() / CLOCK_FREQUENCY * 1000 +} + +pub fn set_next_trigger() { + set_timer(get_time() + CLOCK_FREQUENCY / TICKS_PRE_SECOND); +} diff --git a/os/src/trap.asm b/os/src/trap.asm index 7ca7154..3aaad85 100644 --- a/os/src/trap.asm +++ b/os/src/trap.asm @@ -39,9 +39,6 @@ __alltraps: call trap_handler __restore: - # case1: start running app by __restore - # case2: back to U after handling trap - mv sp, a0 # now sp->kernel stack(after allocated), sscratch->user stack # restore sstatus/sepc ld t0, 32*8(sp) @@ -50,7 +47,7 @@ __restore: csrw sstatus, t0 csrw sepc, t1 csrw sscratch, t2 - # restore general-purpuse registers except sp/tp + # restore general-purpose registers except sp/tp ld x1, 1*8(sp) ld x3, 3*8(sp) .set n, 5 diff --git a/os/src/trap.rs b/os/src/trap.rs index e7aec3e..d97caac 100644 --- a/os/src/trap.rs +++ b/os/src/trap.rs @@ -1,13 +1,10 @@ -use crate::batch::run_next_application; use crate::println; use crate::syscall::syscall; use crate::trap::context::TrapContext; use core::arch::global_asm; -use riscv::register::{ - mtvec::TrapMode, - scause::{self, Exception, Trap}, - stval, stvec, -}; +use riscv::register::{mtvec::TrapMode, scause::{self, Exception, Trap, Interrupt}, sie, stval, stvec}; +use crate::task::{exit_current_and_run_next, suspend_current_and_run_next}; +use crate::timer::set_next_trigger; pub mod context; @@ -18,7 +15,12 @@ pub fn init() { fn __alltraps(); } unsafe { + // 设置中断向量 stvec::write(__alltraps as usize, TrapMode::Direct); + + // 启动时钟中断 + sie::set_stimer(); + set_next_trigger(); } } @@ -34,11 +36,15 @@ pub fn trap_handler(context: &mut TrapContext) -> &mut TrapContext { } Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) => { println!("[kernel] PageFault in application, kernel will kill it."); - run_next_application(); + exit_current_and_run_next(); } Trap::Exception(Exception::IllegalInstruction) => { println!("[kernel] Illegal instruction in application, kernel will kill it."); - run_next_application(); + exit_current_and_run_next(); + } + Trap::Interrupt(Interrupt::SupervisorTimer) => { + set_next_trigger(); + suspend_current_and_run_next(); } _ => { panic!( diff --git a/os/src/trap/context.rs b/os/src/trap/context.rs index c467b0a..d1171ea 100644 --- a/os/src/trap/context.rs +++ b/os/src/trap/context.rs @@ -8,9 +8,11 @@ pub struct TrapContext { } impl TrapContext { - pub unsafe fn init_application_context(entry: usize, sp: usize) -> Self { + pub fn init_application_context(entry: usize, sp: usize) -> Self { let sstatus = sstatus::read(); - sstatus::set_spp(SPP::User); + unsafe { + sstatus::set_spp(SPP::User); + } let mut context = Self { x: [0; 32], s_status: sstatus, diff --git a/user/Makefile b/user/Makefile deleted file mode 100644 index c643fbe..0000000 --- a/user/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -TARGET := riscv64gc-unknown-none-elf -MODE := release -APP_DIR := src/bin -TARGET_DIR := target/$(TARGET)/$(MODE) -APPS := $(wildcard $(APP_DIR)/*.rs) -ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS)) -BINS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%.bin, $(APPS)) - -OBJDUMP := rust-objdump --arch-name=riscv64 -OBJCOPY := rust-objcopy --binary-architecture=riscv64 - -elf: - @cargo build --release - -binary: elf - @$(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));) - -build: binary \ No newline at end of file diff --git a/user/build.py b/user/build.py new file mode 100755 index 0000000..c82f02e --- /dev/null +++ b/user/build.py @@ -0,0 +1,30 @@ +#!/bin/python3 +import os + +base_address = 0x80400000 +step = 0x20000 +linker = 'src/linker.ld' +target_dir = "target/riscv64gc-unknown-none-elf/release/" + +app_id = 0 +apps = os.listdir('src/bin') +apps.sort() +for app in apps: + app = app[:app.find('.')] + lines = [] + lines_before = [] + with open(linker, 'r') as f: + for line in f.readlines(): + lines_before.append(line) + line = line.replace(hex(base_address), hex(base_address+step * app_id)) + lines.append(line) + with open(linker, 'w+') as f: + f.writelines(lines) + os.system('cargo build --bin %s --release' % app) + source_name = target_dir + app + dest_name = target_dir + app + ".bin" + os.system("rust-objcopy %s --binary-architecture=riscv64 --strip-all -O binary %s" %(source_name, dest_name)) + print('[build.py] application %s start with address %s' %(app, hex(base_address+step*app_id))) + with open(linker, 'w+') as f: + f.writelines(lines_before) + app_id = app_id + 1 \ No newline at end of file diff --git a/user/src/bin/hello_world.rs b/user/src/bin/hello_world.rs deleted file mode 100644 index f457094..0000000 --- a/user/src/bin/hello_world.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -#[no_mangle] -fn main() -> i32 { - println!("Hello, world!"); - - 0 -} diff --git a/user/src/bin/illegal_instruction.rs b/user/src/bin/illegal_instruction.rs deleted file mode 100644 index 04dac37..0000000 --- a/user/src/bin/illegal_instruction.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -use core::arch::asm; - -#[no_mangle] -fn main() -> i32 { - println!("Try to execute privileged instruction in U Mode"); - println!("Kernel should kill this application!"); - unsafe { - asm!("sret"); - } - 0 -} diff --git a/user/src/bin/power.rs b/user/src/bin/power.rs deleted file mode 100644 index f628f34..0000000 --- a/user/src/bin/power.rs +++ /dev/null @@ -1,27 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -const SIZE: usize = 10; -const P: u32 = 3; -const STEP: usize = 100000; -const MOD: u32 = 10007; - -#[no_mangle] -fn main() -> i32 { - let mut pow = [0u32; SIZE]; - let mut index: usize = 0; - pow[index] = 1; - for i in 1..=STEP { - let last = pow[index]; - index = (index + 1) % SIZE; - pow[index] = last * P % MOD; - if i % 10000 == 0 { - println!("{}^{}={}(MOD {})", P, i, pow[index], MOD); - } - } - println!("Test power OK!"); - 0 -} diff --git a/user/src/bin/power_3.rs b/user/src/bin/power_3.rs new file mode 100644 index 0000000..e0ec5f3 --- /dev/null +++ b/user/src/bin/power_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 = 200000; + 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!("{}^{} = {}(MOD {})", p, iter, s[cur], m); + println!("Test power_3 OK!"); + 0 +} \ No newline at end of file diff --git a/user/src/bin/power_5.rs b/user/src/bin/power_5.rs new file mode 100644 index 0000000..f31a24e --- /dev/null +++ b/user/src/bin/power_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 = 140000; + 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!("{}^{} = {}(MOD {})", p, iter, s[cur], m); + println!("Test power_5 OK!"); + 0 +} \ No newline at end of file diff --git a/user/src/bin/power_7.rs b/user/src/bin/power_7.rs new file mode 100644 index 0000000..fd9f23e --- /dev/null +++ b/user/src/bin/power_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 = 160000; + 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!("{}^{} = {}(MOD {})", p, iter, s[cur], m); + println!("Test power_7 OK!"); + 0 +} \ No newline at end of file diff --git a/user/src/bin/sleep.rs b/user/src/bin/sleep.rs new file mode 100644 index 0000000..b19774a --- /dev/null +++ b/user/src/bin/sleep.rs @@ -0,0 +1,20 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use user_lib::{get_time, sys_yield}; + +#[no_mangle] +fn main() -> i32 { + let current_time = get_time(); + let wait_time = current_time + 3000; + + while get_time() < wait_time { + sys_yield(); + } + + println!("Test sleep OK!"); + 0 +} \ No newline at end of file diff --git a/user/src/bin/store_fault.rs b/user/src/bin/store_fault.rs deleted file mode 100644 index f8023eb..0000000 --- a/user/src/bin/store_fault.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -#[no_mangle] -fn main() -> i32 { - println!("Into Test store_fault, we will insert an invalid store operation..."); - println!("Kernel should kill this application!"); - unsafe { - core::ptr::null_mut::().write_volatile(0); - } - 0 -} diff --git a/user/src/lib.rs b/user/src/lib.rs index fbe8862..dcbfc32 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -1,7 +1,7 @@ #![no_std] #![feature(linkage)] -use crate::syscall::{sys_exit, sys_write}; +use crate::syscall::{sys_exit, sys_get_time, sys_write}; mod syscall; mod utils; @@ -28,3 +28,11 @@ pub fn write(fd: usize, buf: &[u8]) -> isize { pub fn exit(exit_code: i32) -> isize { sys_exit(exit_code) } + +pub fn get_time() -> isize { + sys_get_time() +} + +pub fn sys_yield() -> isize { + syscall::sys_yield() +} diff --git a/user/src/syscall.rs b/user/src/syscall.rs index 6025b8e..44551fd 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -2,6 +2,8 @@ use core::arch::asm; const SYSCALL_WRITE: usize = 64; const SYSCALL_EXIT: usize = 93; +const SYSCALL_YIELD: usize = 124; +const SYSCALL_GET_TIME: usize = 169; fn syscall(id: usize, args: [usize; 3]) -> isize { let mut result: isize; @@ -26,3 +28,11 @@ pub fn sys_write(fd: usize, buffer: &[u8]) -> isize { pub fn sys_exit(exit_code: i32) -> isize { syscall(SYSCALL_EXIT, [exit_code as usize, 0, 0]) } + +pub fn sys_yield() -> isize { + syscall(SYSCALL_YIELD, [0, 0, 0]) +} + +pub fn sys_get_time() -> isize { + syscall(SYSCALL_GET_TIME, [0, 0, 0]) +}