replace nasm assembly with gcc/clang assembly; add hello_world binary with git lfs

This commit is contained in:
jiangjianfeng 2022-08-30 15:13:51 +08:00
parent 2e28cf5fcb
commit 8bebe380ba
10 changed files with 68 additions and 46 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
src/kxos-user/hello_world/hello_world filter=lfs diff=lfs merge=lfs -text

View File

@ -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
}
}

View File

@ -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<Error> 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")
}
}
}
}

View File

@ -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};

View File

@ -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<F>(task_fn: F) -> Self where F: Fn() + Send + Sync + 'static {
pub fn spawn_kernel_task<F>(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::<u8>, None).expect("spawn kernel task failed");
let exit_code = 0;
Self { pid, task, exit_code }
Self {
pid,
task,
exit_code,
}
}
}

View File

@ -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<Task> {
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?

View File

@ -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 {

View File

@ -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

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0ac54a2485e87769b102225e0a2d7c25e449a01bd0b2504a164fe1ce205acb13
size 9072

View File

@ -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
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: