Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 0 additions & 5 deletions Cargo.lock

This file was deleted.

File renamed without changes.
140 changes: 140 additions & 0 deletions os/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml → os/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
[package]
name = "blog_os"
name = "r_core"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }

# cargo build
[profile.dev]
Expand Down
3 changes: 1 addition & 2 deletions Makefile → os/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

QEMU = qemu-system-riscv64
TARGET = riscv64gc-unknown-none-elf
BIOS = bootloader/rustsbi-qemu.bin
MACHINE = virt
OS_NAME = os.bin
OS_ADDR = 0x80200000

build:
cargo build --release
rust-objcopy --strip-all target/riscv64gc-unknown-none-elf/release/blog_os -O binary target/riscv64gc-unknown-none-elf/release/os.bin
rust-objcopy --strip-all target/riscv64gc-unknown-none-elf/release/r_core -O binary target/riscv64gc-unknown-none-elf/release/os.bin

qemu:
$(QEMU) -m 256M -M $(MACHINE) -nographic -kernel target/riscv64gc-unknown-none-elf/release/os.bin
Expand Down
150 changes: 150 additions & 0 deletions os/src/batch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use crate::sync::UPSafeCell;
use crate::trap::TrapContext;
use core::arch::asm;
use lazy_static::*;

const USER_STACK_SIZE: usize = 4096 * 2;
const KERNEL_STACK_SIZE: usize = 4096 * 2;
const MAX_APP_NUM: usize = 16;
const APP_BASE_ADDRESS: usize = 0x80400000;
const APP_SIZE_LIMIT: usize = 0x20000;

//we make struct structure is same as the sturc in C.
#[repr(align(4096))]
struct KernelStack {
data: [u8; KERNEL_STACK_SIZE],
}

#[repr(align(4096))]
struct UserStack {
data: [u8; USER_STACK_SIZE],
}

static KERNEL_STACK: KernelStack = KernelStack {
data: [0; KERNEL_STACK_SIZE],
};

static USER_STACK: UserStack = UserStack {
data: [0; USER_STACK_SIZE],
};

impl KernelStack {
//get stack bottom
fn get_sp(&self) -> usize {
self.data.as_ptr() as usize + KERNEL_STACK_SIZE
}

//spare a area for context and return it
pub fn push_context(&self, cx: TrapContext) -> &'static mut TrapContext {
let cx_ptr = (self.get_sp() - core::mem::size_of::<TrapContext>()) as *mut TrapContext;
unsafe {
*cx_ptr = cx;
}
unsafe { cx_ptr.as_mut().unwrap() }
}
}

impl UserStack {
fn get_sp(&self) -> usize {
self.data.as_ptr() as usize + USER_STACK_SIZE
}
}

//a array to manage all apps
struct AppManager {
num_app: usize,
current_app: usize,
app_start: [usize; MAX_APP_NUM + 1],
}

impl AppManager {
//walk through all apps,
pub fn print_app_info(&self) {
println!("[kernel] num_app = {}", self.num_app);
for i in 0..self.num_app {
println!(
"[kernel] app_{} [{:#x}, {:#x})",
i,
self.app_start[i],
self.app_start[i+1]
);
}
}

//copy app to dest
unsafe fn load_app(&self, app_id: usize){
if app_id >= self.num_app {
println!("All application completed!");
use crate::board::QEMUExit;
crate::board::QEMU_EXIT_HANDLE.exit_success();
}
println!("[kernel] Loading app_{}", app_id);
asm!("fence.i");
core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, APP_SIZE_LIMIT).fill(0);
let app_src = core::slice::from_raw_parts(
self.app_start[app_id] as *const u8,
self.app_start[app_id + 1] - self.app_start[app_id],
);
let app_dst = core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, app_src.len());
app_dst.copy_from_slice(app_src);
}

pub fn get_current_app(&self) -> usize {
self.current_app
}

pub fn move_to_next_app(&mut self) {
self.current_app += 1;
}
}

//defer the initialization to the first time to using it.
lazy_static! {
//init manager according apps' memory layout
static ref APP_MANAGER: UPSafeCell<AppManager> = unsafe {
UPSafeCell::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 app_start:[usize; MAX_APP_NUM+1] = [0; MAX_APP_NUM+1];
let app_start_raw: &[usize] = core::slice::from_raw_parts(num_app_ptr.add(1), num_app+1);
app_start[..=num_app].copy_from_slice(app_start_raw);
AppManager {
num_app,
current_app: 0,
app_start,
}
})
};
}

pub fn init() {
print_app_info();
}

pub fn print_app_info(){
APP_MANAGER.exclusive_access().print_app_info();
}

// use sret to start
pub fn run_next_app() -> !{
let mut app_manager = APP_MANAGER.exclusive_access();
let current_app = app_manager.get_current_app();
unsafe{
app_manager.load_app(current_app);
}
app_manager.move_to_next_app();
drop(app_manager);
extern "C" {
fn __restore(cx_addr: usize);
}
unsafe{
__restore(KERNEL_STACK.push_context(TrapContext::app_init_context(
APP_BASE_ADDRESS,
USER_STACK.get_sp(),
)) as *const _ as usize);
}
panic!("Unreachable in batch::run_current_app!");
}
Loading