add AppManager
This commit is contained in:
parent
8eba5a3d9b
commit
c47d636498
16
os/Cargo.lock
generated
16
os/Cargo.lock
generated
|
@ -2,10 +2,20 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
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]]
|
[[package]]
|
||||||
name = "os"
|
name = "os"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
"sbi-rt",
|
"sbi-rt",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -27,6 +37,12 @@ dependencies = [
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
|
@ -5,3 +5,4 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sbi-rt = { version = "0.0.2", features = ["legacy"] }
|
sbi-rt = { version = "0.0.2", features = ["legacy"] }
|
||||||
|
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
|
||||||
|
|
56
os/build.rs
Normal file
56
os/build.rs
Normal file
|
@ -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(())
|
||||||
|
}
|
1
os/src/.gitignore
vendored
Normal file
1
os/src/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
link_app.asm
|
86
os/src/batch.rs
Normal file
86
os/src/batch.rs
Normal file
|
@ -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<AppManager> = 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,8 +7,12 @@ use crate::utils::clear_bss;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod sbi;
|
mod sbi;
|
||||||
mod console;
|
mod console;
|
||||||
|
mod batch;
|
||||||
|
mod sync;
|
||||||
|
|
||||||
global_asm!(include_str!("entry.asm"));
|
global_asm!(include_str!("entry.asm"));
|
||||||
|
global_asm!(include_str!("link_app.asm"));
|
||||||
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn rust_main() -> ! {
|
fn rust_main() -> ! {
|
||||||
|
|
1
os/src/sync.rs
Normal file
1
os/src/sync.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
mod unsafe_cell;
|
24
os/src/sync/unsafe_cell.rs
Normal file
24
os/src/sync/unsafe_cell.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use core::cell::{RefCell, RefMut};
|
||||||
|
|
||||||
|
/// 只能在单核场景下保持安全的屑RefCell
|
||||||
|
struct UnsafeCell<T> {
|
||||||
|
inner_cell: RefCell<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T> Sync for UnsafeCell<T> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> UnsafeCell<T> {
|
||||||
|
pub unsafe fn new(value: T) -> UnsafeCell<T> {
|
||||||
|
Self {
|
||||||
|
inner_cell: RefCell::new(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 独占访问
|
||||||
|
/// 当已被借用时访问会Panic
|
||||||
|
pub fn exclusive_access(&self) -> RefMut<'_, T> {
|
||||||
|
self.inner_cell.borrow_mut()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user