diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..54859819 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +src/kxos-user/hello_world/hello_world filter=lfs diff=lfs merge=lfs -text diff --git a/src/kxos-frame/src/user.rs b/src/kxos-frame/src/user.rs index 0cd21525..ac0b0ef0 100644 --- a/src/kxos-frame/src/user.rs +++ b/src/kxos-frame/src/user.rs @@ -111,6 +111,7 @@ impl<'a> UserMode<'a> { self.user_space.vm_space().activate(); if !self.executed { self.current.syscall_frame().caller.rcx = self.user_space.cpu_ctx.gp_regs.rip as usize; + self.current.syscall_frame().callee.rsp = self.user_space.cpu_ctx.gp_regs.rsp as usize; self.executed = true; } else { if self.current.inner_exclusive_access().is_from_trap { @@ -137,6 +138,7 @@ impl<'a> UserMode<'a> { } else { self.context = CpuContext::from(*self.current.syscall_frame()); println!("[kernel] syscall id:{}",self.context.gp_regs.rax); + println!("[kernel] rsp: 0x{:x}", self.context.gp_regs.rsp); UserEvent::Syscall } } diff --git a/src/kxos-std/src/memory/elf.rs b/src/kxos-std/src/memory/elf.rs index ff39e2f9..2338bd39 100644 --- a/src/kxos-std/src/memory/elf.rs +++ b/src/kxos-std/src/memory/elf.rs @@ -1,10 +1,11 @@ -use core::{ops::Range, cmp::Ordering}; +use core::{cmp::Ordering, ops::Range}; -use alloc::vec::Vec; use alloc::vec; +use alloc::vec::Vec; use kxos_frame::{ - vm::{Vaddr, VmAllocOptions, VmFrameVec, VmIo, VmPerm, VmSpace, VmMapOptions}, - Error, config::PAGE_SIZE, + config::PAGE_SIZE, + vm::{Vaddr, VmAllocOptions, VmFrameVec, VmIo, VmMapOptions, VmPerm, VmSpace}, + Error, }; use xmas_elf::{ header, @@ -39,7 +40,7 @@ impl<'a> ElfSegment<'a> { Ok(type_) => type_, }; let data = match read_segment_data(segment, elf_file) { - Err(_) => return Err(ElfError::from("")), + Err(msg) => return Err(ElfError::from(msg)), Ok(data) => data, }; let vm_perm = Self::parse_segment_perm(segment)?; @@ -58,7 +59,7 @@ impl<'a> ElfSegment<'a> { } let mut vm_perm = VmPerm::R; if flags.is_write() { - vm_perm |= VmPerm::W; + vm_perm |= VmPerm::W; } if flags.is_execute() { vm_perm |= VmPerm::X; @@ -188,8 +189,10 @@ impl<'a> ElfLoadInfo<'a> { for segment in self.segments.iter() { let start_address = segment.start_address(); let len = segment.data.len(); - let mut read_buffer = vec![0;len]; - vm_space.read_bytes(start_address, &mut read_buffer).expect("read bytes failed"); + let mut read_buffer = vec![0; len]; + vm_space + .read_bytes(start_address, &mut read_buffer) + .expect("read bytes failed"); let res = segment.data.cmp(&read_buffer); assert_eq!(res, Ordering::Equal); } @@ -255,14 +258,17 @@ impl From for ElfError { fn read_segment_data<'a>( segment: ProgramHeader<'a>, elf_file: &ElfFile<'a>, -) -> Result<&'a [u8], ()> { +) -> Result<&'a [u8], &'static str> { match segment.get_data(&elf_file) { - Err(_) => Err(()), + Err(msg) => Err(msg), Ok(data) => { - if let SegmentData::Undefined(data) = data { - Ok(data) - } else { - Err(()) + match data { + SegmentData::Note64(_, data) | SegmentData::Undefined(data) => { + Ok(data) + }, + _ => { + Err("Unkonwn segment data type") + } } } } diff --git a/src/kxos-std/src/memory/mod.rs b/src/kxos-std/src/memory/mod.rs index f2aadb5b..610bb9de 100644 --- a/src/kxos-std/src/memory/mod.rs +++ b/src/kxos-std/src/memory/mod.rs @@ -1,7 +1,7 @@ pub mod elf; pub mod user_stack; pub mod vm_page; -use kxos_frame::{vm::VmSpace, debug}; +use kxos_frame::{debug, vm::VmSpace}; use self::elf::{ElfError, ElfLoadInfo}; diff --git a/src/kxos-std/src/process/mod.rs b/src/kxos-std/src/process/mod.rs index 5c5adeb2..b9445d2c 100644 --- a/src/kxos-std/src/process/mod.rs +++ b/src/kxos-std/src/process/mod.rs @@ -2,7 +2,7 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use alloc::sync::Arc; // use kxos_frame::{sync::SpinLock, task::Task, user::UserSpace}; -use kxos_frame::{task::Task, debug}; +use kxos_frame::{debug, task::Task}; use self::task::spawn_user_task_from_elf; @@ -34,12 +34,19 @@ impl Process { } } - pub fn spawn_kernel_task(task_fn: F) -> Self where F: Fn() + Send + Sync + 'static { + pub fn spawn_kernel_task(task_fn: F) -> Self + where + F: Fn() + Send + Sync + 'static, + { let pid = new_pid(); - debug!("pid = {}" , pid); + debug!("pid = {}", pid); let task = Task::spawn(task_fn, None::, None).expect("spawn kernel task failed"); 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 7da322d8..2bf6b66a 100644 --- a/src/kxos-std/src/process/task.rs +++ b/src/kxos-std/src/process/task.rs @@ -1,10 +1,9 @@ use alloc::sync::Arc; use kxos_frame::{ cpu::CpuContext, - println, task::Task, user::{UserEvent, UserMode, UserSpace}, - vm::VmSpace, + vm::VmSpace, debug, }; use crate::{memory::load_elf_to_vm_space, syscall::syscall_handler}; @@ -27,6 +26,7 @@ pub fn spawn_user_task_from_elf(elf_file_content: &[u8]) -> Arc { let mut user_mode = UserMode::new(user_space); loop { let user_event = user_mode.execute(); + debug!("return from user mode"); let context = user_mode.context_mut(); if let HandlerResult::Exit = handle_user_event(user_event, context) { // FIXME: How to set task status? How to set exit code of process? diff --git a/src/kxos-std/src/syscall/mod.rs b/src/kxos-std/src/syscall/mod.rs index bff5ad64..b5716c19 100644 --- a/src/kxos-std/src/syscall/mod.rs +++ b/src/kxos-std/src/syscall/mod.rs @@ -1,4 +1,3 @@ -use alloc::ffi::CString; use alloc::vec; use alloc::{sync::Arc, vec::Vec}; use kxos_frame::cpu::CpuContext; @@ -12,7 +11,7 @@ use crate::process::task::HandlerResult; const SYS_WRITE: u64 = 1; const SYS_EXIT: u64 = 60; -pub struct SyscallFrame { +pub struct SyscallArgument { syscall_number: u64, args: [u64; 6], } @@ -22,7 +21,7 @@ pub enum SyscallResult { Return(i32), } -impl SyscallFrame { +impl SyscallArgument { fn new_from_context(context: &CpuContext) -> Self { let syscall_number = context.gp_regs.rax; let mut args = [0u64; 6]; @@ -40,7 +39,7 @@ impl SyscallFrame { } pub fn syscall_handler(context: &mut CpuContext) -> HandlerResult { - let syscall_frame = SyscallFrame::new_from_context(context); + let syscall_frame = SyscallArgument::new_from_context(context); let syscall_return = syscall_dispatch(syscall_frame.syscall_number, syscall_frame.args); match syscall_return { @@ -70,7 +69,7 @@ pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> SyscallResult 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 + let content = alloc::str::from_utf8(user_buffer.as_slice()).expect("Invalid content"); // TODO: print content info!("Message from user mode: {:?}", content); SyscallResult::Return(0) } else { diff --git a/src/kxos-user/hello_world/Makefile b/src/kxos-user/hello_world/Makefile index 2e439425..69261d76 100644 --- a/src/kxos-user/hello_world/Makefile +++ b/src/kxos-user/hello_world/Makefile @@ -1,9 +1,7 @@ .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 + @gcc -static -nostdlib hello_world.s -o hello_world clean: @rm hello_world run: build - @./hello_world + @./hello_world \ No newline at end of file diff --git a/src/kxos-user/hello_world/hello_world b/src/kxos-user/hello_world/hello_world new file mode 100755 index 00000000..33b035c6 --- /dev/null +++ b/src/kxos-user/hello_world/hello_world @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ac54a2485e87769b102225e0a2d7c25e449a01bd0b2504a164fe1ce205acb13 +size 9072 diff --git a/src/kxos-user/hello_world/hello_world.s b/src/kxos-user/hello_world/hello_world.s index c55da226..0baea631 100644 --- a/src/kxos-user/hello_world/hello_world.s +++ b/src/kxos-user/hello_world/hello_world.s @@ -1,18 +1,24 @@ -global _start - -section .text +.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 + call print_message + call print_message + call print_message + mov $60, %rax # syscall number of exit + mov $0, %rdi # exit code + syscall +print_message: + mov $1, %rax # syscall number of write + mov $1, %rdi # stdout + mov $message, %rsi # address of message + mov $message, %r11 + mov $message_end, %r12 + sub %r11, %r12 # calculate message len + mov %r12, %rdx # number of bytes + syscall + ret +.section .rodata +message: + .ascii "Hello, world\n" +message_end: