From 82f24c4d785818a80e49450e597f2540d45d9826 Mon Sep 17 00:00:00 2001 From: SKTT1Ryze Date: Fri, 9 Apr 2021 17:45:53 +0800 Subject: [PATCH] add shared segment mapping --- tornado-kernel/src/main.rs | 22 +++++---- tornado-kernel/src/memory/config.rs | 7 +++ .../src/memory/mapping/memory_set.rs | 46 ++++++++++++++++++- tornado-kernel/src/task/shared.rs | 2 + tornado-kernel/src/trap/mod.rs | 11 +++-- tornado-kernel/src/user.rs | 15 ++++-- tornado-user/src/bin/00-hello-world.rs | 3 -- tornado-user/src/main.rs | 6 +++ tornado-user/src/shared.rs | 24 ++++++++++ 9 files changed, 115 insertions(+), 21 deletions(-) delete mode 100644 tornado-user/src/bin/00-hello-world.rs create mode 100644 tornado-user/src/shared.rs diff --git a/tornado-kernel/src/main.rs b/tornado-kernel/src/main.rs index 5c13928..6f8a26a 100644 --- a/tornado-kernel/src/main.rs +++ b/tornado-kernel/src/main.rs @@ -92,6 +92,8 @@ pub extern "C" fn rust_main(hart_id: usize) -> ! { println!("_user_to_supervisor: {:#x}", _user_to_supervisor as usize); println!("_supervisor_to_user: {:#x}", _supervisor_to_user as usize); println!("_user_data: {:#x}", _user_data as usize); + println!("shared_add_task: {:#x}", task::shared_add_task as usize); + println!("shared_pop_task: {:#x}", task::shared_pop_task as usize); // let executor = task::Executor::default(); @@ -110,21 +112,21 @@ pub extern "C" fn rust_main(hart_id: usize) -> ! { // todo: 这里要有个地方往tp里写东西,目前会出错 let kernel_memory = memory::MemorySet::new_kernel().expect("create kernel memory set"); kernel_memory.activate(); + + let shared_scheduler = task::shared_scheduler(); + println!("Shared scheduler: {:?}", shared_scheduler); + let process = task::Process::new(kernel_memory).expect("create process 1"); let stack_handle = process.alloc_stack().expect("alloc initial stack"); + let task_1 = task::KernelTask::new(task_1(), process.clone()); + println!("task_1: {:?}", task_1); + unsafe { + task::shared_add_task(shared_scheduler, task_1.shared_task_handle()); + let _pop_task = task::shared_pop_task(shared_scheduler); + } // 尝试进入用户态 user::try_enter_user(stack_handle.end.0 - 4) - // let task_1 = task::KernelTask::new(task_1(), process.clone()); - // let task_2 = task::KernelTask::new(task_2(), process.clone()); - // let task_3 = task::KernelTask::new(FibonacciFuture::new(5), process); - // println!("task_1: {:?}", task_1); - // println!("task_2: {:?}", task_2); - // println!("task_3: {:?}", task_3); - - // let shared_scheduler = task::shared_scheduler(); - // println!("Shared scheduler: {:?}", shared_scheduler); - // let user_1_memory = memory::MemorySet::new_user().expect("create user 1 memory set"); // let process_2 = task::Process::new(user_1_memory).expect("create process 2"); // let task_4 = task::user_task::UserTask::new(user_task_1(), process_2); diff --git a/tornado-kernel/src/memory/config.rs b/tornado-kernel/src/memory/config.rs index 3d046e4..e76bf53 100644 --- a/tornado-kernel/src/memory/config.rs +++ b/tornado-kernel/src/memory/config.rs @@ -31,4 +31,11 @@ pub const SWAP_CONTEXT_VA: usize = SWAP_FRAME_VA - PAGE_SIZE; /// 用户态栈的虚拟地址 /// 放在切换时保存的上下文下面 +/// todo: 这个后面要移除 pub const USER_STACK_BOTTOM_VA: usize = SWAP_CONTEXT_VA - PAGE_SIZE; + +/// 共享数据段在用户态中的虚拟地址 +pub const USER_SHARED_DATA_VA: usize = 0xffff_ffff_ffff_0000; + +/// 共享代码段在用户态中的虚拟地址 +pub const USER_SHARED_TEXT_VA: usize = 0xffff_ffff_fffe_0000; diff --git a/tornado-kernel/src/memory/mapping/memory_set.rs b/tornado-kernel/src/memory/mapping/memory_set.rs index 0a5dfc9..4a27faf 100644 --- a/tornado-kernel/src/memory/mapping/memory_set.rs +++ b/tornado-kernel/src/memory/mapping/memory_set.rs @@ -1,5 +1,28 @@ -use crate::memory::{KERNEL_MAP_OFFSET, PhysicalPageNumber, SWAP_CONTEXT_VA, config::{FREE_MEMORY_START, MEMORY_END_ADDRESS, PAGE_SIZE, SWAP_FRAME_VA, USER_STACK_BOTTOM_VA}}; -use crate::memory::{Mapping, MapType, Segment, Flags, VirtualAddress, VirtualPageNumber, PhysicalAddress, FrameTracker, AddressSpaceId}; +use crate::memory::{ + KERNEL_MAP_OFFSET, + PhysicalPageNumber, + SWAP_CONTEXT_VA, + config::{ + FREE_MEMORY_START, + MEMORY_END_ADDRESS, + PAGE_SIZE, + SWAP_FRAME_VA, + USER_STACK_BOTTOM_VA, + USER_SHARED_DATA_VA, + USER_SHARED_TEXT_VA + } +}; +use crate::memory::{ + Mapping, + MapType, + Segment, + Flags, + VirtualAddress, + VirtualPageNumber, + PhysicalAddress, + FrameTracker, + AddressSpaceId +}; use alloc::vec::Vec; use core::ops::Range; @@ -231,6 +254,10 @@ impl MemorySet { pub fn new_bin() -> Option { extern "C" { fn _swap_frame(); + fn _sshared_data(); + fn _eshared_data(); + fn _sshared_text(); + fn _eshared_text(); } let mut mapping = Mapping::new_alloc()?; let allocated_pairs = Vec::new(); @@ -253,6 +280,21 @@ impl MemorySet { range: swap_cx_va..swap_cx_va + PAGE_SIZE, flags: Flags::READABLE | Flags::WRITABLE, }, None)?; + + // 映射共享数据段 + let shared_data_len = _eshared_data as usize - _sshared_data as usize; + let va_range = VirtualAddress(USER_SHARED_DATA_VA)..VirtualAddress(USER_SHARED_DATA_VA + shared_data_len); + let pa_range = + VirtualAddress(_sshared_data as usize).physical_address_linear()..VirtualAddress(_eshared_data as usize).physical_address_linear(); + mapping.map_defined(&va_range, &pa_range, Flags::READABLE | Flags::WRITABLE | Flags::USER); + + // 映射共享代码段 + let shared_text_len = _eshared_text as usize - _sshared_text as usize; + let va_range = VirtualAddress(USER_SHARED_TEXT_VA)..VirtualAddress(USER_SHARED_TEXT_VA + shared_text_len); + let pa_range = + VirtualAddress(_sshared_text as usize).physical_address_linear()..VirtualAddress(_eshared_text as usize).physical_address_linear(); + mapping.map_defined(&va_range, &pa_range, Flags::READABLE | Flags::WRITABLE | Flags::EXECUTABLE | Flags::USER); + let address_space_id = crate::hart::KernelHartInfo::alloc_address_space_id()?; // todo: 释放asid println!("New asid = {:?}", address_space_id); Some(MemorySet { mapping, segments: Vec::new(), allocated_pairs, address_space_id }) diff --git a/tornado-kernel/src/task/shared.rs b/tornado-kernel/src/task/shared.rs index 528d80b..4b229e4 100644 --- a/tornado-kernel/src/task/shared.rs +++ b/tornado-kernel/src/task/shared.rs @@ -90,6 +90,7 @@ pub static SHARED_RAW_TABLE: (unsafe fn(NonNull<()>, SharedTaskHandle) -> Option /// /// 在内核态和用户态都可以调用,访问的是shared_scheduler对应的同一块内存 #[link_section = ".shared_text"] +#[no_mangle] pub unsafe fn shared_add_task(shared_scheduler: NonNull<()>, handle: SharedTaskHandle) -> Option { let s: NonNull = shared_scheduler.cast(); // println!("Add task: scheduler = {:?}, handle = {:x?}", s, handle); @@ -101,6 +102,7 @@ pub unsafe fn shared_add_task(shared_scheduler: NonNull<()>, handle: SharedTaskH /// /// 在内核态和用户态都可以调用,访问的是shared_scheduler对应的同一块内存 #[link_section = ".shared_text"] +#[no_mangle] pub unsafe fn shared_pop_task(shared_scheduler: NonNull<()>) -> TaskResult { // 得到共享调度器的引用 let mut s: NonNull = shared_scheduler.cast(); diff --git a/tornado-kernel/src/trap/mod.rs b/tornado-kernel/src/trap/mod.rs index ce8219f..5905278 100644 --- a/tornado-kernel/src/trap/mod.rs +++ b/tornado-kernel/src/trap/mod.rs @@ -20,7 +20,7 @@ macro_rules! define_load_store { mod handler; mod timer; -pub use handler::TrapFrame; +pub use handler::{TrapFrame, trap_vector}; /// 初始化中断相关的子模块 /// @@ -103,6 +103,10 @@ impl SwapContext { self.x[1] = sp; self } + pub fn set_gp(&mut self, gp: usize) -> &mut Self { + self.x[2] = gp; + self + } } // 该函数的指针在从内核态返回到用户态之前被写到 stvec 寄存器里面去 @@ -113,7 +117,7 @@ impl SwapContext { #[export_name = "_user_to_supervisor"] pub unsafe extern "C" fn user_to_supervisor() -> ! { asm!( - + ".p2align 2", // 交换 a0 和 sscratch(原先保存着交换栈的栈顶指针) "csrrw a0, sscratch, a0", @@ -249,11 +253,12 @@ pub fn switch_to_user(context: &SwapContext, user_satp: usize) -> ! { // 用户态发生中断时 pc 将会被设置成此值 let user_trap_va = SWAP_FRAME_VA as usize; // 该函数最后应该跳转的虚拟地址 - let jmp_va = supervisor_to_user as usize - _swap_frame as usize + SWAP_FRAME_VA; + let jmp_va = _supervisor_to_user as usize - _swap_frame as usize + SWAP_FRAME_VA; // println!("jmp_va = {:#x}", jmp_va); // 设置用户态陷入内核时需要跳转的地址 unsafe { stvec::write(user_trap_va, TrapMode::Direct); } + // 将 trap::handler 中的 trap_vector 以 Vectored 模式写入到 stvec 寄存器 // 设置 sstatus.SPP 的值为 User unsafe { sstatus::set_spp(SPP::User); } diff --git a/tornado-kernel/src/user.rs b/tornado-kernel/src/user.rs index ae849e9..81c6fa3 100644 --- a/tornado-kernel/src/user.rs +++ b/tornado-kernel/src/user.rs @@ -13,6 +13,10 @@ pub fn try_enter_user(kernel_stack_top: usize) -> ! { fn _test_user_trap(); // 用户程序入口点 fn _test_user_entry(); + fn _sshared_data(); + fn _eshared_data(); + fn _sshared_text(); + fn _eshared_text(); } // println!("_test_user_trap: {:#x}, _test_user_entry: {:#x}", _test_user_trap as usize, _test_user_entry as usize); @@ -55,7 +59,11 @@ pub fn try_enter_user(kernel_stack_top: usize) -> ! { // 往 SwapContext 写东西 // _test_user_entry 由虚拟地址 0 映射到真实物理地址 *swap_cx = trap::SwapContext::new_to_user( - kernel_satp, 0, 0, kernel_stack_top, user_stack_top, _test_user_trap as usize); + kernel_satp, 0, 0, kernel_stack_top, user_stack_top, _test_user_trap as usize + ); + + // 在这里把 .shared_text 段在用户态的虚拟地址通过 gp 寄存器传过去 + swap_cx.set_gp(memory::USER_SHARED_TEXT_VA); // println!("swap_cx.epc: {:#x}", swap_cx.epc); // println!("swap_cx.trap_handler: {:#x}", swap_cx.user_trap_handler); trap::switch_to_user(swap_cx, user_satp) @@ -67,7 +75,7 @@ pub extern "C" fn test_user_trap() { match scause::read().cause() { Trap::Interrupt(Interrupt::SupervisorTimer) => { println!("s mode timer!"); - // 目前遇到时钟中断先让系统退出,等把内核进程队列完善好了再来处理 + // 目前遇到时钟中断先让系统退出,等把内核完善好了再来处理 crate::sbi::shutdown(); }, Trap::Exception(scause::Exception::Breakpoint) => { @@ -75,7 +83,8 @@ pub extern "C" fn test_user_trap() { crate::sbi::shutdown(); }, Trap::Exception(scause::Exception::UserEnvCall) => { - println!("user mode exit."); + println!("ecall from user."); + // 这里先返回到用户态 crate::sbi::shutdown(); } _ => todo!("scause: {:?}, sepc: {:#x}, stval: {:#x}", scause::read().cause(), sepc::read(), stval::read()) diff --git a/tornado-user/src/bin/00-hello-world.rs b/tornado-user/src/bin/00-hello-world.rs deleted file mode 100644 index e0b5e27..0000000 --- a/tornado-user/src/bin/00-hello-world.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello world!"); -} diff --git a/tornado-user/src/main.rs b/tornado-user/src/main.rs index 757fd31..5f21b15 100644 --- a/tornado-user/src/main.rs +++ b/tornado-user/src/main.rs @@ -1,6 +1,7 @@ #![no_std] #![no_main] #![feature(llvm_asm)] +#![feature(asm)] #![feature(panic_info_message)] #![feature(alloc_error_handler)] extern crate alloc; @@ -38,6 +39,11 @@ pub fn handle_alloc_error(_layout: core::alloc::Layout) -> ! { #[link_section = ".text.entry"] #[export_name = "_start"] fn main() -> ! { + unsafe { + asm!( + "lw t0, (gp)" + ); + } unsafe { HEAP.lock().init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE); } diff --git a/tornado-user/src/shared.rs b/tornado-user/src/shared.rs new file mode 100644 index 0000000..8f4a2ea --- /dev/null +++ b/tornado-user/src/shared.rs @@ -0,0 +1,24 @@ +//! 尝试在用户态给共享调度器添加任务 + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(C)] +pub struct SharedTaskHandle { + /// 处理核编号 + pub(crate) hart_id: usize, + /// 地址空间编号 + pub(crate) address_space_id: AddressSpaceId, + /// task_ptr 是 Arc 的虚拟地址 + pub(crate) task_ptr: usize, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct AddressSpaceId(u16); + +impl AddressSpaceId { + pub(crate) unsafe fn from_raw(asid: usize) -> AddressSpaceId { + AddressSpaceId(asid as u16) + } + pub(crate) fn into_inner(self) -> usize { + self.0 as usize + } +} \ No newline at end of file