From 8bbe1fc8f8177a2d0cec4ef2a186391ff8beb20d Mon Sep 17 00:00:00 2001 From: tinyblinker <2149934895@qq.com> Date: Tue, 21 Jul 2026 15:11:07 +0800 Subject: [PATCH 1/5] remove mod.rs, use newer methods in all cases --- Cargo.lock | 4 ++ Cargo.toml | 2 - framework/src/boot.rs | 22 ++++++++++ framework/src/lib.rs | 3 ++ framework/src/main.rs | 3 -- kernel/src/{boards/qemu.rs => boards.rs} | 2 - kernel/src/config.rs | 1 - kernel/src/loader.rs | 5 ++- kernel/src/main.rs | 49 +++++------------------ kernel/src/{mm/mod.rs => mm.rs} | 7 +--- kernel/src/{sync/mod.rs => sync.rs} | 1 + kernel/src/{syscall/mod.rs => syscall.rs} | 1 - kernel/src/{task/mod.rs => task.rs} | 45 +++++---------------- kernel/src/{trap/mod.rs => trap.rs} | 36 ++++++++--------- user_lib/src/lib.rs | 2 +- 15 files changed, 73 insertions(+), 110 deletions(-) create mode 100644 framework/src/boot.rs create mode 100644 framework/src/lib.rs delete mode 100644 framework/src/main.rs rename kernel/src/{boards/qemu.rs => boards.rs} (71%) rename kernel/src/{mm/mod.rs => mm.rs} (79%) rename kernel/src/{sync/mod.rs => sync.rs} (98%) rename kernel/src/{syscall/mod.rs => syscall.rs} (94%) rename kernel/src/{task/mod.rs => task.rs} (75%) rename kernel/src/{trap/mod.rs => trap.rs} (86%) diff --git a/Cargo.lock b/Cargo.lock index 4b10805..05bb4db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,6 +41,10 @@ dependencies = [ "spin 0.7.2", ] +[[package]] +name = "framework" +version = "0.1.0" + [[package]] name = "kernel" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 2bbc8ad..eb41f97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,8 +3,6 @@ resolver = "2" members = [ "kernel", "user_lib", -] -exclude = [ "framework", ] diff --git a/framework/src/boot.rs b/framework/src/boot.rs new file mode 100644 index 0000000..2bc283a --- /dev/null +++ b/framework/src/boot.rs @@ -0,0 +1,22 @@ +unsafe extern "C" { + pub fn skernel(); + pub fn stext(); + pub fn etext(); + pub fn srodata(); + pub fn erodata(); + pub fn sdata(); + pub fn edata(); + pub fn sbss(); + pub fn ebss(); + pub fn sbss_with_stack(); + pub fn ekernel(); + pub fn strampoline(); +} + +pub fn clear_bss() { + for addr in sbss as usize..ebss as usize { + unsafe { + (addr as *mut u8).write_volatile(0); + } + } +} diff --git a/framework/src/lib.rs b/framework/src/lib.rs new file mode 100644 index 0000000..11b7636 --- /dev/null +++ b/framework/src/lib.rs @@ -0,0 +1,3 @@ +#![no_std] +mod boot; +pub use boot::clear_bss; diff --git a/framework/src/main.rs b/framework/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/framework/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/kernel/src/boards/qemu.rs b/kernel/src/boards.rs similarity index 71% rename from kernel/src/boards/qemu.rs rename to kernel/src/boards.rs index 0134d67..0658864 100644 --- a/kernel/src/boards/qemu.rs +++ b/kernel/src/boards.rs @@ -1,10 +1,8 @@ //! Constants used in rCore for qemu -// Board-level configuration for the QEMU virt machine pub const CLOCK_FREQ: usize = 1250_0000; pub const MEMORY_END: usize = 0x8800_0000; -// MMIO regions: (start_addr, size) pub const MMIO: &[(usize, usize)] = &[ (0x0010_0000, 0x00_2000), // VIRT_TEST/RTC in virt-machine ]; diff --git a/kernel/src/config.rs b/kernel/src/config.rs index 839046d..f1cc54f 100644 --- a/kernel/src/config.rs +++ b/kernel/src/config.rs @@ -23,4 +23,3 @@ pub fn kernel_stack_position(app_id: usize) -> (usize, usize) { let bottom = top - KERNEL_STACK_SIZE; (bottom, top) } - diff --git a/kernel/src/loader.rs b/kernel/src/loader.rs index 03c0039..3858e81 100644 --- a/kernel/src/loader.rs +++ b/kernel/src/loader.rs @@ -1,6 +1,7 @@ +use core::arch::asm; + use crate::config::*; use crate::trap::TrapContext; -use core::arch::asm; #[repr(align(4096))] #[derive(Clone, Copy)] @@ -27,7 +28,7 @@ impl KernelStack { self.data.as_ptr() as usize + KERNEL_STACK_SIZE } pub fn push_context(&self, trap_cx: TrapContext) -> usize { - let trap_cx_ptr = (self.get_sp() - core::mem::size_of::()) as *mut TrapContext; + let trap_cx_ptr = (self.get_sp() - size_of::()) as *mut TrapContext; unsafe { *trap_cx_ptr = trap_cx; } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 8c97bfa..d7e5cd2 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -2,14 +2,12 @@ #![no_main] #![feature(alloc_error_handler)] -#[path = "boards/qemu.rs"] -mod boards; - -//add my MODs -extern crate bitflags; +extern crate alloc; #[macro_use] mod console; + +mod boards; mod config; mod lang_items; mod loader; @@ -17,20 +15,18 @@ mod logging; mod mm; mod sbi; mod sync; +mod timer; + pub mod syscall; pub mod task; -mod timer; pub mod trap; -extern crate alloc; use core::arch::global_asm; use log::*; -use crate::mm::{frame_allocator_test, init_frame_allocator, init_heap}; global_asm!(include_str!("entry.asm")); global_asm!(include_str!("link_app.S")); -/// clear BSS segment fn clear_bss() { unsafe extern "C" { safe fn sbss(); @@ -45,9 +41,9 @@ fn clear_bss() { #[allow(unused)] fn heap_test() { - info!("[kernel test02] heap init test ..."); use alloc::boxed::Box; use alloc::vec::Vec; + unsafe extern "C" { safe fn sbss(); safe fn ebss(); @@ -69,42 +65,15 @@ fn heap_test() { info!("[kernel test02] heap init test passed!"); } -/// the rust entry-point of OS #[unsafe(no_mangle)] pub fn rust_main() -> ! { - // Referrence - // clear_bss(); - // logging::init(); - // info!("[kernel] Hello, world!"); - // - // // Initialize the kernel heap and run a heap memory test - // init_heap(); - // heap_test(); - // - // // Initialize the physical frame allocator - // init_frame_allocator(); - // frame_allocator_test(); - // - // // Run user applications - // trap::init(); - // loader::load_apps(); - // trap::enable_timer_interrupt(); - // timer::set_next_trigger(); - // task::run_first_task(); - // - // panic!("Unreachable in rust_main"); - clear_bss(); // test ok! + clear_bss(); + logging::init(); - // TODO: - // 7.19,20;继续排除问题重构代码让上面这两个函数的调用链正常,遇到必要时,重构代码和写测试代码 - // 重构代码,参考framework kernel,分离safe rust和unsafe rust; - // 分享想法(重构framework kernel后,录制演示视频) - // 直接录制演示视频,写一个架构介绍去咨询意见 mm::init(); - trap::init(); // setup the kernel trap + trap::init(); trap::enable_timer_interrupt(); timer::set_next_trigger(); task::run_first_task(); panic!("Unreachable in rust_main!"); - // NOTE: 7.14决定完全重构,刚检查完主函数,后续继续重构 } diff --git a/kernel/src/mm/mod.rs b/kernel/src/mm.rs similarity index 79% rename from kernel/src/mm/mod.rs rename to kernel/src/mm.rs index 8c3358c..946e210 100644 --- a/kernel/src/mm/mod.rs +++ b/kernel/src/mm.rs @@ -22,12 +22,9 @@ use crate::heap_test; /// initiate the heap allocator, frame allocator and kernel space pub fn init() { - heap_allocator::init_heap(); + init_heap(); heap_test(); - frame_allocator::init_frame_allocator(); + init_frame_allocator(); frame_allocator_test(); - // NOTE: How the kernel page table is set up (TOPIC) - // Activate SV39 paging mode - // successfully established the KERNEL_SPACE KERNEL_SPACE.exclusive_access().active(); } diff --git a/kernel/src/sync/mod.rs b/kernel/src/sync.rs similarity index 98% rename from kernel/src/sync/mod.rs rename to kernel/src/sync.rs index 6bb64af..1ccdd2e 100644 --- a/kernel/src/sync/mod.rs +++ b/kernel/src/sync.rs @@ -1,3 +1,4 @@ //! Synchronization and interior mutability primitives + mod up; pub use up::UPSafeCell; diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall.rs similarity index 94% rename from kernel/src/syscall/mod.rs rename to kernel/src/syscall.rs index cd685ed..e2fde20 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall.rs @@ -21,7 +21,6 @@ mod process; use fs::sys_write; use process::{sys_exit, sys_get_time, sys_yield}; -/// handle syscall exception with 'syscall_id' and other arguments pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { match syscall_id { SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]), diff --git a/kernel/src/task/mod.rs b/kernel/src/task.rs similarity index 75% rename from kernel/src/task/mod.rs rename to kernel/src/task.rs index 7334c91..59d24e2 100644 --- a/kernel/src/task/mod.rs +++ b/kernel/src/task.rs @@ -1,18 +1,21 @@ +use alloc::vec::Vec; +use lazy_static::*; + +use crate::info; +use crate::loader::get_app_data; +use crate::loader::get_num_app; +use crate::sbi::shutdown; +use crate::sync::UPSafeCell; +use crate::trap::TrapContext; + mod context; mod switch; mod task; -use super::sync::UPSafeCell; -use crate::info; -use crate::loader::get_app_data; use crate::task::context::TaskContext; use crate::task::switch::__switch; use crate::task::task::TaskControlBlock; use crate::task::task::TaskStatus; -use crate::trap::TrapContext; -use crate::{loader::get_num_app, sbi::shutdown}; -use alloc::vec::Vec; -use lazy_static::*; pub struct TaskManagerInner { tasks: Vec, @@ -20,14 +23,11 @@ pub struct TaskManagerInner { } pub struct TaskManager { - /// total number of tasks num_app: usize, - /// use inner value to get mutable access; inner: UPSafeCell, } lazy_static! { - /// Global variable: TASK_MANAGER pub static ref TASK_MANAGER: TaskManager = { info!("[kernel test07] init TASK_MANAGER ...!"); let num_app = get_num_app(); @@ -58,38 +58,27 @@ impl TaskManager { drop(inner); let mut fake_task_context = TaskContext::zero_init(); - // NOTE: let the "first task" be the "next task" being switch to info!("[kernel test08] use 'switch.S' to load the first task's context ...!"); unsafe { - // NOTE: - // __switch(context_being_stored, context_being_restored); - // store "current context"(group of registers) to context_being_stored - // restore context_being_restored to "current context"(group of registers) __switch(&mut fake_task_context as *mut TaskContext, next_task_cx_ptr); - // paraments will be put in the a0,a1 for expression in "__switch()" to use } panic!("unreachable in run_first_task") } - /// Change the status of current fn mark_current_suspended(&self) { let mut inner = self.inner.exclusive_access(); let current = inner.current_task; inner.tasks[current].task_status = TaskStatus::Ready; } - /// Change the status of current `Running` task into `Ready` fn mark_current_exited(&self) { let mut inner = self.inner.exclusive_access(); let current = inner.current_task; inner.tasks[current].task_status = TaskStatus::Exited; } - /// Find next task to run and return task id. - /// - /// In this case, we only return the first `Ready` task in task list. fn find_next_task(&self) -> Option { let inner = self.inner.exclusive_access(); let current = inner.current_task; @@ -98,8 +87,6 @@ impl TaskManager { .find(|id| inner.tasks[*id].task_status == TaskStatus::Ready) } - /// Switch current `Running` task to the task we have found, - /// or there is no `Ready` task and we can exit with all applications complecated fn run_next_task(&self) { if let Some(next) = self.find_next_task() { let mut inner = self.inner.exclusive_access(); @@ -109,20 +96,18 @@ impl TaskManager { let current_task_cx_ptr = &mut inner.tasks[current].task_cx as *mut TaskContext; let next_task_cx_ptr = &inner.tasks[next].task_cx as *const TaskContext; drop(inner); - // before this, we should drop local variables that must be dropped mannually info!( "[kernel notice] run_next_task(): next task exist!Use __switch(task a, task b) to switch task!" ); unsafe { __switch(current_task_cx_ptr, next_task_cx_ptr); } - // go back to user mode } else { info!("[kernel notice] next task not exists! All applications completed! shutdown!"); shutdown(false); } } - /// get the current `Running` task's token. + fn get_current_token(&self) -> usize { let inner = self.inner.exclusive_access(); let current = inner.current_task; @@ -136,44 +121,36 @@ impl TaskManager { } } -/// run first task pub fn run_first_task() { TASK_MANAGER.run_first_task(); } -/// exit current task fn mark_current_exited() { TASK_MANAGER.mark_current_exited(); } -/// suspend current task fn mark_current_suspended() { TASK_MANAGER.mark_current_suspended(); } -/// run next task fn run_next_task() { TASK_MANAGER.run_next_task(); } -/// suspend current task and run next task pub fn suspend_current_and_run_next() { mark_current_suspended(); run_next_task(); } -/// exit current task, then run next task pub fn exit_current_and_run_next() { mark_current_exited(); run_next_task(); } -/// get the current `Running` task's token pub fn current_user_token() -> usize { TASK_MANAGER.get_current_token() } -/// get current task's TrapContext pub fn current_trap_cx() -> &'static mut TrapContext { TASK_MANAGER.get_current_trap_cx() } diff --git a/kernel/src/trap/mod.rs b/kernel/src/trap.rs similarity index 86% rename from kernel/src/trap/mod.rs rename to kernel/src/trap.rs index 034ffc8..78c0e8d 100644 --- a/kernel/src/trap/mod.rs +++ b/kernel/src/trap.rs @@ -11,15 +11,9 @@ //! It then calls different functionality based on what exactly the exception //! was. For example, timer interrupts trigger task preemption, and syscalls go //! to [`syscall()`]. -mod context; -use crate::config::{TRAMPOLINE, TRAP_CONTEXT}; -use crate::task::{ - current_trap_cx, current_user_token, exit_current_and_run_next, suspend_current_and_run_next, -}; -use crate::{syscall::syscall, timer::set_next_trigger}; -pub use context::TrapContext; use core::arch::{asm, global_asm}; + use log::info; use riscv::register::{ scause::{self, Exception, Interrupt, Trap}, @@ -27,9 +21,18 @@ use riscv::register::{ stvec::{self, TrapMode}, }; -global_asm!(include_str!("trap.S")); +use crate::config::{TRAMPOLINE, TRAP_CONTEXT}; +use crate::syscall::syscall; +use crate::task::{ + current_trap_cx, current_user_token, exit_current_and_run_next, suspend_current_and_run_next, +}; +use crate::timer::set_next_trigger; + +mod context; +pub use context::TrapContext; + +global_asm!(include_str!("trap/trap.S")); -/// set kernel trap entry pub fn init() { set_kernel_trap_entry(); } @@ -53,7 +56,7 @@ fn set_kernel_trap_entry() { pub fn enable_timer_interrupt() { info!("[kernel test05] use sie to enable stimer interrupt ...!"); unsafe { - sie::set_stimer(); // can be triggered in the trap_handler + sie::set_stimer(); } info!("[kernel test05] use sie to enable stimer interrupt ok!"); } @@ -144,15 +147,10 @@ pub fn trap_return() -> ! { unsafe { asm!( "fence.i", - "jr {restore_va}", // jump to new addr of __restore asm function - // NOTE: - // "Put the Rust variable restore_va into a register, and bind that register to the {restore_va} placeholder in the assembly string." - restore_va = in(reg) restore_va, // compiler paras!! not asm!! - // a0 = virt addr of Trap Context - in("a0") trap_cx_ptr, // compiler paras!! not asm!! - // a1 = userspace's satp setup value - in("a1") user_satp, // compiler paras!! not asm!! - // do not return + "jr {restore_va}", + restore_va = in(reg) restore_va, + in("a0") trap_cx_ptr, + in("a1") user_satp, options(noreturn) ); } diff --git a/user_lib/src/lib.rs b/user_lib/src/lib.rs index df3628d..2bc7979 100644 --- a/user_lib/src/lib.rs +++ b/user_lib/src/lib.rs @@ -19,7 +19,7 @@ fn main() -> i32 { panic!("Cannot find main"); } -use syscall::*; +use syscall::{sys_exit, sys_get_time, sys_write, sys_yield}; pub fn write(fd: usize, buf: &[u8]) -> isize { sys_write(fd, buf) From 5d97dc4f3e87f992f635a68fc54574dce09e40b7 Mon Sep 17 00:00:00 2001 From: tinyblinker <2149934895@qq.com> Date: Tue, 21 Jul 2026 15:24:20 +0800 Subject: [PATCH 2/5] safe_clear_bss --- Cargo.lock | 1 + framework/src/boot.rs | 2 +- kernel/Cargo.toml | 1 + kernel/src/main.rs | 24 ++++++------------------ 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 05bb4db..85a2edd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,6 +51,7 @@ version = "0.1.0" dependencies = [ "bitflags", "buddy_system_allocator", + "framework", "lazy_static", "log", "riscv", diff --git a/framework/src/boot.rs b/framework/src/boot.rs index 2bc283a..0465271 100644 --- a/framework/src/boot.rs +++ b/framework/src/boot.rs @@ -14,7 +14,7 @@ unsafe extern "C" { } pub fn clear_bss() { - for addr in sbss as usize..ebss as usize { + for addr in sbss as *const () as usize..ebss as *const () as usize { unsafe { (addr as *mut u8).write_volatile(0); } diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 5fd6390..2bf1f26 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -11,6 +11,7 @@ xmas-elf.workspace = true sbi-rt.workspace = true buddy_system_allocator.workspace = true bitflags.workspace = true +framework = { path = "../framework" } [lints] workspace = true diff --git a/kernel/src/main.rs b/kernel/src/main.rs index d7e5cd2..938ed00 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -22,23 +22,12 @@ pub mod task; pub mod trap; use core::arch::global_asm; +use framework::clear_bss; use log::*; global_asm!(include_str!("entry.asm")); global_asm!(include_str!("link_app.S")); -fn clear_bss() { - unsafe extern "C" { - safe fn sbss(); - safe fn ebss(); - } - for item in sbss as unsafe extern "C" fn() as usize..ebss as unsafe extern "C" fn() as usize { - unsafe { - (item as *mut u8).write_volatile(0); - } - } -} - #[allow(unused)] fn heap_test() { use alloc::boxed::Box; @@ -68,12 +57,11 @@ fn heap_test() { #[unsafe(no_mangle)] pub fn rust_main() -> ! { clear_bss(); - logging::init(); - mm::init(); - trap::init(); - trap::enable_timer_interrupt(); - timer::set_next_trigger(); - task::run_first_task(); + // mm::init(); + // trap::init(); + // trap::enable_timer_interrupt(); + // timer::set_next_trigger(); + // task::run_first_task(); panic!("Unreachable in rust_main!"); } From c0a974f6795dcdad1a2ac5985aed3993517b6ae6 Mon Sep 17 00:00:00 2001 From: tinyblinker <2149934895@qq.com> Date: Tue, 21 Jul 2026 15:38:38 +0800 Subject: [PATCH 3/5] init log:safe --- kernel/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 938ed00..e2eefd1 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -21,6 +21,7 @@ pub mod syscall; pub mod task; pub mod trap; +use crate::logging::init; use core::arch::global_asm; use framework::clear_bss; use log::*; From a53f688c5efa6e996c7e39b83cf6de81b08b3e9b Mon Sep 17 00:00:00 2001 From: tinyblinker <2149934895@qq.com> Date: Tue, 21 Jul 2026 16:02:33 +0800 Subject: [PATCH 4/5] remove unsafe in mm::init() --- framework/src/boot.rs | 47 +++++++++++++++++------- framework/src/lib.rs | 8 ++++- framework/src/memory.rs | 25 +++++++++++++ kernel/src/main.rs | 9 ++--- kernel/src/mm/address.rs | 8 ++--- kernel/src/mm/frame_allocator.rs | 5 +-- kernel/src/mm/memory_set.rs | 61 +++++++++++--------------------- 7 files changed, 94 insertions(+), 69 deletions(-) create mode 100644 framework/src/memory.rs diff --git a/framework/src/boot.rs b/framework/src/boot.rs index 0465271..e640830 100644 --- a/framework/src/boot.rs +++ b/framework/src/boot.rs @@ -1,22 +1,43 @@ unsafe extern "C" { - pub fn skernel(); - pub fn stext(); - pub fn etext(); - pub fn srodata(); - pub fn erodata(); - pub fn sdata(); - pub fn edata(); - pub fn sbss(); - pub fn ebss(); - pub fn sbss_with_stack(); - pub fn ekernel(); - pub fn strampoline(); + fn skernel(); + fn stext(); + fn etext(); + fn srodata(); + fn erodata(); + fn sdata(); + fn edata(); + fn sbss(); + fn ebss(); + fn sbss_with_stack(); + fn ekernel(); + fn strampoline(); } pub fn clear_bss() { - for addr in sbss as *const () as usize..ebss as *const () as usize { + for addr in sbss_addr()..ebss_addr() { unsafe { (addr as *mut u8).write_volatile(0); } } } + +macro_rules! define_addr_getter { + ($name:ident, $sym:ident) => { + pub fn $name() -> usize { + $sym as *const () as usize + } + }; +} + +define_addr_getter!(skernel_addr, skernel); +define_addr_getter!(stext_addr, stext); +define_addr_getter!(etext_addr, etext); +define_addr_getter!(srodata_addr, srodata); +define_addr_getter!(erodata_addr, erodata); +define_addr_getter!(sdata_addr, sdata); +define_addr_getter!(edata_addr, edata); +define_addr_getter!(sbss_addr, sbss); +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); diff --git a/framework/src/lib.rs b/framework/src/lib.rs index 11b7636..ae65aa2 100644 --- a/framework/src/lib.rs +++ b/framework/src/lib.rs @@ -1,3 +1,9 @@ #![no_std] mod boot; -pub use boot::clear_bss; +mod memory; + +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, +}; +pub use memory::{phys_to_byte_slice, phys_to_ref, phys_to_slice, sfence_vma, write_satp}; diff --git a/framework/src/memory.rs b/framework/src/memory.rs new file mode 100644 index 0000000..ac31ddf --- /dev/null +++ b/framework/src/memory.rs @@ -0,0 +1,25 @@ +use core::arch::asm; + +pub fn phys_to_byte_slice(phys_addr: usize, len: usize) -> &'static mut [u8] { + unsafe { core::slice::from_raw_parts_mut(phys_addr as *mut u8, len) } +} + +pub fn phys_to_slice(phys_addr: usize, count: usize) -> &'static mut [T] { + unsafe { core::slice::from_raw_parts_mut(phys_addr as *mut T, count) } +} + +pub fn phys_to_ref(phys_addr: usize) -> &'static mut T { + unsafe { (phys_addr as *mut T).as_mut().unwrap() } +} + +pub fn write_satp(val: usize) { + unsafe { + asm!("csrw satp, {}", in(reg) val); + } +} + +pub fn sfence_vma() { + unsafe { + asm!("sfence.vma"); + } +} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index e2eefd1..75d8763 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -21,7 +21,6 @@ pub mod syscall; pub mod task; pub mod trap; -use crate::logging::init; use core::arch::global_asm; use framework::clear_bss; use log::*; @@ -34,11 +33,7 @@ fn heap_test() { use alloc::boxed::Box; use alloc::vec::Vec; - unsafe extern "C" { - safe fn sbss(); - safe fn ebss(); - } - let bss_range = sbss as *const () as usize..ebss as *const () as usize; + let bss_range = framework::sbss_addr()..framework::ebss_addr(); let a = Box::new(5); assert_eq!(*a, 5); assert!(bss_range.contains(&(a.as_ref() as *const _ as *const () as usize))); @@ -59,7 +54,7 @@ fn heap_test() { pub fn rust_main() -> ! { clear_bss(); logging::init(); - // mm::init(); + mm::init(); // trap::init(); // trap::enable_timer_interrupt(); // timer::set_next_trigger(); diff --git a/kernel/src/mm/address.rs b/kernel/src/mm/address.rs index a3b2c21..becbae7 100644 --- a/kernel/src/mm/address.rs +++ b/kernel/src/mm/address.rs @@ -1,7 +1,7 @@ use core::fmt::{self, Debug, Formatter}; use crate::{ - config::{PAGE_SIZE, PAGE_SIZE_BITS, PTES_PER_PAGE}, + config::{PAGE_SIZE, PAGE_SIZE_BITS}, mm::page_table::PageTableEntry, }; @@ -146,15 +146,15 @@ impl PhysPageNum { /// the entire page like a normal array. pub fn get_bytes_array(&self) -> &'static mut [u8] { let pa: PhysAddr = self.clone().into(); - unsafe { core::slice::from_raw_parts_mut(pa.0 as *mut u8, PAGE_SIZE) } + framework::phys_to_byte_slice(pa.0, PAGE_SIZE) } pub fn get_pte_array(&self) -> &'static mut [PageTableEntry] { let pa: PhysAddr = self.clone().into(); - unsafe { core::slice::from_raw_parts_mut(pa.0 as *mut PageTableEntry, PTES_PER_PAGE) } + framework::phys_to_slice(pa.0, crate::config::PTES_PER_PAGE) } pub fn get_mut(&self) -> &'static mut T { let pa: PhysAddr = self.clone().into(); - unsafe { (pa.0 as *mut T).as_mut().unwrap() } + framework::phys_to_ref(pa.0) } } impl VirtPageNum { diff --git a/kernel/src/mm/frame_allocator.rs b/kernel/src/mm/frame_allocator.rs index e2f768f..b9f0fbc 100644 --- a/kernel/src/mm/frame_allocator.rs +++ b/kernel/src/mm/frame_allocator.rs @@ -106,11 +106,8 @@ lazy_static! { // operation on the allocator, we must call FRAME_ALLOCATOR.exclusive_access() // to obtain a mutable reference. pub fn init_frame_allocator() { - unsafe extern "C" { - safe fn ekernel(); - } FRAME_ALLOCATOR.exclusive_access().init( - PhysAddr::from(ekernel as *const u8 as usize).ceil(), + PhysAddr::from(framework::ekernel_addr()).ceil(), PhysAddr::from(MEMORY_END).floor(), ); } diff --git a/kernel/src/mm/memory_set.rs b/kernel/src/mm/memory_set.rs index 697db10..9205203 100644 --- a/kernel/src/mm/memory_set.rs +++ b/kernel/src/mm/memory_set.rs @@ -1,23 +1,9 @@ +use alloc::collections::btree_map::BTreeMap; use alloc::vec::Vec; -use alloc::{collections::btree_map::BTreeMap, sync::Arc}; +use alloc::sync::Arc; use bitflags::bitflags; -use core::arch::asm; use lazy_static::lazy_static; use log::info; -use riscv::register::satp; - -unsafe extern "C" { - safe fn stext(); - safe fn etext(); - safe fn srodata(); - safe fn erodata(); - safe fn sdata(); - safe fn edata(); - safe fn sbss_with_stack(); - safe fn ebss(); - safe fn ekernel(); - safe fn strampoline(); -} lazy_static! { /// Create the global kernel address space instance @@ -173,7 +159,7 @@ impl MemorySet { fn map_trampoline(&mut self) { self.page_table.map( VirtAddr::from(TRAMPOLINE).into(), - PhysAddr::from(strampoline as *const () as usize).into(), + PhysAddr::from(framework::strampoline_addr()).into(), PTEFlags::R | PTEFlags::X, ); } @@ -187,25 +173,25 @@ impl MemorySet { // map kernel sections println!( ".text [{:#x}, {:#x})", - stext as *const () as usize, etext as *const () as usize + framework::stext_addr(), framework::etext_addr() ); println!( ".rodata [{:#x}, {:#x})", - srodata as *const () as usize, erodata as *const () as usize + framework::srodata_addr(), framework::erodata_addr() ); println!( ".data [{:#x}, {:#x})", - sdata as *const () as usize, edata as *const () as usize + framework::sdata_addr(), framework::edata_addr() ); println!( ".bss [{:#x}, {:#x})", - sbss_with_stack as *const () as usize, ebss as *const () as usize + framework::sbss_with_stack_addr(), framework::ebss_addr() ); println!("mapping .text section"); memory_set.push( MapArea::new( - (stext as *const () as usize).into(), - (etext as *const () as usize).into(), + (framework::stext_addr()).into(), + (framework::etext_addr()).into(), MapType::Identical, MapPermission::R | MapPermission::X, ), @@ -214,8 +200,8 @@ impl MemorySet { println!("mapping .rodata section"); memory_set.push( MapArea::new( - (srodata as *const () as usize).into(), - (erodata as *const () as usize).into(), + (framework::srodata_addr()).into(), + (framework::erodata_addr()).into(), MapType::Identical, MapPermission::R, ), @@ -224,8 +210,8 @@ impl MemorySet { println!("mapping .data section"); memory_set.push( MapArea::new( - (sdata as *const () as usize).into(), - (edata as *const () as usize).into(), + (framework::sdata_addr()).into(), + (framework::edata_addr()).into(), MapType::Identical, MapPermission::R | MapPermission::W, ), @@ -234,8 +220,8 @@ impl MemorySet { println!("mapping .bss section"); memory_set.push( MapArea::new( - (sbss_with_stack as *const () as usize).into(), - (ebss as *const () as usize).into(), + (framework::sbss_with_stack_addr()).into(), + (framework::ebss_addr()).into(), MapType::Identical, MapPermission::R | MapPermission::W, ), @@ -244,7 +230,7 @@ impl MemorySet { println!("mapping physical memory"); memory_set.push( MapArea::new( - (ekernel as *const () as usize).into(), + (framework::ekernel_addr()).into(), MEMORY_END.into(), MapType::Identical, MapPermission::R | MapPermission::W, @@ -354,13 +340,8 @@ impl MemorySet { pub fn active(&self) { info!("[kernel notice] enable virtual memory ...!"); let satp = self.page_table.token(); - unsafe { - satp::write(satp); - // Since the kernel page table uses identity mapping, after paging - // is enabled we can still correctly access kernel addresses to - // fetch instructions - asm!("sfence.vma"); - } + framework::write_satp(satp); + framework::sfence_vma(); info!("[kernel notice] enable virtual memory ok!"); } pub fn translate(&self, vpn: VirtPageNum) -> Option { @@ -374,11 +355,11 @@ impl MemorySet { pub fn remap_test() { let mut kernel_space = KERNEL_SPACE.exclusive_access(); let mid_text: VirtAddr = - ((stext as *const () as usize + etext as *const () as usize) / 2).into(); + ((framework::stext_addr() + framework::etext_addr()) / 2).into(); let mid_rodata: VirtAddr = - ((srodata as *const () as usize + erodata as *const () as usize) / 2).into(); + ((framework::srodata_addr() + framework::erodata_addr()) / 2).into(); let mid_data: VirtAddr = - ((sdata as *const () as usize + edata as *const () as usize) / 2).into(); + ((framework::sdata_addr() + framework::edata_addr()) / 2).into(); assert!( !kernel_space .page_table From aec945d543216085f916ae0b43ef1568a3d63437 Mon Sep 17 00:00:00 2001 From: tinyblinker <2149934895@qq.com> Date: Tue, 21 Jul 2026 16:20:05 +0800 Subject: [PATCH 5/5] remove all unsafe in mm::init() --- Cargo.lock | 3 +++ framework/Cargo.toml | 1 + framework/src/lib.rs | 5 ++++- framework/src/memory.rs | 18 ++++++++++++++++++ kernel/src/config.rs | 1 - kernel/src/main.rs | 10 ++++++---- kernel/src/mm/heap_allocator.rs | 11 +---------- 7 files changed, 33 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 85a2edd..f2a8a40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,9 @@ dependencies = [ [[package]] name = "framework" version = "0.1.0" +dependencies = [ + "buddy_system_allocator", +] [[package]] name = "kernel" diff --git a/framework/Cargo.toml b/framework/Cargo.toml index 1162d03..b636f91 100644 --- a/framework/Cargo.toml +++ b/framework/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] +buddy_system_allocator.workspace = true [lints] workspace = true diff --git a/framework/src/lib.rs b/framework/src/lib.rs index ae65aa2..60ceff5 100644 --- a/framework/src/lib.rs +++ b/framework/src/lib.rs @@ -6,4 +6,7 @@ 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, }; -pub use memory::{phys_to_byte_slice, phys_to_ref, phys_to_slice, sfence_vma, write_satp}; +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, +}; diff --git a/framework/src/memory.rs b/framework/src/memory.rs index ac31ddf..8d25626 100644 --- a/framework/src/memory.rs +++ b/framework/src/memory.rs @@ -1,5 +1,23 @@ +use buddy_system_allocator::LockedHeap; use core::arch::asm; +pub const KERNEL_HEAP_SIZE: usize = 0x30_0000; + +static mut HEAP_SPACE: [u8; KERNEL_HEAP_SIZE] = [0; KERNEL_HEAP_SIZE]; + +pub fn heap_region() -> &'static mut [u8] { + unsafe { &mut *core::ptr::addr_of_mut!(HEAP_SPACE) } +} + +pub fn init_heap_allocator(allocator: &LockedHeap) { + let heap = heap_region(); + unsafe { + allocator + .lock() + .init(heap.as_mut_ptr() as usize, KERNEL_HEAP_SIZE); + } +} + pub fn phys_to_byte_slice(phys_addr: usize, len: usize) -> &'static mut [u8] { unsafe { core::slice::from_raw_parts_mut(phys_addr as *mut u8, len) } } diff --git a/kernel/src/config.rs b/kernel/src/config.rs index f1cc54f..e7f3850 100644 --- a/kernel/src/config.rs +++ b/kernel/src/config.rs @@ -6,7 +6,6 @@ pub const APP_BASE_ADDRESS: usize = 0x80400000; pub const APP_SIZE_LIMIT: usize = 0x20000; pub const USER_STACK_SIZE: usize = 4096 * 2; pub const KERNEL_STACK_SIZE: usize = 4096 * 2; -pub const KERNEL_HEAP_SIZE: usize = 0x30_0000; /// Current page size (typical value 0x1000: 4KB) pub const PAGE_SIZE: usize = 0x1000; /// Number of bits used for page offset (with 0x1000 page size, diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 75d8763..9fb1a71 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -55,9 +55,11 @@ pub fn rust_main() -> ! { clear_bss(); logging::init(); mm::init(); - // trap::init(); - // trap::enable_timer_interrupt(); - // timer::set_next_trigger(); - // task::run_first_task(); + // NOTE: finished removed (only necessary unsafe in framework) all the unsafe in the "mm::init" + // TODO: 7.22 remove necessary(minimal) unsafe to framework in trap::init(); + trap::init(); + trap::enable_timer_interrupt(); + timer::set_next_trigger(); + task::run_first_task(); panic!("Unreachable in rust_main!"); } diff --git a/kernel/src/mm/heap_allocator.rs b/kernel/src/mm/heap_allocator.rs index 3f56b79..36f167c 100644 --- a/kernel/src/mm/heap_allocator.rs +++ b/kernel/src/mm/heap_allocator.rs @@ -1,20 +1,11 @@ -use core::ptr::addr_of_mut; - -use crate::config::KERNEL_HEAP_SIZE; use buddy_system_allocator::LockedHeap; //follow the rules to provide ABIs for allocator #[global_allocator] static HEAP_ALLOCATOR: LockedHeap = LockedHeap::empty(); -static mut HEAP_SPACE: [u8; KERNEL_HEAP_SIZE] = [0; KERNEL_HEAP_SIZE]; - pub fn init_heap() { - unsafe { - HEAP_ALLOCATOR - .lock() - .init(addr_of_mut!(HEAP_SPACE) as usize, KERNEL_HEAP_SIZE); - } + framework::init_heap_allocator(&HEAP_ALLOCATOR); } #[alloc_error_handler]