From c47d636498ba5bd3199845fb0a01c6ec228ac61f Mon Sep 17 00:00:00 2001 From: jackfiled Date: Wed, 17 Jul 2024 18:12:33 +0800 Subject: [PATCH 1/4] add AppManager --- os/Cargo.lock | 16 +++++++ os/Cargo.toml | 1 + os/build.rs | 56 +++++++++++++++++++++++++ os/src/.gitignore | 1 + os/src/batch.rs | 86 ++++++++++++++++++++++++++++++++++++++ os/src/main.rs | 4 ++ os/src/sync.rs | 1 + os/src/sync/unsafe_cell.rs | 24 +++++++++++ 8 files changed, 189 insertions(+) create mode 100644 os/build.rs create mode 100644 os/src/.gitignore create mode 100644 os/src/batch.rs create mode 100644 os/src/sync.rs create mode 100644 os/src/sync/unsafe_cell.rs diff --git a/os/Cargo.lock b/os/Cargo.lock index 0ddea58..d6406ea 100644 --- a/os/Cargo.lock +++ b/os/Cargo.lock @@ -2,10 +2,20 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + [[package]] name = "os" version = "0.1.0" dependencies = [ + "lazy_static", "sbi-rt", ] @@ -27,6 +37,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "static_assertions" version = "1.1.0" diff --git a/os/Cargo.toml b/os/Cargo.toml index 7fb4302..43e795b 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -5,3 +5,4 @@ edition = "2021" [dependencies] sbi-rt = { version = "0.0.2", features = ["legacy"] } +lazy_static = { version = "1.4.0", features = ["spin_no_std"] } diff --git a/os/build.rs b/os/build.rs new file mode 100644 index 0000000..5d0c988 --- /dev/null +++ b/os/build.rs @@ -0,0 +1,56 @@ +use std::fs::{read_dir, File}; +use std::io::{Result, Write}; + +fn main() { + println!("cargo:rerun-if-changed=../user/src/"); + println!("cargo:rerun-if-changed={}", TARGET_PATH); + insert_app_data().unwrap(); +} + +static TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/"; + +fn insert_app_data() -> Result<()> { + let mut f = File::create("src/link_app.asm").unwrap(); + let mut apps: Vec<_> = read_dir("../user/src/bin") + .unwrap() + .into_iter() + .map(|dir_entry| { + let mut name_with_ext = dir_entry.unwrap().file_name().into_string().unwrap(); + name_with_ext.drain(name_with_ext.find('.').unwrap()..name_with_ext.len()); + name_with_ext + }) + .collect(); + apps.sort(); + + writeln!( + f, + r#" + .align 3 + .section .data + .global _num_app +_num_app: + .quad {}"#, + apps.len() + )?; + + for i in 0..apps.len() { + writeln!(f, r#" .quad app_{}_start"#, i)?; + } + writeln!(f, r#" .quad app_{}_end"#, apps.len() - 1)?; + + for (idx, app) in apps.iter().enumerate() { + println!("app_{}: {}", idx, app); + writeln!( + f, + r#" + .section .data + .global app_{0}_start + .global app_{0}_end +app_{0}_start: + .incbin "{2}{1}.bin" +app_{0}_end:"#, + idx, app, TARGET_PATH + )?; + } + Ok(()) +} \ No newline at end of file diff --git a/os/src/.gitignore b/os/src/.gitignore new file mode 100644 index 0000000..09f0f39 --- /dev/null +++ b/os/src/.gitignore @@ -0,0 +1 @@ +link_app.asm diff --git a/os/src/batch.rs b/os/src/batch.rs new file mode 100644 index 0000000..349cdb2 --- /dev/null +++ b/os/src/batch.rs @@ -0,0 +1,86 @@ +use core::arch::asm; +use core::cell::UnsafeCell; +use lazy_static::lazy_static; +use crate::println; + +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: UnsafeCell = unsafe { + UnsafeCell::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) { + println!("[kernel] Application count is {}.", self.app_count); + + for i in 0..self.app_count { + println!("[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!"); + } + + println!("[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_SIZE_LIMIT + ); + app_destination.copy_from_slice(app_source); + + // 保证指令缓存的更新 + // 因为上述代码会修改指令数据段 + asm!("fence.i"); + } +} + diff --git a/os/src/main.rs b/os/src/main.rs index 7d69b5e..c837444 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -7,8 +7,12 @@ use crate::utils::clear_bss; mod utils; mod sbi; mod console; +mod batch; +mod sync; global_asm!(include_str!("entry.asm")); +global_asm!(include_str!("link_app.asm")); + #[no_mangle] fn rust_main() -> ! { diff --git a/os/src/sync.rs b/os/src/sync.rs new file mode 100644 index 0000000..47af97e --- /dev/null +++ b/os/src/sync.rs @@ -0,0 +1 @@ +mod unsafe_cell; \ No newline at end of file diff --git a/os/src/sync/unsafe_cell.rs b/os/src/sync/unsafe_cell.rs new file mode 100644 index 0000000..502d8ce --- /dev/null +++ b/os/src/sync/unsafe_cell.rs @@ -0,0 +1,24 @@ +use core::cell::{RefCell, RefMut}; + +/// 只能在单核场景下保持安全的屑RefCell +struct UnsafeCell { + inner_cell: RefCell +} + +unsafe impl Sync for UnsafeCell { + +} + +impl UnsafeCell { + pub unsafe fn new(value: T) -> UnsafeCell { + Self { + inner_cell: RefCell::new(value) + } + } + + /// 独占访问 + /// 当已被借用时访问会Panic + pub fn exclusive_access(&self) -> RefMut<'_, T> { + self.inner_cell.borrow_mut() + } +} \ No newline at end of file -- 2.45.1 From 8cf6fdc9bfc752c535ecefac632fc024a37b3f30 Mon Sep 17 00:00:00 2001 From: jackfiled Date: Thu, 18 Jul 2024 22:48:23 +0800 Subject: [PATCH 2/4] add: finish basic work --- os/Cargo.lock | 55 +++++++++++++++++++++++ os/Cargo.toml | 1 + os/src/batch.rs | 90 ++++++++++++++++++++++++++++++++++---- os/src/main.rs | 12 ++--- os/src/sync.rs | 2 +- os/src/sync/single_cell.rs | 24 ++++++++++ os/src/sync/unsafe_cell.rs | 24 ---------- os/src/syscall.rs | 18 ++++++++ os/src/syscall/fs.rs | 17 +++++++ os/src/syscall/process.rs | 7 +++ os/src/trap.asm | 67 ++++++++++++++++++++++++++++ os/src/trap.rs | 47 ++++++++++++++++++++ os/src/trap/context.rs | 29 ++++++++++++ 13 files changed, 353 insertions(+), 40 deletions(-) create mode 100644 os/src/sync/single_cell.rs delete mode 100644 os/src/sync/unsafe_cell.rs create mode 100644 os/src/syscall.rs create mode 100644 os/src/syscall/fs.rs create mode 100644 os/src/syscall/process.rs create mode 100644 os/src/trap.asm create mode 100644 os/src/trap.rs create mode 100644 os/src/trap/context.rs diff --git a/os/Cargo.lock b/os/Cargo.lock index d6406ea..3775338 100644 --- a/os/Cargo.lock +++ b/os/Cargo.lock @@ -2,6 +2,28 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -11,14 +33,41 @@ dependencies = [ "spin", ] +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + [[package]] name = "os" version = "0.1.0" dependencies = [ "lazy_static", + "riscv", "sbi-rt", ] +[[package]] +name = "riscv" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa3145d2fae3778b1e31ec2e827b228bdc6abd9b74bb5705ba46dcb82069bc4f" +dependencies = [ + "bit_field", + "critical-section", + "embedded-hal", +] + [[package]] name = "sbi-rt" version = "0.0.2" @@ -48,3 +97,9 @@ name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/os/Cargo.toml b/os/Cargo.toml index 43e795b..22acc70 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" [dependencies] sbi-rt = { version = "0.0.2", features = ["legacy"] } lazy_static = { version = "1.4.0", features = ["spin_no_std"] } +riscv = { version = "0.10.0" } diff --git a/os/src/batch.rs b/os/src/batch.rs index 349cdb2..2698466 100644 --- a/os/src/batch.rs +++ b/os/src/batch.rs @@ -1,7 +1,10 @@ use core::arch::asm; -use core::cell::UnsafeCell; + use lazy_static::lazy_static; -use crate::println; + +use crate::log_information; +use crate::sync::single_cell::SingleCell; +use crate::trap::context::TrapContext; const MAX_APP_NUMBER: usize = 32; const APP_BASE_ADDRESS: usize = 0x80400000; @@ -14,13 +17,13 @@ struct AppManager { } lazy_static! { - static ref APP_MANAGER: UnsafeCell = unsafe { - UnsafeCell::new({ + 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_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( @@ -38,10 +41,10 @@ lazy_static! { impl AppManager { pub fn print_app_information(&self) { - println!("[kernel] Application count is {}.", self.app_count); + log_information!("[kernel] Application count is {}.", self.app_count); for i in 0..self.app_count { - println!("[kernel] Application_{} ({:#x} -> {:#x})", + log_information!("[kernel] Application_{} ({:#x} -> {:#x})", i, self.start_addresses[i], self.start_addresses[i + 1]); @@ -61,7 +64,7 @@ impl AppManager { panic!("Application id is invalid!"); } - println!("[kernel] Loading application_{}...", app_id); + log_information!("[kernel] Loading application_{}...", app_id); core::slice::from_raw_parts_mut( APP_BASE_ADDRESS as *mut u8, @@ -74,7 +77,7 @@ impl AppManager { ); let app_destination = core::slice::from_raw_parts_mut( APP_BASE_ADDRESS as *mut u8, - APP_SIZE_LIMIT + app_source.len() ); app_destination.copy_from_slice(app_source); @@ -84,3 +87,72 @@ impl AppManager { } } +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(); + 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/main.rs b/os/src/main.rs index c837444..af83c41 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -9,6 +9,8 @@ mod sbi; mod console; mod batch; mod sync; +mod trap; +mod syscall; global_asm!(include_str!("entry.asm")); global_asm!(include_str!("link_app.asm")); @@ -17,11 +19,9 @@ global_asm!(include_str!("link_app.asm")); #[no_mangle] fn rust_main() -> ! { clear_bss(); - log_error!("Hello, rCore!"); - log_warning!("Hello, rCore!"); - log_information!("Hello, rCore!"); - log_debug!("Hello, rCore!"); - log_trace!("Hello, rCore!"); - sbi::shutdown(false); + log_information!("[kernel] Hello, rCore!"); + trap::init(); + batch::print_app_information(); + batch::run_next_application(); } diff --git a/os/src/sync.rs b/os/src/sync.rs index 47af97e..5c76622 100644 --- a/os/src/sync.rs +++ b/os/src/sync.rs @@ -1 +1 @@ -mod unsafe_cell; \ No newline at end of file +pub mod single_cell; \ No newline at end of file diff --git a/os/src/sync/single_cell.rs b/os/src/sync/single_cell.rs new file mode 100644 index 0000000..c647797 --- /dev/null +++ b/os/src/sync/single_cell.rs @@ -0,0 +1,24 @@ +use core::cell::{RefCell, RefMut}; + +/// 只能在单核场景下保持安全的屑RefCell +pub struct SingleCell { + inner: RefCell +} + +unsafe impl Sync for SingleCell { + +} + +impl SingleCell { + pub unsafe fn new(value: T) -> SingleCell { + SingleCell { + inner: RefCell::new(value) + } + } + + /// 独占访问 + /// 当已被借用时访问会Panic + pub fn exclusive_borrow(&self) -> RefMut<'_, T> { + self.inner.borrow_mut() + } +} diff --git a/os/src/sync/unsafe_cell.rs b/os/src/sync/unsafe_cell.rs deleted file mode 100644 index 502d8ce..0000000 --- a/os/src/sync/unsafe_cell.rs +++ /dev/null @@ -1,24 +0,0 @@ -use core::cell::{RefCell, RefMut}; - -/// 只能在单核场景下保持安全的屑RefCell -struct UnsafeCell { - inner_cell: RefCell -} - -unsafe impl Sync for UnsafeCell { - -} - -impl UnsafeCell { - pub unsafe fn new(value: T) -> UnsafeCell { - Self { - inner_cell: RefCell::new(value) - } - } - - /// 独占访问 - /// 当已被借用时访问会Panic - pub fn exclusive_access(&self) -> RefMut<'_, T> { - self.inner_cell.borrow_mut() - } -} \ No newline at end of file diff --git a/os/src/syscall.rs b/os/src/syscall.rs new file mode 100644 index 0000000..91cf8d9 --- /dev/null +++ b/os/src/syscall.rs @@ -0,0 +1,18 @@ +use crate::syscall::fs::sys_write; +use crate::syscall::process::sys_exit; + +mod fs; +mod process; + +const SYSCALL_WRITE: usize = 64; +const SYSCALL_EXIT: usize = 93; + +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), + _ => { + panic!("Unsupported syscall: {}", syscall_id) + } + } +} diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs new file mode 100644 index 0000000..859e998 --- /dev/null +++ b/os/src/syscall/fs.rs @@ -0,0 +1,17 @@ +use crate::print; + +const STDOUT_FD: usize = 1; + +pub fn sys_write(fd: usize, buffer: *const u8, len: usize) -> usize { + match fd { + STDOUT_FD => { + let slice = unsafe { core::slice::from_raw_parts(buffer, len) }; + let str = core::str::from_utf8(slice).unwrap(); + print!("{}", str); + len as usize + } + _ => { + panic!("Unsupported file descriptor in sys_write"); + } + } +} diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs new file mode 100644 index 0000000..b6ec127 --- /dev/null +++ b/os/src/syscall/process.rs @@ -0,0 +1,7 @@ +use crate::batch::run_next_application; +use crate::println; + +pub fn sys_exit(exit_state: i32) -> ! { + println!("[kernel] Application exited with code {}.", exit_state); + run_next_application() +} \ No newline at end of file diff --git a/os/src/trap.asm b/os/src/trap.asm new file mode 100644 index 0000000..3b3811d --- /dev/null +++ b/os/src/trap.asm @@ -0,0 +1,67 @@ +.altmacro +.macro SAVE_GP n + sd x\n, \n*8(sp) +.endm +.macro LOAD_GP n + ld x\n, \n*8(sp) +.endm + + .section .text + .global __alltraps + .global __restore + .align 2 +__alltraps: + csrrw sp, sscratch, sp + # now sp->kernel stack, sscratch->user stack + # allocate a TrapContext on kernel stack + addi sp, sp, -34*8 + # save general-purpose registers + sd x1, 1*8(sp) + # skip sp(x2), we will save it later + sd x3, 3*8(sp) + # skip tp(x4), application does not use it + # save x5~x31 + .set n, 5 + .rept 27 + SAVE_GP %n + .set n, n+1 + .endr + # we can use t0/t1/t2 freely, because they were saved on kernel stack + csrr t0, sstatus + csrr t1, sepc + sd t0, 32*8(sp) + sd t1, 33*8(sp) + # read user stack from sscratch and save it on the kernel stack + csrr t2, sscratch + sd t2, 2*8(sp) + # set input argument of trap_handler(cx: &mut TrapContext) + mv a0, sp + 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) + ld t1, 33*8(sp) + ld t2, 2*8(sp) + csrw sstatus, t0 + csrw sepc, t1 + csrw sscratch, t2 + # restore general-purpuse registers except sp/tp + ld x1, 1*8(sp) + ld x3, 3*8(sp) + .set n, 5 + .rept 27 + LOAD_GP %n + .set n, n+1 + .endr + # release TrapContext on kernel stack + addi sp, sp, 34*8 + # now sp->kernel stack, sscratch->user stack + csrrw sp, sscratch, sp + sret \ No newline at end of file diff --git a/os/src/trap.rs b/os/src/trap.rs new file mode 100644 index 0000000..d989dd4 --- /dev/null +++ b/os/src/trap.rs @@ -0,0 +1,47 @@ +use core::arch::global_asm; +use riscv::register::{ + mtvec::TrapMode, + scause::{self, Exception, Trap}, + stval, stvec +}; +use crate::batch::run_next_application; +use crate::println; +use crate::syscall::syscall; +use crate::trap::context::TrapContext; + +pub mod context; + +global_asm!(include_str!("trap.asm")); + +pub fn init() { + extern "C" { fn __alltraps(); } + unsafe { + stvec::write(__alltraps as usize, TrapMode::Direct); + } +} + +#[no_mangle] +pub fn trap_handler(context: &mut TrapContext) -> &mut TrapContext { + let scause = scause::read(); + let stval = stval::read(); + + match scause.cause() { + Trap::Exception(Exception::UserEnvCall) => { + context.sepc += 4; + context.x[10] = syscall(context.x[17], [context.x[10], context.x[11], context.x[12]]); + }, + Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) => { + println!("[kernel] PageFault in application, kernel will kill it."); + run_next_application(); + }, + Trap::Exception(Exception::IllegalInstruction) => { + println!("[kernel] Illegal instruction in application, kernel will kill it."); + run_next_application(); + }, + _ => { + panic!("[Kernel] Unsupported trap: {:?}, stval = {:#x}!", scause.cause(), stval); + } + } + + context +} \ No newline at end of file diff --git a/os/src/trap/context.rs b/os/src/trap/context.rs new file mode 100644 index 0000000..8ef2412 --- /dev/null +++ b/os/src/trap/context.rs @@ -0,0 +1,29 @@ +use riscv::register::sstatus::{self, Sstatus, SPP}; + +#[repr(C)] +pub struct TrapContext { + pub x: [usize; 32], + pub s_status: Sstatus, + pub sepc: usize +} + +impl TrapContext { + pub unsafe fn init_application_context(entry: usize, sp: usize) -> Self { + let sstatus = sstatus::read(); + sstatus::set_spp(SPP::User); + let mut context = Self { + x: [0; 32], + s_status: sstatus, + sepc: entry + }; + + context.set_sp(sp); + context + } + + pub fn set_sp(&mut self, sp: usize) { + // x2 is stack pointer register + self.x[2] = sp; + } +} + -- 2.45.1 From 47ba1d271ab3f1e11707e664f721e2aa1aeb704f Mon Sep 17 00:00:00 2001 From: jackfiled Date: Fri, 19 Jul 2024 11:41:17 +0800 Subject: [PATCH 3/4] fix: format code --- os/build.rs | 2 +- os/src/batch.rs | 52 ++++++++++++++++------------- os/src/console.rs | 4 +-- os/src/main.rs | 12 +++---- os/src/sbi.rs | 4 +-- os/src/sync.rs | 2 +- os/src/sync/single_cell.rs | 8 ++--- os/src/syscall/process.rs | 2 +- os/src/trap.asm | 2 -- os/src/trap.rs | 30 ++++++++++------- os/src/trap/context.rs | 5 ++- os/src/utils.rs | 14 ++++---- user/src/bin/hello_world.rs | 2 +- user/src/bin/illegal_instruction.rs | 2 +- user/src/bin/power.rs | 2 +- user/src/bin/store_fault.rs | 2 +- user/src/console.rs | 4 +-- user/src/lib.rs | 3 +- user/src/syscall.rs | 4 +-- user/src/utils.rs | 15 +++++---- 20 files changed, 88 insertions(+), 83 deletions(-) diff --git a/os/build.rs b/os/build.rs index 5d0c988..3cd2e06 100644 --- a/os/build.rs +++ b/os/build.rs @@ -53,4 +53,4 @@ app_{0}_end:"#, )?; } Ok(()) -} \ No newline at end of file +} diff --git a/os/src/batch.rs b/os/src/batch.rs index 2698466..2b09e78 100644 --- a/os/src/batch.rs +++ b/os/src/batch.rs @@ -3,6 +3,7 @@ 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; @@ -26,14 +27,13 @@ lazy_static! { 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 - ); + 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 + start_addresses, } }) }; @@ -44,10 +44,12 @@ impl AppManager { 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]); + log_information!( + "[kernel] Application_{} ({:#x} -> {:#x})", + i, + self.start_addresses[i], + self.start_addresses[i + 1] + ); } } @@ -66,19 +68,14 @@ impl AppManager { log_information!("[kernel] Loading application_{}...", app_id); - core::slice::from_raw_parts_mut( - APP_BASE_ADDRESS as *mut u8, - APP_SIZE_LIMIT - ).fill(0); + 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() + 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); // 保证指令缓存的更新 @@ -92,7 +89,7 @@ const KERNEL_STACK_SIZE: usize = 4096 * 2; #[repr(align(4096))] struct UserStack { - data: [u8; USER_STACK_SIZE] + data: [u8; USER_STACK_SIZE], } impl UserStack { @@ -103,7 +100,7 @@ impl UserStack { #[repr(align(4096))] struct KernelStack { - data: [u8; KERNEL_STACK_SIZE] + data: [u8; KERNEL_STACK_SIZE], } impl KernelStack { @@ -120,8 +117,12 @@ impl KernelStack { } } -static KERNEL_STACK: KernelStack = KernelStack { data: [0; KERNEL_STACK_SIZE]}; -static USER_STACK: UserStack = UserStack { data: [0; USER_STACK_SIZE]}; +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(); @@ -131,6 +132,11 @@ pub fn 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); } @@ -147,12 +153,10 @@ pub fn run_next_application() -> ! { unsafe { let context_address = KERNEL_STACK.push_context(TrapContext::init_application_context( APP_BASE_ADDRESS, - USER_STACK.get_sp() + USER_STACK.get_sp(), )) as *const _ as usize; __restore(context_address); unreachable!() } } - - diff --git a/os/src/console.rs b/os/src/console.rs index 7d2b0cf..e88704f 100644 --- a/os/src/console.rs +++ b/os/src/console.rs @@ -1,6 +1,6 @@ +use crate::sbi::console_print; use core::fmt; use core::fmt::Write; -use crate::sbi::console_print; struct Stdout; @@ -65,4 +65,4 @@ macro_rules! log_trace { ($fmt: literal $(, $($arg: tt)+)?) => { $crate::console::print(format_args!(concat!("\x1b[90m" ,concat!($fmt, "\x1b[0m\n")) $(, $($arg)+)?)); } -} \ No newline at end of file +} diff --git a/os/src/main.rs b/os/src/main.rs index af83c41..c2e2c42 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -1,21 +1,20 @@ #![no_std] #![no_main] -use core::arch::global_asm; use crate::utils::clear_bss; +use core::arch::global_asm; -mod utils; -mod sbi; -mod console; mod batch; +mod console; +mod sbi; mod sync; -mod trap; mod syscall; +mod trap; +mod utils; global_asm!(include_str!("entry.asm")); global_asm!(include_str!("link_app.asm")); - #[no_mangle] fn rust_main() -> ! { clear_bss(); @@ -24,4 +23,3 @@ fn rust_main() -> ! { batch::print_app_information(); batch::run_next_application(); } - diff --git a/os/src/sbi.rs b/os/src/sbi.rs index 322fb0b..73c351c 100644 --- a/os/src/sbi.rs +++ b/os/src/sbi.rs @@ -4,7 +4,7 @@ pub fn console_print(c: usize) { } pub fn shutdown(failure: bool) -> ! { - use sbi_rt::{system_reset, Shutdown, NoReason, SystemFailure}; + use sbi_rt::{system_reset, NoReason, Shutdown, SystemFailure}; if failure { system_reset(Shutdown, SystemFailure); @@ -13,4 +13,4 @@ pub fn shutdown(failure: bool) -> ! { } unreachable!() -} \ No newline at end of file +} diff --git a/os/src/sync.rs b/os/src/sync.rs index 5c76622..01d434f 100644 --- a/os/src/sync.rs +++ b/os/src/sync.rs @@ -1 +1 @@ -pub mod single_cell; \ No newline at end of file +pub mod single_cell; diff --git a/os/src/sync/single_cell.rs b/os/src/sync/single_cell.rs index c647797..f6687cd 100644 --- a/os/src/sync/single_cell.rs +++ b/os/src/sync/single_cell.rs @@ -2,17 +2,15 @@ use core::cell::{RefCell, RefMut}; /// 只能在单核场景下保持安全的屑RefCell pub struct SingleCell { - inner: RefCell + inner: RefCell, } -unsafe impl Sync for SingleCell { - -} +unsafe impl Sync for SingleCell {} impl SingleCell { pub unsafe fn new(value: T) -> SingleCell { SingleCell { - inner: RefCell::new(value) + inner: RefCell::new(value), } } diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index b6ec127..619c197 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -4,4 +4,4 @@ use crate::println; pub fn sys_exit(exit_state: i32) -> ! { println!("[kernel] Application exited with code {}.", exit_state); run_next_application() -} \ No newline at end of file +} diff --git a/os/src/trap.asm b/os/src/trap.asm index 3b3811d..7ca7154 100644 --- a/os/src/trap.asm +++ b/os/src/trap.asm @@ -38,8 +38,6 @@ __alltraps: mv a0, sp call trap_handler - - __restore: # case1: start running app by __restore # case2: back to U after handling trap diff --git a/os/src/trap.rs b/os/src/trap.rs index d989dd4..e7aec3e 100644 --- a/os/src/trap.rs +++ b/os/src/trap.rs @@ -1,20 +1,22 @@ -use core::arch::global_asm; -use riscv::register::{ - mtvec::TrapMode, - scause::{self, Exception, Trap}, - stval, stvec -}; 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, +}; pub mod context; global_asm!(include_str!("trap.asm")); pub fn init() { - extern "C" { fn __alltraps(); } + extern "C" { + fn __alltraps(); + } unsafe { stvec::write(__alltraps as usize, TrapMode::Direct); } @@ -29,19 +31,23 @@ pub fn trap_handler(context: &mut TrapContext) -> &mut TrapContext { Trap::Exception(Exception::UserEnvCall) => { context.sepc += 4; context.x[10] = syscall(context.x[17], [context.x[10], context.x[11], context.x[12]]); - }, + } Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) => { println!("[kernel] PageFault in application, kernel will kill it."); run_next_application(); - }, + } Trap::Exception(Exception::IllegalInstruction) => { println!("[kernel] Illegal instruction in application, kernel will kill it."); run_next_application(); - }, + } _ => { - panic!("[Kernel] Unsupported trap: {:?}, stval = {:#x}!", scause.cause(), stval); + panic!( + "[Kernel] Unsupported trap: {:?}, stval = {:#x}!", + scause.cause(), + stval + ); } } context -} \ No newline at end of file +} diff --git a/os/src/trap/context.rs b/os/src/trap/context.rs index 8ef2412..c467b0a 100644 --- a/os/src/trap/context.rs +++ b/os/src/trap/context.rs @@ -4,7 +4,7 @@ use riscv::register::sstatus::{self, Sstatus, SPP}; pub struct TrapContext { pub x: [usize; 32], pub s_status: Sstatus, - pub sepc: usize + pub sepc: usize, } impl TrapContext { @@ -14,7 +14,7 @@ impl TrapContext { let mut context = Self { x: [0; 32], s_status: sstatus, - sepc: entry + sepc: entry, }; context.set_sp(sp); @@ -26,4 +26,3 @@ impl TrapContext { self.x[2] = sp; } } - diff --git a/os/src/utils.rs b/os/src/utils.rs index 9d5fdad..72f9175 100644 --- a/os/src/utils.rs +++ b/os/src/utils.rs @@ -1,17 +1,19 @@ use core::panic::PanicInfo; -use crate::println; + +use crate::log_error; use crate::sbi::shutdown; #[panic_handler] fn panic(info: &PanicInfo) -> ! { if let Some(location) = info.location() { - println!("Panicked at {}:{} {}.", + log_error!( + "Panicked at {}:{} {}.", location.file(), location.line(), info.message() ); } else { - println!("Panicked: {}.", info.message()); + log_error!("Panicked: {}.", info.message()); } shutdown(true) @@ -24,8 +26,6 @@ pub fn clear_bss() { } for m in sbss as usize..ebss as usize { - unsafe { - (m as *mut u8).write_volatile(0) - } + unsafe { (m as *mut u8).write_volatile(0) } } -} \ No newline at end of file +} diff --git a/user/src/bin/hello_world.rs b/user/src/bin/hello_world.rs index 5329f79..f457094 100644 --- a/user/src/bin/hello_world.rs +++ b/user/src/bin/hello_world.rs @@ -9,4 +9,4 @@ fn main() -> i32 { println!("Hello, world!"); 0 -} \ No newline at end of file +} diff --git a/user/src/bin/illegal_instruction.rs b/user/src/bin/illegal_instruction.rs index cbd3210..04dac37 100644 --- a/user/src/bin/illegal_instruction.rs +++ b/user/src/bin/illegal_instruction.rs @@ -14,4 +14,4 @@ fn main() -> i32 { asm!("sret"); } 0 -} \ No newline at end of file +} diff --git a/user/src/bin/power.rs b/user/src/bin/power.rs index 54fde24..f628f34 100644 --- a/user/src/bin/power.rs +++ b/user/src/bin/power.rs @@ -24,4 +24,4 @@ fn main() -> i32 { } println!("Test power OK!"); 0 -} \ No newline at end of file +} diff --git a/user/src/bin/store_fault.rs b/user/src/bin/store_fault.rs index aedf88b..f8023eb 100644 --- a/user/src/bin/store_fault.rs +++ b/user/src/bin/store_fault.rs @@ -12,4 +12,4 @@ fn main() -> i32 { core::ptr::null_mut::().write_volatile(0); } 0 -} \ No newline at end of file +} diff --git a/user/src/console.rs b/user/src/console.rs index 0d41582..253fb41 100644 --- a/user/src/console.rs +++ b/user/src/console.rs @@ -1,5 +1,5 @@ -use core::fmt::Write; use crate::syscall::sys_write; +use core::fmt::Write; struct Stdout; @@ -29,4 +29,4 @@ macro_rules! println { ($fmt: literal $(, $($arg: tt)+)?) => { $crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?)); } -} \ No newline at end of file +} diff --git a/user/src/lib.rs b/user/src/lib.rs index 9c42c3f..fbe8862 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -3,8 +3,8 @@ use crate::syscall::{sys_exit, sys_write}; -mod utils; mod syscall; +mod utils; #[macro_use] pub mod console; @@ -28,4 +28,3 @@ pub fn write(fd: usize, buf: &[u8]) -> isize { pub fn exit(exit_code: i32) -> isize { sys_exit(exit_code) } - diff --git a/user/src/syscall.rs b/user/src/syscall.rs index b4a305d..6025b8e 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -4,7 +4,7 @@ const SYSCALL_WRITE: usize = 64; const SYSCALL_EXIT: usize = 93; fn syscall(id: usize, args: [usize; 3]) -> isize { - let mut result : isize; + let mut result: isize; unsafe { asm!( @@ -25,4 +25,4 @@ 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]) -} \ No newline at end of file +} diff --git a/user/src/utils.rs b/user/src/utils.rs index 85b7f0f..2644afe 100644 --- a/user/src/utils.rs +++ b/user/src/utils.rs @@ -1,5 +1,5 @@ -use core::panic::PanicInfo; use crate::println; +use core::panic::PanicInfo; pub fn clear_bss() { extern "C" { @@ -9,9 +9,7 @@ pub fn clear_bss() { } for i in start_bss as usize..end_bss as usize { - unsafe { - (i as *mut u8).write_volatile(0) - } + unsafe { (i as *mut u8).write_volatile(0) } } } @@ -20,10 +18,15 @@ fn panic_handler(info: &PanicInfo) -> ! { let message = info.message(); if let Some(location) = info.location() { - println!("Panicked at {}:{} {}", location.file(), location.line(), message); + println!( + "Panicked at {}:{} {}", + location.file(), + location.line(), + message + ); } else { println!("Panicked: {}", message); } unreachable!() -} \ No newline at end of file +} -- 2.45.1 From e27d935b9dd34eb43ead8912a09de9e1f2b31dc6 Mon Sep 17 00:00:00 2001 From: jackfiled Date: Fri, 19 Jul 2024 13:49:53 +0800 Subject: [PATCH 4/4] add README.md --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..12c8596 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Rust RISC-V 操作系统 + +按照[rCore](https://rcore-os.cn/rCore-Tutorial-Book-v3/chapter0/index.html)的教程进行开发。 + +## 目前进度 + +- [x] 基本执行环境 +- [x] 批处理系统 +- [ ] 多道程序和分时系统 +- [ ] 地址空间 +- [ ] 文件系统 +- [ ] 进程间通信和I/O重定向 +- [ ] 并发 +- [ ] I/O设备管理 + -- 2.45.1