mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
add user-mode hello_world; support syscall exit
This commit is contained in:
parent
40f5b81252
commit
e6569edbe2
@ -15,14 +15,14 @@ pub mod config;
|
|||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
pub mod device;
|
pub mod device;
|
||||||
mod error;
|
mod error;
|
||||||
|
pub mod log;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
pub mod sync;
|
||||||
pub mod task;
|
pub mod task;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
mod util;
|
mod util;
|
||||||
pub mod log;
|
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
pub mod sync;
|
|
||||||
|
|
||||||
pub use self::error::Error;
|
pub use self::error::Error;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
@ -2,4 +2,4 @@ mod spin;
|
|||||||
mod wait;
|
mod wait;
|
||||||
|
|
||||||
pub use self::spin::{SpinLock, SpinLockGuard};
|
pub use self::spin::{SpinLock, SpinLockGuard};
|
||||||
pub use self::wait::{WaitQueue};
|
pub use self::wait::WaitQueue;
|
||||||
|
@ -25,7 +25,7 @@ unsafe impl<T: ?Sized + Send> Sync for SpinLock<T> {}
|
|||||||
|
|
||||||
/// The guard of a spin lock.
|
/// The guard of a spin lock.
|
||||||
pub struct SpinLockGuard<'a, T: ?Sized + 'a> {
|
pub struct SpinLockGuard<'a, T: ?Sized + 'a> {
|
||||||
lock: &'a SpinLock<T>
|
lock: &'a SpinLock<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> Deref for SpinLockGuard<'a, T> {
|
impl<'a, T> Deref for SpinLockGuard<'a, T> {
|
||||||
|
@ -23,6 +23,6 @@ pub fn run_first_process() {
|
|||||||
Process::spawn_from_elf(elf_file_content);
|
Process::spawn_from_elf(elf_file_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_elf_content<'a>() -> &'a [u8]{
|
fn read_elf_content() -> &'static [u8] {
|
||||||
todo!()
|
include_bytes!("../../kxos-user/hello_world/hello_world")
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ use core::ops::Range;
|
|||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use kxos_frame::{
|
use kxos_frame::{
|
||||||
vm::{Vaddr, VmIo, VmPerm, VmSpace, VmFrameVec, VmAllocOptions},
|
vm::{Vaddr, VmAllocOptions, VmFrameVec, VmIo, VmPerm, VmSpace},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
use xmas_elf::{
|
use xmas_elf::{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use alloc::{boxed::Box, collections::VecDeque, sync::Arc};
|
use alloc::{boxed::Box, collections::VecDeque, sync::Arc};
|
||||||
use kxos_frame::task::{set_scheduler, Scheduler, Task};
|
|
||||||
use kxos_frame::sync::SpinLock;
|
use kxos_frame::sync::SpinLock;
|
||||||
|
use kxos_frame::task::{set_scheduler, Scheduler, Task};
|
||||||
|
|
||||||
pub const TASK_INIT_CAPABILITY: usize = 16;
|
pub const TASK_INIT_CAPABILITY: usize = 16;
|
||||||
|
|
||||||
|
@ -27,7 +27,11 @@ impl Process {
|
|||||||
let pid = new_pid();
|
let pid = new_pid();
|
||||||
let task = spawn_user_task_from_elf(elf_file_content);
|
let task = spawn_user_task_from_elf(elf_file_content);
|
||||||
let exit_code = 0;
|
let exit_code = 0;
|
||||||
Self { pid, task, exit_code }
|
Self {
|
||||||
|
pid,
|
||||||
|
task,
|
||||||
|
exit_code,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use kxos_frame::{cpu::CpuContext, task::Task, user::{UserSpace, UserEvent}, vm::VmSpace};
|
use kxos_frame::{
|
||||||
|
cpu::CpuContext,
|
||||||
|
task::Task,
|
||||||
|
user::{UserEvent, UserSpace},
|
||||||
|
vm::VmSpace,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{memory::load_elf_to_vm_space, syscall::syscall_handler};
|
use crate::{memory::load_elf_to_vm_space, syscall::syscall_handler};
|
||||||
|
|
||||||
@ -22,7 +27,10 @@ pub fn spawn_user_task_from_elf(elf_file_content: &[u8]) -> Arc<Task> {
|
|||||||
loop {
|
loop {
|
||||||
let user_event = user_mode.execute();
|
let user_event = user_mode.execute();
|
||||||
let context = user_mode.context_mut();
|
let context = user_mode.context_mut();
|
||||||
handle_user_event(user_event, context);
|
if let HandlerResult::Exit = handle_user_event(user_event, context) {
|
||||||
|
// FIXME: How to set task status? How to set exit code of process?
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,10 +38,15 @@ pub fn spawn_user_task_from_elf(elf_file_content: &[u8]) -> Arc<Task> {
|
|||||||
Task::spawn(user_task_entry, None::<u8>, Some(user_space)).expect("spawn user task failed.")
|
Task::spawn(user_task_entry, None::<u8>, Some(user_space)).expect("spawn user task failed.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_user_event(user_event: UserEvent, context: &mut CpuContext) {
|
fn handle_user_event(user_event: UserEvent, context: &mut CpuContext) -> HandlerResult {
|
||||||
match user_event {
|
match user_event {
|
||||||
UserEvent::Syscall => syscall_handler(context),
|
UserEvent::Syscall => syscall_handler(context),
|
||||||
UserEvent::Fault => todo!(),
|
UserEvent::Fault => todo!(),
|
||||||
UserEvent::Exception => todo!(),
|
UserEvent::Exception => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum HandlerResult {
|
||||||
|
Exit,
|
||||||
|
Continue,
|
||||||
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
use kxos_frame::Error;
|
|
||||||
use kxos_frame::cpu::CpuContext;
|
use kxos_frame::cpu::CpuContext;
|
||||||
|
use kxos_frame::Error;
|
||||||
use kxos_frame::{task::Task, user::UserSpace, vm::VmIo};
|
use kxos_frame::{task::Task, user::UserSpace, vm::VmIo};
|
||||||
|
|
||||||
use kxos_frame::info;
|
use kxos_frame::info;
|
||||||
|
|
||||||
|
use crate::process::task::HandlerResult;
|
||||||
|
|
||||||
const SYS_WRITE: u64 = 64;
|
const SYS_WRITE: u64 = 64;
|
||||||
const SYS_EXIT: u64 = 93;
|
const SYS_EXIT: u64 = 93;
|
||||||
|
|
||||||
@ -14,6 +16,11 @@ pub struct SyscallFrame {
|
|||||||
args: [u64; 6],
|
args: [u64; 6],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum SyscallResult {
|
||||||
|
Exit(i32),
|
||||||
|
Return(i32),
|
||||||
|
}
|
||||||
|
|
||||||
impl SyscallFrame {
|
impl SyscallFrame {
|
||||||
fn new_from_context(context: &CpuContext) -> Self {
|
fn new_from_context(context: &CpuContext) -> Self {
|
||||||
let syscall_number = context.gp_regs.rax;
|
let syscall_number = context.gp_regs.rax;
|
||||||
@ -25,20 +32,27 @@ impl SyscallFrame {
|
|||||||
args[4] = context.gp_regs.r8;
|
args[4] = context.gp_regs.r8;
|
||||||
args[5] = context.gp_regs.r9;
|
args[5] = context.gp_regs.r9;
|
||||||
Self {
|
Self {
|
||||||
syscall_number, args,
|
syscall_number,
|
||||||
|
args,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn syscall_handler(context: &mut CpuContext) {
|
pub fn syscall_handler(context: &mut CpuContext) -> HandlerResult {
|
||||||
let syscall_frame = SyscallFrame::new_from_context(context);
|
let syscall_frame = SyscallFrame::new_from_context(context);
|
||||||
let syscall_return = syscall_dispatch(syscall_frame.syscall_number, syscall_frame.args);
|
let syscall_return = syscall_dispatch(syscall_frame.syscall_number, syscall_frame.args);
|
||||||
|
|
||||||
|
match syscall_return {
|
||||||
|
SyscallResult::Return(return_value) => {
|
||||||
// FIXME: set return value?
|
// FIXME: set return value?
|
||||||
context.gp_regs.rax = syscall_return as u64;
|
context.gp_regs.rax = return_value as u64;
|
||||||
|
HandlerResult::Continue
|
||||||
|
}
|
||||||
|
SyscallResult::Exit(exit_code) => HandlerResult::Exit,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn syscall_dispatch(syscall_number: u64, args: [u64; 6]) -> isize {
|
pub fn syscall_dispatch(syscall_number: u64, args: [u64; 6]) -> SyscallResult {
|
||||||
match syscall_number {
|
match syscall_number {
|
||||||
SYS_WRITE => sys_write(args[0], args[1], args[2]),
|
SYS_WRITE => sys_write(args[0], args[1], args[2]),
|
||||||
SYS_EXIT => sys_exit(args[0] as _),
|
SYS_EXIT => sys_exit(args[0] as _),
|
||||||
@ -46,27 +60,26 @@ pub fn syscall_dispatch(syscall_number: u64, args: [u64; 6]) -> isize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> isize {
|
pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> SyscallResult {
|
||||||
// only suppprt STDOUT now.
|
// only suppprt STDOUT now.
|
||||||
const STDOUT: u64 = 1;
|
const STDOUT: u64 = 1;
|
||||||
if fd == STDOUT {
|
if fd == STDOUT {
|
||||||
let task = Task::current();
|
let task = Task::current();
|
||||||
let user_space = task.user_space().expect("No user space attached");
|
let user_space = task.user_space().expect("No user space attached");
|
||||||
let user_buffer = copy_bytes_from_user(user_space, user_buf_ptr as usize, user_buf_len as usize)
|
let user_buffer =
|
||||||
|
copy_bytes_from_user(user_space, user_buf_ptr as usize, user_buf_len as usize)
|
||||||
.expect("read user buffer failed");
|
.expect("read user buffer failed");
|
||||||
let content = alloc::str::from_utf8(user_buffer.as_slice()).expect("Invalid content");
|
let content = alloc::str::from_utf8(user_buffer.as_slice()).expect("Invalid content");
|
||||||
// TODO: print content
|
// TODO: print content
|
||||||
info!("Message from user mode: {}", content);
|
info!("Message from user mode: {}", content);
|
||||||
0
|
SyscallResult::Return(0)
|
||||||
} else {
|
} else {
|
||||||
panic!("Unsupported fd number {}", fd);
|
panic!("Unsupported fd number {}", fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_exit(exit_code: i32) -> isize {
|
pub fn sys_exit(exit_code: i32) -> SyscallResult {
|
||||||
// let current = Task::current();
|
SyscallResult::Exit(exit_code)
|
||||||
// current.exit(exit_code);
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_bytes_from_user(
|
fn copy_bytes_from_user(
|
||||||
|
9
src/kxos-user/hello_world/Makefile
Normal file
9
src/kxos-user/hello_world/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.PHONY: build clean run
|
||||||
|
build: hello_world.s
|
||||||
|
@nasm -f elf64 hello_world.s -o hello_world.o
|
||||||
|
@ld hello_world.o -o hello_world
|
||||||
|
@rm hello_world.o
|
||||||
|
clean:
|
||||||
|
@rm hello_world
|
||||||
|
run: build
|
||||||
|
@./hello_world
|
18
src/kxos-user/hello_world/hello_world.s
Normal file
18
src/kxos-user/hello_world/hello_world.s
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
global _start
|
||||||
|
|
||||||
|
section .text
|
||||||
|
|
||||||
|
_start:
|
||||||
|
mov rax, 1 ; syswrite
|
||||||
|
mov rdi, 1 ; fd
|
||||||
|
mov rsi, msg ; "Hello, world!\n",
|
||||||
|
mov rdx, msglen ; sizeof("Hello, world!\n")
|
||||||
|
syscall
|
||||||
|
|
||||||
|
mov rax, 60 ; sys_exit
|
||||||
|
mov rdi, 0 ; exit_code
|
||||||
|
syscall
|
||||||
|
|
||||||
|
section .rodata
|
||||||
|
msg: db "Hello, world!", 10
|
||||||
|
msglen: equ $ - msg
|
Loading…
x
Reference in New Issue
Block a user