diff --git a/src/kxos-frame/src/lib.rs b/src/kxos-frame/src/lib.rs index add3fa94..b4ba69ca 100644 --- a/src/kxos-frame/src/lib.rs +++ b/src/kxos-frame/src/lib.rs @@ -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; diff --git a/src/kxos-frame/src/log.rs b/src/kxos-frame/src/log.rs index a54045c3..82c3e4cc 100644 --- a/src/kxos-frame/src/log.rs +++ b/src/kxos-frame/src/log.rs @@ -59,4 +59,4 @@ macro_rules! error { $crate::log_print!($($arg)*); $crate::log_print!("\n"); }; -} \ No newline at end of file +} diff --git a/src/kxos-frame/src/sync/mod.rs b/src/kxos-frame/src/sync/mod.rs index a9887a14..751ffd84 100644 --- a/src/kxos-frame/src/sync/mod.rs +++ b/src/kxos-frame/src/sync/mod.rs @@ -2,4 +2,4 @@ mod spin; mod wait; pub use self::spin::{SpinLock, SpinLockGuard}; -pub use self::wait::{WaitQueue}; \ No newline at end of file +pub use self::wait::WaitQueue; diff --git a/src/kxos-frame/src/sync/spin.rs b/src/kxos-frame/src/sync/spin.rs index 8968a4cf..1b92ff1a 100644 --- a/src/kxos-frame/src/sync/spin.rs +++ b/src/kxos-frame/src/sync/spin.rs @@ -2,7 +2,7 @@ use core::ops::{Deref, DerefMut}; /// A spin lock. pub struct SpinLock { - val: T, + val: T, } impl SpinLock { @@ -11,8 +11,8 @@ impl SpinLock { todo!() } - /// Acquire the spin lock. - /// + /// Acquire the spin lock. + /// /// This method runs in a busy loop until the lock can be acquired. /// After acquiring the spin lock, all interrupts are disabled. pub fn lock<'a>(&self) -> SpinLockGuard<'a, T> { @@ -25,7 +25,7 @@ unsafe impl Sync for SpinLock {} /// The guard of a spin lock. pub struct SpinLockGuard<'a, T: ?Sized + 'a> { - lock: &'a SpinLock + lock: &'a SpinLock, } 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!() } @@ -44,4 +44,4 @@ impl <'a, T> DerefMut for SpinLockGuard<'a, T> { impl<'a, T: ?Sized> !Send for SpinLockGuard<'a, T> {} -unsafe impl Sync for SpinLockGuard<'_, T> {} \ No newline at end of file +unsafe impl Sync for SpinLockGuard<'_, T> {} diff --git a/src/kxos-std/src/lib.rs b/src/kxos-std/src/lib.rs index 7c9c9e11..065a8732 100644 --- a/src/kxos-std/src/lib.rs +++ b/src/kxos-std/src/lib.rs @@ -23,6 +23,6 @@ pub fn run_first_process() { Process::spawn_from_elf(elf_file_content); } -fn read_elf_content<'a>() -> &'a [u8]{ - todo!() -} \ No newline at end of file +fn read_elf_content() -> &'static [u8] { + include_bytes!("../../kxos-user/hello_world/hello_world") +} diff --git a/src/kxos-std/src/memory/elf.rs b/src/kxos-std/src/memory/elf.rs index a6700e90..a817f176 100644 --- a/src/kxos-std/src/memory/elf.rs +++ b/src/kxos-std/src/memory/elf.rs @@ -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::{ diff --git a/src/kxos-std/src/process/fifo_scheduler.rs b/src/kxos-std/src/process/fifo_scheduler.rs index e03227af..5ab36106 100644 --- a/src/kxos-std/src/process/fifo_scheduler.rs +++ b/src/kxos-std/src/process/fifo_scheduler.rs @@ -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; diff --git a/src/kxos-std/src/process/mod.rs b/src/kxos-std/src/process/mod.rs index 0ab02964..27410c2a 100644 --- a/src/kxos-std/src/process/mod.rs +++ b/src/kxos-std/src/process/mod.rs @@ -19,7 +19,7 @@ pub struct Process { task: Arc, exit_code: i32, // user_space: Option>, - // TODO: childs, parent, files, + // TODO: childs, parent, files, } impl Process { @@ -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, + } } } diff --git a/src/kxos-std/src/process/task.rs b/src/kxos-std/src/process/task.rs index a4aae7aa..f0b17079 100644 --- a/src/kxos-std/src/process/task.rs +++ b/src/kxos-std/src/process/task.rs @@ -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 { 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::spawn(user_task_entry, None::, 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!(), } -} \ No newline at end of file +} + +pub enum HandlerResult { + Exit, + Continue, +} diff --git a/src/kxos-std/src/syscall/mod.rs b/src/kxos-std/src/syscall/mod.rs index 75a8480e..40491efd 100644 --- a/src/kxos-std/src/syscall/mod.rs +++ b/src/kxos-std/src/syscall/mod.rs @@ -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( diff --git a/src/kxos-user/hello_world/Makefile b/src/kxos-user/hello_world/Makefile new file mode 100644 index 00000000..2e439425 --- /dev/null +++ b/src/kxos-user/hello_world/Makefile @@ -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 diff --git a/src/kxos-user/hello_world/hello_world.s b/src/kxos-user/hello_world/hello_world.s new file mode 100644 index 00000000..c55da226 --- /dev/null +++ b/src/kxos-user/hello_world/hello_world.s @@ -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 \ No newline at end of file