feat: 批处理操作系统 #1
16
os/Cargo.lock
generated
16
os/Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"] }
|
||||
|
|
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 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() -> ! {
|
||||
|
|
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