mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Merge pull request #17 from StevenJiang1110/main
Add hello_world binary with git lfs
This commit is contained in:
commit
7e733a83eb
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
src/kxos-user/hello_world/hello_world filter=lfs diff=lfs merge=lfs -text
|
15
README.md
15
README.md
@ -34,6 +34,21 @@ While there is nothing revolutionary in KxOS, it does explore some new design po
|
|||||||
While most code is written in Rust, the project-scope build process is governed
|
While most code is written in Rust, the project-scope build process is governed
|
||||||
by Makefile.
|
by Makefile.
|
||||||
|
|
||||||
|
Before downloading source code, install and init Git LFS since the project manage binaries with Git LFS.
|
||||||
|
```bash
|
||||||
|
# 1. install git-lfs
|
||||||
|
brew install git-lfs # for mac
|
||||||
|
apt install git-lfs # for ubuntu
|
||||||
|
|
||||||
|
# 2. init git-lfs for current user
|
||||||
|
git lfs install --skip-repo # for mac & ubuntu
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, download source codes as normal.
|
||||||
|
```bash
|
||||||
|
git clone [repository url]
|
||||||
|
```
|
||||||
|
|
||||||
After downloading the source code, run the following command once to make sure
|
After downloading the source code, run the following command once to make sure
|
||||||
all developmennt tools are installed.
|
all developmennt tools are installed.
|
||||||
```bash
|
```bash
|
||||||
|
@ -111,6 +111,7 @@ impl<'a> UserMode<'a> {
|
|||||||
self.user_space.vm_space().activate();
|
self.user_space.vm_space().activate();
|
||||||
if !self.executed {
|
if !self.executed {
|
||||||
self.current.syscall_frame().caller.rcx = self.user_space.cpu_ctx.gp_regs.rip as usize;
|
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;
|
self.executed = true;
|
||||||
} else {
|
} else {
|
||||||
if self.current.inner_exclusive_access().is_from_trap {
|
if self.current.inner_exclusive_access().is_from_trap {
|
||||||
@ -137,6 +138,7 @@ impl<'a> UserMode<'a> {
|
|||||||
} else {
|
} else {
|
||||||
self.context = CpuContext::from(*self.current.syscall_frame());
|
self.context = CpuContext::from(*self.current.syscall_frame());
|
||||||
println!("[kernel] syscall id:{}",self.context.gp_regs.rax);
|
println!("[kernel] syscall id:{}",self.context.gp_regs.rax);
|
||||||
|
println!("[kernel] rsp: 0x{:x}", self.context.gp_regs.rsp);
|
||||||
UserEvent::Syscall
|
UserEvent::Syscall
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use kxos_frame::{
|
use kxos_frame::{
|
||||||
vm::{Vaddr, VmAllocOptions, VmFrameVec, VmIo, VmPerm, VmSpace, VmMapOptions},
|
config::PAGE_SIZE,
|
||||||
Error, config::PAGE_SIZE,
|
vm::{Vaddr, VmAllocOptions, VmFrameVec, VmIo, VmMapOptions, VmPerm, VmSpace},
|
||||||
|
Error,
|
||||||
};
|
};
|
||||||
use xmas_elf::{
|
use xmas_elf::{
|
||||||
header,
|
header,
|
||||||
@ -39,7 +40,7 @@ impl<'a> ElfSegment<'a> {
|
|||||||
Ok(type_) => type_,
|
Ok(type_) => type_,
|
||||||
};
|
};
|
||||||
let data = match read_segment_data(segment, elf_file) {
|
let data = match read_segment_data(segment, elf_file) {
|
||||||
Err(_) => return Err(ElfError::from("")),
|
Err(msg) => return Err(ElfError::from(msg)),
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
};
|
};
|
||||||
let vm_perm = Self::parse_segment_perm(segment)?;
|
let vm_perm = Self::parse_segment_perm(segment)?;
|
||||||
@ -58,7 +59,7 @@ impl<'a> ElfSegment<'a> {
|
|||||||
}
|
}
|
||||||
let mut vm_perm = VmPerm::R;
|
let mut vm_perm = VmPerm::R;
|
||||||
if flags.is_write() {
|
if flags.is_write() {
|
||||||
vm_perm |= VmPerm::W;
|
vm_perm |= VmPerm::W;
|
||||||
}
|
}
|
||||||
if flags.is_execute() {
|
if flags.is_execute() {
|
||||||
vm_perm |= VmPerm::X;
|
vm_perm |= VmPerm::X;
|
||||||
@ -188,8 +189,10 @@ impl<'a> ElfLoadInfo<'a> {
|
|||||||
for segment in self.segments.iter() {
|
for segment in self.segments.iter() {
|
||||||
let start_address = segment.start_address();
|
let start_address = segment.start_address();
|
||||||
let len = segment.data.len();
|
let len = segment.data.len();
|
||||||
let mut read_buffer = vec![0;len];
|
let mut read_buffer = vec![0; len];
|
||||||
vm_space.read_bytes(start_address, &mut read_buffer).expect("read bytes failed");
|
vm_space
|
||||||
|
.read_bytes(start_address, &mut read_buffer)
|
||||||
|
.expect("read bytes failed");
|
||||||
let res = segment.data.cmp(&read_buffer);
|
let res = segment.data.cmp(&read_buffer);
|
||||||
assert_eq!(res, Ordering::Equal);
|
assert_eq!(res, Ordering::Equal);
|
||||||
}
|
}
|
||||||
@ -255,14 +258,17 @@ impl From<Error> for ElfError {
|
|||||||
fn read_segment_data<'a>(
|
fn read_segment_data<'a>(
|
||||||
segment: ProgramHeader<'a>,
|
segment: ProgramHeader<'a>,
|
||||||
elf_file: &ElfFile<'a>,
|
elf_file: &ElfFile<'a>,
|
||||||
) -> Result<&'a [u8], ()> {
|
) -> Result<&'a [u8], &'static str> {
|
||||||
match segment.get_data(&elf_file) {
|
match segment.get_data(&elf_file) {
|
||||||
Err(_) => Err(()),
|
Err(msg) => Err(msg),
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
if let SegmentData::Undefined(data) = data {
|
match data {
|
||||||
Ok(data)
|
SegmentData::Note64(_, data) | SegmentData::Undefined(data) => {
|
||||||
} else {
|
Ok(data)
|
||||||
Err(())
|
},
|
||||||
|
_ => {
|
||||||
|
Err("Unkonwn segment data type")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
pub mod elf;
|
pub mod elf;
|
||||||
pub mod user_stack;
|
pub mod user_stack;
|
||||||
pub mod vm_page;
|
pub mod vm_page;
|
||||||
use kxos_frame::{vm::VmSpace, debug};
|
use kxos_frame::{debug, vm::VmSpace};
|
||||||
|
|
||||||
use self::elf::{ElfError, ElfLoadInfo};
|
use self::elf::{ElfError, ElfLoadInfo};
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use core::sync::atomic::{AtomicUsize, Ordering};
|
|||||||
|
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
// use kxos_frame::{sync::SpinLock, task::Task, user::UserSpace};
|
// 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;
|
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();
|
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 task = Task::spawn(task_fn, None::<u8>, None).expect("spawn kernel task failed");
|
||||||
let exit_code = 0;
|
let exit_code = 0;
|
||||||
Self { pid, task, exit_code }
|
Self {
|
||||||
|
pid,
|
||||||
|
task,
|
||||||
|
exit_code,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use kxos_frame::{
|
use kxos_frame::{
|
||||||
cpu::CpuContext,
|
cpu::CpuContext,
|
||||||
println,
|
|
||||||
task::Task,
|
task::Task,
|
||||||
user::{UserEvent, UserMode, UserSpace},
|
user::{UserEvent, UserMode, UserSpace},
|
||||||
vm::VmSpace,
|
vm::VmSpace, debug,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{memory::load_elf_to_vm_space, syscall::syscall_handler};
|
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);
|
let mut user_mode = UserMode::new(user_space);
|
||||||
loop {
|
loop {
|
||||||
let user_event = user_mode.execute();
|
let user_event = user_mode.execute();
|
||||||
|
debug!("return from user mode");
|
||||||
let context = user_mode.context_mut();
|
let context = user_mode.context_mut();
|
||||||
if let HandlerResult::Exit = 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?
|
// FIXME: How to set task status? How to set exit code of process?
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use alloc::ffi::CString;
|
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
use kxos_frame::cpu::CpuContext;
|
use kxos_frame::cpu::CpuContext;
|
||||||
@ -12,7 +11,7 @@ use crate::process::task::HandlerResult;
|
|||||||
const SYS_WRITE: u64 = 1;
|
const SYS_WRITE: u64 = 1;
|
||||||
const SYS_EXIT: u64 = 60;
|
const SYS_EXIT: u64 = 60;
|
||||||
|
|
||||||
pub struct SyscallFrame {
|
pub struct SyscallArgument {
|
||||||
syscall_number: u64,
|
syscall_number: u64,
|
||||||
args: [u64; 6],
|
args: [u64; 6],
|
||||||
}
|
}
|
||||||
@ -22,7 +21,7 @@ pub enum SyscallResult {
|
|||||||
Return(i32),
|
Return(i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyscallFrame {
|
impl SyscallArgument {
|
||||||
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;
|
||||||
let mut args = [0u64; 6];
|
let mut args = [0u64; 6];
|
||||||
@ -40,7 +39,7 @@ impl SyscallFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn syscall_handler(context: &mut CpuContext) -> HandlerResult {
|
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);
|
let syscall_return = syscall_dispatch(syscall_frame.syscall_number, syscall_frame.args);
|
||||||
|
|
||||||
match syscall_return {
|
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 =
|
let user_buffer =
|
||||||
copy_bytes_from_user(user_space, user_buf_ptr as usize, user_buf_len as usize)
|
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"); // 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);
|
info!("Message from user mode: {:?}", content);
|
||||||
SyscallResult::Return(0)
|
SyscallResult::Return(0)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
.PHONY: build clean run
|
.PHONY: build clean run
|
||||||
build: hello_world.s
|
build: hello_world.s
|
||||||
@nasm -f elf64 hello_world.s -o hello_world.o
|
@gcc -static -nostdlib hello_world.s -o hello_world
|
||||||
@ld hello_world.o -o hello_world
|
|
||||||
@rm hello_world.o
|
|
||||||
clean:
|
clean:
|
||||||
@rm hello_world
|
@rm hello_world
|
||||||
run: build
|
run: build
|
||||||
@./hello_world
|
@./hello_world
|
3
src/kxos-user/hello_world/hello_world
Executable file
3
src/kxos-user/hello_world/hello_world
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:0ac54a2485e87769b102225e0a2d7c25e449a01bd0b2504a164fe1ce205acb13
|
||||||
|
size 9072
|
@ -1,18 +1,24 @@
|
|||||||
global _start
|
.global _start
|
||||||
|
|
||||||
section .text
|
|
||||||
|
|
||||||
|
.section .text
|
||||||
_start:
|
_start:
|
||||||
mov rax, 1 ; syswrite
|
call print_message
|
||||||
mov rdi, 1 ; fd
|
call print_message
|
||||||
mov rsi, msg ; "Hello, world!\n",
|
call print_message
|
||||||
mov rdx, msglen ; sizeof("Hello, world!\n")
|
mov $60, %rax # syscall number of exit
|
||||||
syscall
|
mov $0, %rdi # exit code
|
||||||
|
syscall
|
||||||
mov rax, 60 ; sys_exit
|
print_message:
|
||||||
mov rdi, 0 ; exit_code
|
mov $1, %rax # syscall number of write
|
||||||
syscall
|
mov $1, %rdi # stdout
|
||||||
|
mov $message, %rsi # address of message
|
||||||
section .rodata
|
mov $message, %r11
|
||||||
msg: db "Hello, world!", 10
|
mov $message_end, %r12
|
||||||
msglen: equ $ - msg
|
sub %r11, %r12 # calculate message len
|
||||||
|
mov %r12, %rdx # number of bytes
|
||||||
|
syscall
|
||||||
|
ret
|
||||||
|
.section .rodata
|
||||||
|
message:
|
||||||
|
.ascii "Hello, world\n"
|
||||||
|
message_end:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user