Skip to content
This repository was archived by the owner on Aug 12, 2026. It is now read-only.
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
> **NOTE**
>
> *This project is at an extremely early stage of development — almost nothing has been implemented yet, and everything is immature. The README.md was also written by AI; it looks impressive but actual functionality is far from complete. Please do not take this early, rough project too seriously. I will update this notice myself once a stable release is ready.*
> *{Intro:Multi-architecture(now only riscv64gc on qemu-virt first, do it bad first, then reconstruct later) toykernel, with "framekernel" target inspired by "Asterinas",with an "Alpine-like" userland target(musl + BusyBox).}This project is at an extremely early stage of development — almost nothing has been implemented yet, and everything is immature. The README.md was also written by AI; it looks impressive but actual functionality is far from complete. Please do not take this early, rough project too seriously. I will update this notice myself once a stable release is ready.*

# racho

Expand Down
61 changes: 61 additions & 0 deletions framework/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use std::fs::{File, read_dir};
use std::io::{Result, Write};
use std::path::PathBuf;

fn main() {
let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let target_dir = manifest_dir
.parent()
.unwrap()
.join("target")
.join("riscv64gc-unknown-none-elf")
.join("release");

let target_path = target_dir.to_string_lossy().into_owned();
insert_app_data(&target_path).unwrap();
}

fn insert_app_data(target_path: &str) -> Result<()> {
let mut f = File::create("src/link_app.S").unwrap();
let mut apps: Vec<_> = read_dir("../user_lib/src/bin")
.unwrap()
.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 "{1}/{2}"
app_{0}_end:"#,
idx, target_path, app
)?;
}
Ok(())
}
7 changes: 7 additions & 0 deletions kernel/src/linker-qemu.ld → framework/linker-qemu.ld
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ SECTIONS
*(.sdata .sdata.*)
}

. = ALIGN(8);
.init_array : {
__init_array_start = .;
KEEP(*(.init_array .init_array.*))
__init_array_end = .;
}

. = ALIGN(4K);
edata = .;
sbss_with_stack = .;
Expand Down
76 changes: 76 additions & 0 deletions framework/src/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ unsafe extern "C" {
fn sbss_with_stack();
fn ekernel();
fn strampoline();
fn _num_app();
fn __alltraps();
fn __restore();
}

pub fn clear_bss() {
Expand Down Expand Up @@ -41,3 +44,76 @@ define_addr_getter!(ebss_addr, ebss);
define_addr_getter!(sbss_with_stack_addr, sbss_with_stack);
define_addr_getter!(ekernel_addr, ekernel);
define_addr_getter!(strampoline_addr, strampoline);

pub fn get_num_app() -> usize {
unsafe { (_num_app as *const () as *const usize).read_volatile() }
}

pub fn get_app_data(app_id: usize) -> &'static [u8] {
let num_app = get_num_app();
let num_app_ptr = _num_app as *const () as *const usize;
let app_start = unsafe { core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1) };
assert!(app_id < num_app);
unsafe {
core::slice::from_raw_parts(
app_start[app_id] as *const u8,
app_start[app_id + 1] - app_start[app_id],
)
}
}

pub fn alltraps_addr() -> usize {
__alltraps as *const () as usize
}

pub fn restore_addr() -> usize {
__restore as *const () as usize
}

pub trait Kernel {
fn main() -> !;
}

pub fn boot<K: Kernel>() -> ! {
clear_bss();
K::main()
}

#[macro_export]
macro_rules! register_kernel {
($kernel:ty) => {
#[used]
#[unsafe(link_section = ".init_array")]
static _FRAMEWORK_BOOT_KERNEL: unsafe extern "C" fn() = {
unsafe extern "C" fn __framework_boot() {
$crate::boot::<$kernel>();
}
__framework_boot
};
};
}

#[unsafe(no_mangle)]
pub fn rust_main() -> ! {
clear_bss();
execute_init_array();
panic!("No kernel entry registered in .init_array");
}

unsafe extern "C" {
fn __init_array_start();
fn __init_array_end();
}

fn execute_init_array() {
let start = __init_array_start as *const () as *const usize;
let end = __init_array_end as *const () as *const usize;
let count = (end as usize - start as usize) / size_of::<usize>();
for i in 0..count {
let func: unsafe extern "C" fn() =
unsafe { core::mem::transmute(*start.add(i)) };
unsafe {
func();
}
}
}
File renamed without changes.
22 changes: 17 additions & 5 deletions framework/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
#![no_std]

use core::arch::global_asm;

global_asm!(include_str!("entry.asm"));
global_asm!(include_str!("link_app.S"));
global_asm!(include_str!("trap/trap.S"));

mod boot;
mod memory;
mod sync;
mod task;
mod trap;

pub use boot::{
clear_bss, ebss_addr, edata_addr, ekernel_addr, erodata_addr, etext_addr, sbss_addr,
sbss_with_stack_addr, sdata_addr, skernel_addr, srodata_addr, stext_addr, strampoline_addr,
Kernel, alltraps_addr, boot, clear_bss, ebss_addr, edata_addr, ekernel_addr, erodata_addr,
etext_addr, get_app_data, get_num_app, restore_addr, sbss_addr, sbss_with_stack_addr,
sdata_addr, skernel_addr, srodata_addr, stext_addr, strampoline_addr,
};
pub use memory::{
KERNEL_HEAP_SIZE, heap_region, init_heap_allocator, phys_to_byte_slice, phys_to_ref,
phys_to_slice, sfence_vma, write_satp,
KERNEL_HEAP_SIZE, fence_i, heap_region, init_heap_allocator, phys_to_byte_slice, phys_to_ref,
phys_to_slice, sfence_vma, write_satp, zero_memory,
};
pub use trap::{set_sie_enable_stimer, set_stvec};
pub use sync::UPSafeCell;
pub use task::{TaskContext, context_switch};
pub use trap::{restore_to_user, set_sie_enable_stimer, set_stvec};
39 changes: 39 additions & 0 deletions framework/src/link_app.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

