mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +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 device;
|
||||
mod error;
|
||||
pub mod log;
|
||||
pub mod prelude;
|
||||
pub mod sync;
|
||||
pub mod task;
|
||||
pub mod timer;
|
||||
pub mod user;
|
||||
mod util;
|
||||
pub mod log;
|
||||
pub mod vm;
|
||||
pub mod sync;
|
||||
|
||||
pub use self::error::Error;
|
||||
use alloc::sync::Arc;
|
||||
|
@ -2,4 +2,4 @@ mod spin;
|
||||
mod wait;
|
||||
|
||||
pub use self::spin::{SpinLock, SpinLockGuard};
|
||||
pub use self::wait::{WaitQueue};
|
||||
pub use self::wait::WaitQueue;
|
||||
|
@ -2,7 +2,7 @@ use core::ops::{Deref, DerefMut};
|
||||
|
||||
/// A spin lock.
|
||||
pub struct SpinLock<T: ?Sized> {
|
||||
val: T,
|
||||
val: T,
|
||||
}
|
||||
|
||||
impl<T> SpinLock<T> {
|
||||
@ -25,7 +25,7 @@ unsafe impl<T: ?Sized + Send> Sync for SpinLock<T> {}
|
||||
|
||||
/// The guard of a spin lock.
|
||||
pub struct SpinLockGuard<'a, T: ?Sized + 'a> {
|
||||
lock: &'a SpinLock<T>
|
||||
lock: &'a SpinLock<T>,
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for SpinLockGuard<'a, T> {
|
||||
@ -36,7 +36,7 @@ impl<'a, T> Deref for SpinLockGuard<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a, T> DerefMut for SpinLockGuard<'a, T> {
|
||||
impl<'a, T> DerefMut for SpinLockGuard<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
todo!()
|
||||
}
|
||||
|
@ -23,6 +23,6 @@ pub fn run_first_process() {
|
||||
Process::spawn_from_elf(elf_file_content);
|
||||
}
|
||||
|
||||
fn read_elf_content<'a>() -> &'a [u8]{
|
||||
todo!()
|
||||
fn read_elf_content() -> &'static [u8] {
|
||||
include_bytes!("../../kxos-user/hello_world/hello_world")
|
||||
}
|
@ -2,7 +2,7 @@ use core::ops::Range;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use kxos_frame::{
|
||||
vm::{Vaddr, VmIo, VmPerm, VmSpace, VmFrameVec, VmAllocOptions},
|
||||
vm::{Vaddr, VmAllocOptions, VmFrameVec, VmIo, VmPerm, VmSpace},
|
||||
Error,
|
||||
};
|
||||
use xmas_elf::{
|
||||
|
@ -1,6 +1,6 @@
|
||||
use alloc::{boxed::Box, collections::VecDeque, sync::Arc};
|
||||
use kxos_frame::task::{set_scheduler, Scheduler, Task};
|
||||
use kxos_frame::sync::SpinLock;
|
||||
use kxos_frame::task::{set_scheduler, Scheduler, Task};
|
||||
|
||||
pub const TASK_INIT_CAPABILITY: usize = 16;
|
||||
|
||||
|
@ -27,7 +27,11 @@ impl Process {
|
||||
let pid = new_pid();
|
||||
let task = spawn_user_task_from_elf(elf_file_content);
|
||||
let exit_code = 0;
|
||||
Self { pid, task, exit_code }
|
||||
Self {
|
||||
pid,
|
||||
task,
|
||||
exit_code,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
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};
|
||||
|
||||
@ -22,7 +27,10 @@ pub fn spawn_user_task_from_elf(elf_file_content: &[u8]) -> Arc<Task> {
|
||||
loop {
|
||||
let user_event = user_mode.execute();
|
||||
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.")
|
||||
}
|
||||
|
||||
fn handle_user_event(user_event: UserEvent, context: &mut CpuContext) {
|
||||
fn handle_user_event(user_event: UserEvent, context: &mut CpuContext) -> HandlerResult {
|
||||
match user_event {
|
||||
UserEvent::Syscall => syscall_handler(context),
|
||||
UserEvent::Fault => todo!(),
|
||||
UserEvent::Exception => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub enum HandlerResult {
|
||||
Exit,
|
||||
Continue,
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
use alloc::vec;
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use kxos_frame::Error;
|
||||
use kxos_frame::cpu::CpuContext;
|
||||
use kxos_frame::Error;
|
||||
use kxos_frame::{task::Task, user::UserSpace, vm::VmIo};
|
||||
|
||||
use kxos_frame::info;
|
||||
|
||||
use crate::process::task::HandlerResult;
|
||||
|
||||
const SYS_WRITE: u64 = 64;
|
||||
const SYS_EXIT: u64 = 93;
|
||||
|
||||
@ -14,6 +16,11 @@ pub struct SyscallFrame {
|
||||
args: [u64; 6],
|
||||
}
|
||||
|
||||
pub enum SyscallResult {
|
||||
Exit(i32),
|
||||
Return(i32),
|
||||
}
|
||||
|
||||
impl SyscallFrame {
|
||||
fn new_from_context(context: &CpuContext) -> Self {
|
||||
let syscall_number = context.gp_regs.rax;
|
||||
@ -25,20 +32,27 @@ impl SyscallFrame {
|
||||
args[4] = context.gp_regs.r8;
|
||||
args[5] = context.gp_regs.r9;
|
||||
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_return = syscall_dispatch(syscall_frame.syscall_number, syscall_frame.args);
|
||||
|
||||
// FIXME: set return value?
|
||||
context.gp_regs.rax = syscall_return as u64;
|
||||
match syscall_return {
|
||||
SyscallResult::Return(return_value) => {
|
||||
// FIXME: set return value?
|
||||
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 {
|
||||
SYS_WRITE => sys_write(args[0], args[1], args[2]),
|
||||
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.
|
||||
const STDOUT: u64 = 1;
|
||||
if fd == STDOUT {
|
||||
let task = Task::current();
|
||||
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)
|
||||
.expect("read user buffer failed");
|
||||
let user_buffer =
|
||||
copy_bytes_from_user(user_space, user_buf_ptr as usize, user_buf_len as usize)
|
||||
.expect("read user buffer failed");
|
||||
let content = alloc::str::from_utf8(user_buffer.as_slice()).expect("Invalid content");
|
||||
// TODO: print content
|
||||
info!("Message from user mode: {}", content);
|
||||
0
|
||||
SyscallResult::Return(0)
|
||||
} else {
|
||||
panic!("Unsupported fd number {}", fd);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_exit(exit_code: i32) -> isize {
|
||||
// let current = Task::current();
|
||||
// current.exit(exit_code);
|
||||
todo!()
|
||||
pub fn sys_exit(exit_code: i32) -> SyscallResult {
|
||||
SyscallResult::Exit(exit_code)
|
||||
}
|
||||
|
||||
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