feat: 批处理操作系统 #1

Merged
jackfiled merged 4 commits from feat-ch2 into master 2024-07-19 13:52:36 +08:00
8 changed files with 189 additions and 0 deletions
Showing only changes of commit c47d636498 - Show all commits

16
os/Cargo.lock generated
View File

@ -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"

View File

@ -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
View 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
View File

@ -0,0 +1 @@
link_app.asm

86
os/src/batch.rs Normal file
View 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");
}
}

View File

@ -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
View File

@ -0,0 +1 @@
mod unsafe_cell;

View 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()
}
}