mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-12 23:06:51 +00:00
Modify the 100-lines example
This commit is contained in:
parent
135100a472
commit
af4cf19eb4
@ -14,12 +14,12 @@ use alloc::vec;
|
|||||||
use ostd::arch::qemu::{exit_qemu, QemuExitCode};
|
use ostd::arch::qemu::{exit_qemu, QemuExitCode};
|
||||||
use ostd::cpu::UserContext;
|
use ostd::cpu::UserContext;
|
||||||
use ostd::mm::{
|
use ostd::mm::{
|
||||||
CachePolicy, FallibleVmRead, FallibleVmWrite, FrameAllocOptions, PageFlags, PageProperty,
|
CachePolicy, FallibleVmRead, FrameAllocOptions, PageFlags, PageProperty, Vaddr, VmIo, VmSpace,
|
||||||
Vaddr, VmIo, VmSpace, VmWriter, PAGE_SIZE,
|
VmWriter, PAGE_SIZE,
|
||||||
};
|
};
|
||||||
use ostd::prelude::*;
|
use ostd::prelude::*;
|
||||||
use ostd::task::{Task, TaskOptions};
|
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.
|
/// The kernel's boot and initialization process is managed by OSTD.
|
||||||
/// After the process is done, the kernel's execution environment
|
/// After the process is done, the kernel's execution environment
|
||||||
@ -28,12 +28,13 @@ use ostd::user::{ReturnReason, UserMode, UserSpace};
|
|||||||
#[ostd::main]
|
#[ostd::main]
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let program_binary = include_bytes!("../hello");
|
let program_binary = include_bytes!("../hello");
|
||||||
let user_space = create_user_space(program_binary);
|
let vm_space = Arc::new(create_vm_space(program_binary));
|
||||||
let user_task = create_user_task(Arc::new(user_space));
|
vm_space.activate();
|
||||||
|
let user_task = create_user_task(vm_space);
|
||||||
user_task.run();
|
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 nbytes = program.len().align_up(PAGE_SIZE);
|
||||||
let user_pages = {
|
let user_pages = {
|
||||||
let segment = FrameAllocOptions::new()
|
let segment = FrameAllocOptions::new()
|
||||||
@ -44,42 +45,29 @@ fn create_user_space(program: &[u8]) -> UserSpace {
|
|||||||
segment.write_bytes(0, program).unwrap();
|
segment.write_bytes(0, program).unwrap();
|
||||||
segment
|
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
|
// The page table of the user space can be
|
||||||
// created and manipulated safely through
|
// created and manipulated safely through
|
||||||
// the `VmSpace` abstraction.
|
// the `VmSpace` abstraction.
|
||||||
let vm_space = VmSpace::new();
|
let vm_space = VmSpace::new();
|
||||||
let mut cursor = vm_space.cursor_mut(&(MAP_ADDR..MAP_ADDR + nbytes)).unwrap();
|
const MAP_ADDR: Vaddr = 0x0040_0000; // The map addr for statically-linked executable
|
||||||
let map_prop = PageProperty::new(PageFlags::RWX, CachePolicy::Writeback);
|
let mut cursor = vm_space.cursor_mut(&(MAP_ADDR..MAP_ADDR + nbytes)).unwrap();
|
||||||
for frame in user_pages {
|
let map_prop = PageProperty::new(PageFlags::RWX, CachePolicy::Writeback);
|
||||||
cursor.map(frame.into(), map_prop);
|
for frame in user_pages {
|
||||||
}
|
cursor.map(frame.into(), map_prop);
|
||||||
drop(cursor);
|
}
|
||||||
Arc::new(vm_space)
|
drop(cursor);
|
||||||
};
|
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_user_task(user_space: Arc<UserSpace>) -> Arc<Task> {
|
fn create_user_task(vm_space: Arc<VmSpace>) -> Arc<Task> {
|
||||||
fn user_task() {
|
fn user_task() {
|
||||||
let current = Task::current().unwrap();
|
let current = Task::current().unwrap();
|
||||||
// Switching between user-kernel space is
|
// Switching between user-kernel space is
|
||||||
// performed via the UserMode abstraction.
|
// performed via the UserMode abstraction.
|
||||||
let mut user_mode = {
|
let mut user_mode = {
|
||||||
let user_space = current.user_space().unwrap();
|
let user_ctx = create_user_context();
|
||||||
UserMode::new(user_space)
|
UserMode::new(user_ctx)
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@ -93,7 +81,8 @@ fn create_user_task(user_space: Arc<UserSpace>) -> Arc<Task> {
|
|||||||
// the `UserContext` abstraction.
|
// the `UserContext` abstraction.
|
||||||
let user_context = user_mode.context_mut();
|
let user_context = user_mode.context_mut();
|
||||||
if ReturnReason::UserSyscall == return_reason {
|
if ReturnReason::UserSyscall == return_reason {
|
||||||
handle_syscall(user_context, current.user_space().unwrap());
|
let vm_space = current.data().downcast_ref::<Arc<VmSpace>>().unwrap();
|
||||||
|
handle_syscall(user_context, &vm_space);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,16 +90,20 @@ fn create_user_task(user_space: Arc<UserSpace>) -> Arc<Task> {
|
|||||||
// Kernel tasks are managed by the Framework,
|
// Kernel tasks are managed by the Framework,
|
||||||
// while scheduling algorithms for them can be
|
// while scheduling algorithms for them can be
|
||||||
// determined by the users of the Framework.
|
// determined by the users of the Framework.
|
||||||
Arc::new(
|
Arc::new(TaskOptions::new(user_task).data(vm_space).build().unwrap())
|
||||||
TaskOptions::new(user_task)
|
|
||||||
.user_space(Some(user_space))
|
|
||||||
.data(0)
|
|
||||||
.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_WRITE: usize = 1;
|
||||||
const SYS_EXIT: usize = 60;
|
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];
|
let mut buf = vec![0u8; buf_len];
|
||||||
// Copy data from the user space without
|
// Copy data from the user space without
|
||||||
// unsafe pointer dereferencing.
|
// unsafe pointer dereferencing.
|
||||||
let current_vm_space = user_space.vm_space();
|
let mut reader = vm_space.reader(buf_addr, buf_len).unwrap();
|
||||||
let mut reader = current_vm_space.reader(buf_addr, buf_len).unwrap();
|
|
||||||
reader
|
reader
|
||||||
.read_fallible(&mut VmWriter::from(&mut buf as &mut [u8]))
|
.read_fallible(&mut VmWriter::from(&mut buf as &mut [u8]))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user