diff --git a/osdk/tests/examples_in_book/write_a_kernel_in_100_lines_templates/lib.rs b/osdk/tests/examples_in_book/write_a_kernel_in_100_lines_templates/lib.rs index 542873b79..4783698a1 100644 --- a/osdk/tests/examples_in_book/write_a_kernel_in_100_lines_templates/lib.rs +++ b/osdk/tests/examples_in_book/write_a_kernel_in_100_lines_templates/lib.rs @@ -14,12 +14,12 @@ use alloc::vec; use ostd::arch::qemu::{exit_qemu, QemuExitCode}; use ostd::cpu::UserContext; use ostd::mm::{ - CachePolicy, FallibleVmRead, FallibleVmWrite, FrameAllocOptions, PageFlags, PageProperty, - Vaddr, VmIo, VmSpace, VmWriter, PAGE_SIZE, + CachePolicy, FallibleVmRead, FrameAllocOptions, PageFlags, PageProperty, Vaddr, VmIo, VmSpace, + VmWriter, PAGE_SIZE, }; use ostd::prelude::*; use ostd::task::{Task, TaskOptions}; -use ostd::user::{ReturnReason, UserMode, UserSpace}; +use ostd::user::{ReturnReason, UserMode}; /// The kernel's boot and initialization process is managed by OSTD. /// After the process is done, the kernel's execution environment @@ -28,12 +28,13 @@ use ostd::user::{ReturnReason, UserMode, UserSpace}; #[ostd::main] pub fn main() { let program_binary = include_bytes!("../hello"); - let user_space = create_user_space(program_binary); - let user_task = create_user_task(Arc::new(user_space)); + let vm_space = Arc::new(create_vm_space(program_binary)); + vm_space.activate(); + let user_task = create_user_task(vm_space); user_task.run(); } -fn create_user_space(program: &[u8]) -> UserSpace { +fn create_vm_space(program: &[u8]) -> VmSpace { let nbytes = program.len().align_up(PAGE_SIZE); let user_pages = { let segment = FrameAllocOptions::new() @@ -44,42 +45,29 @@ fn create_user_space(program: &[u8]) -> UserSpace { segment.write_bytes(0, program).unwrap(); segment }; - let user_address_space = { - const MAP_ADDR: Vaddr = 0x0040_0000; // The map addr for statically-linked executable - // The page table of the user space can be - // created and manipulated safely through - // the `VmSpace` abstraction. - let vm_space = VmSpace::new(); - let mut cursor = vm_space.cursor_mut(&(MAP_ADDR..MAP_ADDR + nbytes)).unwrap(); - let map_prop = PageProperty::new(PageFlags::RWX, CachePolicy::Writeback); - for frame in user_pages { - cursor.map(frame.into(), map_prop); - } - drop(cursor); - Arc::new(vm_space) - }; - let user_cpu_state = { - const ENTRY_POINT: Vaddr = 0x0040_1000; // The entry point for statically-linked executable - - // The user-space CPU states can be initialized - // to arbitrary values via the UserContext - // abstraction. - let mut user_cpu_state = UserContext::default(); - user_cpu_state.set_rip(ENTRY_POINT); - user_cpu_state - }; - UserSpace::new(user_address_space, user_cpu_state) + // The page table of the user space can be + // created and manipulated safely through + // the `VmSpace` abstraction. + let vm_space = VmSpace::new(); + const MAP_ADDR: Vaddr = 0x0040_0000; // The map addr for statically-linked executable + let mut cursor = vm_space.cursor_mut(&(MAP_ADDR..MAP_ADDR + nbytes)).unwrap(); + let map_prop = PageProperty::new(PageFlags::RWX, CachePolicy::Writeback); + for frame in user_pages { + cursor.map(frame.into(), map_prop); + } + drop(cursor); + vm_space } -fn create_user_task(user_space: Arc) -> Arc { +fn create_user_task(vm_space: Arc) -> Arc { fn user_task() { let current = Task::current().unwrap(); // Switching between user-kernel space is // performed via the UserMode abstraction. let mut user_mode = { - let user_space = current.user_space().unwrap(); - UserMode::new(user_space) + let user_ctx = create_user_context(); + UserMode::new(user_ctx) }; loop { @@ -93,7 +81,8 @@ fn create_user_task(user_space: Arc) -> Arc { // the `UserContext` abstraction. let user_context = user_mode.context_mut(); if ReturnReason::UserSyscall == return_reason { - handle_syscall(user_context, current.user_space().unwrap()); + let vm_space = current.data().downcast_ref::>().unwrap(); + handle_syscall(user_context, &vm_space); } } } @@ -101,16 +90,20 @@ fn create_user_task(user_space: Arc) -> Arc { // Kernel tasks are managed by the Framework, // while scheduling algorithms for them can be // determined by the users of the Framework. - Arc::new( - TaskOptions::new(user_task) - .user_space(Some(user_space)) - .data(0) - .build() - .unwrap(), - ) + Arc::new(TaskOptions::new(user_task).data(vm_space).build().unwrap()) } -fn handle_syscall(user_context: &mut UserContext, user_space: &UserSpace) { +fn create_user_context() -> UserContext { + // The user-space CPU states can be initialized + // to arbitrary values via the `UserContext` + // abstraction. + let mut user_ctx = UserContext::default(); + const ENTRY_POINT: Vaddr = 0x0040_1000; // The entry point for statically-linked executable + user_ctx.set_rip(ENTRY_POINT); + user_ctx +} + +fn handle_syscall(user_context: &mut UserContext, vm_space: &VmSpace) { const SYS_WRITE: usize = 1; const SYS_EXIT: usize = 60; @@ -123,8 +116,7 @@ fn handle_syscall(user_context: &mut UserContext, user_space: &UserSpace) { let mut buf = vec![0u8; buf_len]; // Copy data from the user space without // unsafe pointer dereferencing. - let current_vm_space = user_space.vm_space(); - let mut reader = current_vm_space.reader(buf_addr, buf_len).unwrap(); + let mut reader = vm_space.reader(buf_addr, buf_len).unwrap(); reader .read_fallible(&mut VmWriter::from(&mut buf as &mut [u8])) .unwrap();