From c47d636498ba5bd3199845fb0a01c6ec228ac61f Mon Sep 17 00:00:00 2001 From: jackfiled Date: Wed, 17 Jul 2024 18:12:33 +0800 Subject: [PATCH] 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