.align 3
.section .data
.global _num_app
_num_app:
.quad 4
.quad app_0_start
.quad app_1_start
.quad app_2_start
.quad app_3_start
.quad app_3_end

.section .data
.global app_0_start
.global app_0_end
app_0_start:
.incbin "/home/shyweeds/Projects/racho/target/riscv64gc-unknown-none-elf/release/00power_3"
app_0_end:

.section .data
.global app_1_start
.global app_1_end
app_1_start:
.incbin "/home/shyweeds/Projects/racho/target/riscv64gc-unknown-none-elf/release/01power_5"
app_1_end:

.section .data
.global app_2_start
.global app_2_end
app_2_start:
.incbin "/home/shyweeds/Projects/racho/target/riscv64gc-unknown-none-elf/release/02power_7"
app_2_end:

.section .data
.global app_3_start
.global app_3_end
app_3_start:
.incbin "/home/shyweeds/Projects/racho/target/riscv64gc-unknown-none-elf/release/03sleep"
app_3_end:
14 changes: 14 additions & 0 deletions framework/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,17 @@ pub fn sfence_vma() {
asm!("sfence.vma");
}
}

pub fn zero_memory(phys_addr: usize, len: usize) {
for addr in phys_addr..phys_addr + len {
unsafe {
(addr as *mut u8).write_volatile(0);
}
}
}

pub fn fence_i() {
unsafe {
asm!("fence.i");
}
}
12 changes: 5 additions & 7 deletions kernel/src/sync/up.rs → framework/src/sync.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! Uniprocessor interior mutability primitives

//! only guaranteed in uniprocessor env
use core::cell::{RefCell, RefMut};

pub struct UPSafeCell<T> {
Expand All @@ -9,14 +8,13 @@ pub struct UPSafeCell<T> {
unsafe impl<T> Sync for UPSafeCell<T> {}

impl<T> UPSafeCell<T> {
/// User is responsible to guarantee that inner struct is only used in
/// uniprocessor.
pub unsafe fn new(value: T) -> Self {
/// only used in the uniprocessor please
pub fn new(val: T) -> Self {
Self {
inner: RefCell::new(value),
inner: RefCell::new(val),
}
}
/// Exclusive access inner data in UPSafeCell. Panic if the data has been borrowed
/// exclusive access inner data in UPSafeCell. Panic if the data has been borrowed
pub fn exclusive_access(&self) -> RefMut<'_, T> {
self.inner.borrow_mut()
}
Expand Down
17 changes: 17 additions & 0 deletions framework/src/task.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
mod context;

pub use context::TaskContext;
use core::arch::global_asm;

global_asm!(include_str!("task/switch.S"));

unsafe extern "C" {
unsafe fn __switch(current_taskcx_ptr: *mut (), next_taskcx_ptr: *const ());
}

// in the core of framework, we can never depend on structs in kernel, or it will be a mess
pub fn context_switch(current_taskcx_ptr: *mut TaskContext, next_taskcx_ptr: *const TaskContext) {
unsafe {
__switch(current_taskcx_ptr as *mut (), next_taskcx_ptr as *const ());
}
}
15 changes: 10 additions & 5 deletions kernel/src/task/context.rs → framework/src/task/context.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//! Implementation of [`TaskContext`]

use crate::trap::trap_return;

/// Task Context
#[derive(Copy, Clone)]
#[repr(C)]
Expand All @@ -25,10 +23,17 @@ impl TaskContext {
}

/// set Task Context{__restore ASM function: trap_return, sp: kstack_ptr, s: s_0..12}
pub fn goto_trap_return(kstack_ptr: usize) -> Self {
// pub fn goto_trap_return(kstack_ptr: usize) -> Self {
// Self {
// ra: trap_return as *const () as usize,
// sp: kstack_ptr,
// s: [0; 12],
// }
// }
pub fn new(return_addr: usize, kernel_sp: usize) -> Self {
Self {
ra: trap_return as *const () as usize,
sp: kstack_ptr,
ra: return_addr,
sp: kernel_sp,
s: [0; 12],
}
}
Expand Down
File renamed without changes.
18 changes: 18 additions & 0 deletions framework/src/trap.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use core::arch::asm;
use riscv::{
self,
register::{sie, stvec, utvec::TrapMode},
};

pub fn set_stvec(addr: usize, mode: TrapMode) {
unsafe {
stvec::write(addr, mode);
Expand All @@ -12,3 +14,19 @@ pub fn set_sie_enable_stimer() {
sie::set_stimer();
}
}

pub fn restore_to_user(trap_cx_ptr: usize, user_satp: usize, trampoline_base: usize) -> ! {
let alltraps = crate::boot::alltraps_addr();
let restore = crate::boot::restore_addr();
let restore_va = restore - alltraps + trampoline_base;
unsafe {
asm!(
"fence.i",
"jr {restore_va}",
restore_va = in(reg) restore_va,
in("a0") trap_cx_ptr,
in("a1") user_satp,
options(noreturn)
);
}
}
File renamed without changes.
Loading
Loading