mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 12:56:48 +00:00
Merge branch 'occlum:main' into main
This commit is contained in:
commit
5359879499
@ -19,7 +19,7 @@ pub fn log_print(args: Arguments) {
|
||||
#[macro_export]
|
||||
macro_rules! log_print {
|
||||
($($arg:tt)*) => {
|
||||
(kxos_frame::log::log_print(format_args!($($arg)*)))
|
||||
$crate::log::log_print(format_args!($($arg)*))
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,9 @@
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
#![feature(const_btree_new)]
|
||||
#![feature(cstr_from_bytes_until_nul)]
|
||||
|
||||
use kxos_frame::println;
|
||||
use process::Process;
|
||||
|
||||
extern crate alloc;
|
||||
@ -18,6 +20,12 @@ pub fn init() {
|
||||
process::fifo_scheduler::init();
|
||||
}
|
||||
|
||||
pub fn run_first_kernel_task() {
|
||||
Process::spawn_kernel_task(|| {
|
||||
println!("hello world from kernel");
|
||||
});
|
||||
}
|
||||
|
||||
pub fn run_first_process() {
|
||||
let elf_file_content = read_elf_content();
|
||||
Process::spawn_from_elf(elf_file_content);
|
||||
|
@ -1,9 +1,10 @@
|
||||
use core::ops::Range;
|
||||
use core::{ops::Range, cmp::Ordering};
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use alloc::vec;
|
||||
use kxos_frame::{
|
||||
vm::{Vaddr, VmAllocOptions, VmFrameVec, VmIo, VmPerm, VmSpace},
|
||||
Error,
|
||||
vm::{Vaddr, VmAllocOptions, VmFrameVec, VmIo, VmPerm, VmSpace, VmMapOptions},
|
||||
Error, config::PAGE_SIZE,
|
||||
};
|
||||
use xmas_elf::{
|
||||
header,
|
||||
@ -23,6 +24,7 @@ pub struct ElfSegment<'a> {
|
||||
range: Range<Vaddr>,
|
||||
data: &'a [u8],
|
||||
type_: program::Type,
|
||||
vm_perm: VmPerm,
|
||||
}
|
||||
|
||||
impl<'a> ElfSegment<'a> {
|
||||
@ -40,13 +42,30 @@ impl<'a> ElfSegment<'a> {
|
||||
Err(_) => return Err(ElfError::from("")),
|
||||
Ok(data) => data,
|
||||
};
|
||||
let vm_perm = Self::parse_segment_perm(segment)?;
|
||||
Ok(Self {
|
||||
range: start..end,
|
||||
type_,
|
||||
data,
|
||||
vm_perm,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_segment_perm(segment: ProgramHeader<'a>) -> Result<VmPerm, ElfError> {
|
||||
let flags = segment.flags();
|
||||
if !flags.is_read() {
|
||||
return Err(ElfError::UnreadableSegment);
|
||||
}
|
||||
let mut vm_perm = VmPerm::R;
|
||||
if flags.is_write() {
|
||||
vm_perm |= VmPerm::W;
|
||||
}
|
||||
if flags.is_execute() {
|
||||
vm_perm |= VmPerm::X;
|
||||
}
|
||||
Ok(vm_perm)
|
||||
}
|
||||
|
||||
pub fn is_loadable(&self) -> bool {
|
||||
self.type_ == program::Type::Load
|
||||
}
|
||||
@ -58,6 +77,29 @@ impl<'a> ElfSegment<'a> {
|
||||
pub fn end_address(&self) -> Vaddr {
|
||||
self.range.end
|
||||
}
|
||||
|
||||
fn copy_and_map(&self, vm_space: &VmSpace) -> Result<(), ElfError> {
|
||||
if !self.is_page_aligned() {
|
||||
return Err(ElfError::SegmentNotPageAligned);
|
||||
}
|
||||
let vm_page_range = VmPageRange::new_range(self.start_address()..self.end_address());
|
||||
let page_number = vm_page_range.len();
|
||||
// allocate frames
|
||||
let vm_alloc_options = VmAllocOptions::new(page_number);
|
||||
let mut frames = VmFrameVec::allocate(&vm_alloc_options)?;
|
||||
// copy segment
|
||||
frames.write_bytes(0, self.data)?;
|
||||
// map segment
|
||||
let mut vm_map_options = VmMapOptions::new();
|
||||
vm_map_options.addr(Some(self.start_address()));
|
||||
vm_map_options.perm(self.vm_perm);
|
||||
vm_space.map(frames, &vm_map_options)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_page_aligned(&self) -> bool {
|
||||
self.start_address() % PAGE_SIZE == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ElfLoadInfo<'a> {
|
||||
@ -116,28 +158,11 @@ impl<'a> ElfLoadInfo<'a> {
|
||||
Ok(VmPageRange::new_range(elf_start_address..elf_end_address))
|
||||
}
|
||||
|
||||
pub fn map_self(&self, vm_space: &VmSpace, frames: VmFrameVec) -> Result<(), ElfError> {
|
||||
let mut vm_page_range = self.vm_page_range()?;
|
||||
let vm_perm = ElfLoadInfo::perm();
|
||||
vm_page_range.map_to(vm_space, frames, vm_perm);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn copy_elf(&self) -> Result<VmFrameVec, ElfError> {
|
||||
let vm_page_range = self.vm_page_range()?;
|
||||
// calculate offset
|
||||
let offset = vm_page_range.start_address();
|
||||
// allocate frames
|
||||
let page_number = vm_page_range.len();
|
||||
let options = VmAllocOptions::new(page_number);
|
||||
let mut frames = VmFrameVec::allocate(&options)?;
|
||||
|
||||
for segment in self.segments.iter().filter(|segment| segment.is_loadable()) {
|
||||
let start_address = segment.start_address();
|
||||
frames.write_bytes(start_address - offset, segment.data)?;
|
||||
pub fn copy_and_map(&self, vm_space: &VmSpace) -> Result<(), ElfError> {
|
||||
for segment in self.segments.iter() {
|
||||
segment.copy_and_map(vm_space)?;
|
||||
}
|
||||
|
||||
Ok(frames)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn map_and_clear_user_stack(&self, vm_space: &VmSpace) {
|
||||
@ -154,8 +179,20 @@ impl<'a> ElfLoadInfo<'a> {
|
||||
self.entry_point as u64
|
||||
}
|
||||
|
||||
pub fn user_stack_bottom(&self) -> u64 {
|
||||
self.user_stack.stack_bottom as u64
|
||||
pub fn user_stack_top(&self) -> u64 {
|
||||
self.user_stack.stack_top() as u64
|
||||
}
|
||||
|
||||
/// read content from vmspace to ensure elf data is correctly copied to user space
|
||||
pub fn debug_check_map_result(&self, vm_space: &VmSpace) {
|
||||
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 res = segment.data.cmp(&read_buffer);
|
||||
assert_eq!(res, Ordering::Equal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,6 +235,8 @@ pub enum ElfError {
|
||||
FrameError(Error),
|
||||
NoSegment,
|
||||
UnsupportedElfType,
|
||||
SegmentNotPageAligned,
|
||||
UnreadableSegment,
|
||||
WithInfo(&'static str),
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
pub mod elf;
|
||||
pub mod user_stack;
|
||||
pub mod vm_page;
|
||||
use kxos_frame::vm::VmSpace;
|
||||
use kxos_frame::{vm::VmSpace, debug};
|
||||
|
||||
use self::elf::{ElfError, ElfLoadInfo};
|
||||
|
||||
@ -15,8 +15,9 @@ pub fn load_elf_to_vm_space<'a>(
|
||||
vm_space: &VmSpace,
|
||||
) -> Result<ElfLoadInfo<'a>, ElfError> {
|
||||
let elf_load_info = ElfLoadInfo::parse_elf_data(elf_file_content)?;
|
||||
let to_frames = elf_load_info.copy_elf()?;
|
||||
elf_load_info.map_self(vm_space, to_frames)?;
|
||||
elf_load_info.copy_and_map(vm_space)?;
|
||||
elf_load_info.debug_check_map_result(vm_space);
|
||||
debug!("map elf success");
|
||||
elf_load_info.map_and_clear_user_stack(vm_space);
|
||||
Ok(elf_load_info)
|
||||
}
|
||||
|
@ -7,32 +7,39 @@ pub const USER_STACK_BASE: Vaddr = 0x0000_0000_1000_0000;
|
||||
pub const USER_STACK_SIZE: usize = 0x1000 * 16; // 64KB
|
||||
|
||||
pub struct UserStack {
|
||||
pub stack_bottom: Vaddr,
|
||||
/// The low address of user stack
|
||||
pub stack_base: Vaddr,
|
||||
stack_size: usize,
|
||||
vm_space: Option<Arc<VmSpace>>,
|
||||
}
|
||||
|
||||
impl UserStack {
|
||||
// initialize user stack on fixed position
|
||||
pub const fn new(stack_bottom: Vaddr, stack_size: usize) -> Self {
|
||||
/// initialize user stack on base addr
|
||||
pub const fn new(stack_base: Vaddr, stack_size: usize) -> Self {
|
||||
Self {
|
||||
stack_bottom,
|
||||
stack_base,
|
||||
stack_size,
|
||||
vm_space: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// This function only work for first process
|
||||
pub const fn new_default_config() -> Self {
|
||||
Self {
|
||||
stack_bottom: USER_STACK_BASE,
|
||||
stack_base: USER_STACK_BASE,
|
||||
stack_size: USER_STACK_SIZE,
|
||||
vm_space: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// the user stack top(high address), used to setup rsp
|
||||
pub const fn stack_top(&self) -> Vaddr {
|
||||
self.stack_base + self.stack_size
|
||||
}
|
||||
|
||||
pub fn map_and_zeroed(&self, vm_space: &VmSpace) {
|
||||
let mut vm_page_range =
|
||||
VmPageRange::new_range(self.stack_bottom..(self.stack_bottom + self.stack_size));
|
||||
VmPageRange::new_range(self.stack_base..(self.stack_base + self.stack_size));
|
||||
let vm_perm = UserStack::perm();
|
||||
vm_page_range.map_zeroed(vm_space, vm_perm);
|
||||
}
|
||||
|
@ -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;
|
||||
use kxos_frame::{task::Task, debug};
|
||||
|
||||
use self::task::spawn_user_task_from_elf;
|
||||
|
||||
@ -33,6 +33,14 @@ impl Process {
|
||||
exit_code,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_kernel_task<F>(task_fn: F) -> Self where F: Fn() + Send + Sync + 'static {
|
||||
let pid = new_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 }
|
||||
}
|
||||
}
|
||||
|
||||
/// create a new pid for new process
|
||||
|
@ -17,7 +17,7 @@ pub fn spawn_user_task_from_elf(elf_file_content: &[u8]) -> Arc<Task> {
|
||||
// set entry point
|
||||
cpu_ctx.gp_regs.rip = elf_load_info.entry_point();
|
||||
// set user stack
|
||||
cpu_ctx.gp_regs.rsp = elf_load_info.user_stack_bottom();
|
||||
cpu_ctx.gp_regs.rsp = elf_load_info.user_stack_top();
|
||||
|
||||
let user_space = Arc::new(UserSpace::new(vm_space, cpu_ctx));
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
use alloc::ffi::CString;
|
||||
use alloc::vec;
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use kxos_frame::cpu::CpuContext;
|
||||
@ -8,8 +9,8 @@ use kxos_frame::info;
|
||||
|
||||
use crate::process::task::HandlerResult;
|
||||
|
||||
const SYS_WRITE: u64 = 64;
|
||||
const SYS_EXIT: u64 = 93;
|
||||
const SYS_WRITE: u64 = 1;
|
||||
const SYS_EXIT: u64 = 60;
|
||||
|
||||
pub struct SyscallFrame {
|
||||
syscall_number: u64,
|
||||
@ -69,9 +70,9 @@ 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");
|
||||
let content = CString::from_vec_with_nul(user_buffer).expect("read string failed");
|
||||
// TODO: print content
|
||||
info!("Message from user mode: {}", content);
|
||||
info!("Message from user mode: {:?}", content);
|
||||
SyscallResult::Return(0)
|
||||
} else {
|
||||
panic!("Unsupported fd number {}", fd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user