add init stack

This commit is contained in:
Jianfeng Jiang 2022-09-14 17:08:34 +08:00
parent 73f66d54b9
commit a611ac416f
14 changed files with 475 additions and 97 deletions

View File

@ -15,4 +15,4 @@ pub const PAGE_SIZE_BITS: usize = 0xc;
pub const KVA_START: usize = (usize::MAX) << PAGE_SIZE_BITS;
pub const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Info;
pub const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Debug;

View File

@ -86,7 +86,8 @@ pub fn init(boot_info: &'static mut BootInfo) {
}
}
fn general_handler(trap_frame: TrapFrame) {
debug!("TrapFrame:{:#x?}", trap_frame);
println!("{:?}", trap_frame);
panic!("couldn't handler trap right now");
}
#[inline(always)]

View File

@ -221,13 +221,17 @@ impl MemorySet {
let mut current_addr = addr;
let mut remain = data.len();
let start_write = false;
let mut offset = 0usize;
for (va, area) in self.areas.iter_mut() {
if current_addr >= va.0 && current_addr < area.size + va.0 {
if !area.flags.contains(PTFlags::WRITABLE) {
return Err(Error::PageFault);
}
area.write_data(current_addr, data);
remain -= (va.0 + area.size - current_addr).min(remain);
let write_len = remain.min(area.size + va.0 - current_addr);
area.write_data(current_addr, &data[offset..(offset + write_len)]);
offset += write_len;
remain -= write_len;
// remain -= (va.0 + area.size - current_addr).min(remain);
if remain == 0 {
return Ok(());
}
@ -242,11 +246,15 @@ impl MemorySet {
pub fn read_bytes(&self, addr: usize, data: &mut [u8]) -> Result<()> {
let mut current_addr = addr;
let mut remain = data.len();
let mut offset = 0usize;
let start_read = false;
for (va, area) in self.areas.iter() {
if current_addr >= va.0 && current_addr < area.size + va.0 {
area.read_data(current_addr, data);
remain -= (va.0 + area.size - current_addr).min(remain);
let read_len = remain.min(area.size + va.0 - current_addr);
area.read_data(current_addr , &mut data[offset..(offset + read_len)]);
remain -= read_len;
offset += read_len;
// remain -= (va.0 + area.size - current_addr).min(remain);
if remain == 0 {
return Ok(());
}

View File

@ -117,6 +117,11 @@ impl<'a> UserMode<'a> {
self.current.syscall_frame().caller.rcx = self.user_space.cpu_ctx.gp_regs.rip;
self.current.syscall_frame().callee.rsp = self.user_space.cpu_ctx.gp_regs.rsp;
self.current.syscall_frame().caller.rax = self.user_space.cpu_ctx.gp_regs.rax;
// set argument registers
self.current.syscall_frame().caller.rdi = self.user_space.cpu_ctx.gp_regs.rdi;
self.current.syscall_frame().caller.rsi = self.user_space.cpu_ctx.gp_regs.rsi;
self.current.syscall_frame().caller.rdx = self.user_space.cpu_ctx.gp_regs.rdx;
self.executed = true;
} else {
if self.current.inner_exclusive_access().is_from_trap {

View File

@ -47,7 +47,7 @@ pub trait VmIo: Send + Sync {
fn write_bytes(&self, offset: usize, buf: &[u8]) -> Result<()>;
/// Write a value of a specified type at a specified offset.
fn write_val<T: Pod>(&mut self, offset: usize, new_val: &T) -> Result<()> {
fn write_val<T: Pod>(&self, offset: usize, new_val: &T) -> Result<()> {
self.write_bytes(offset, new_val.as_bytes())?;
Ok(())
}

View File

@ -52,6 +52,9 @@ pub unsafe trait Pod: Copy + Sized {
}
}
/// WorkAround. When implement macro impl_pod_for, this can be removed.
unsafe impl Pod for u64 {}
macro_rules! impl_pod_for {
($($token:tt)*/* define the input */) => {
/* define the expansion */

View File

@ -6,6 +6,7 @@
#![feature(const_btree_new)]
#![feature(cstr_from_bytes_until_nul)]
use alloc::ffi::CString;
use kxos_frame::{debug, info, println};
use process::Process;
@ -36,21 +37,24 @@ pub fn init_process() {
);
let hello_world_content = read_hello_world_content();
let process = Process::spawn_user_process(hello_world_content);
let hello_world_filename = CString::new("hello_world").unwrap();
let process = Process::spawn_user_process(hello_world_filename, hello_world_content);
info!(
"[kxos-std/lib.rs] spwan hello world process, pid = {}",
process.pid()
);
let fork_content = read_fork_content();
let process = Process::spawn_user_process(fork_content);
let fork_filename = CString::new("fork").unwrap();
let process = Process::spawn_user_process(fork_filename, fork_content);
info!(
"[kxos-std/lib.rs] spawn fork process, pid = {}",
process.pid()
);
let hello_c_content = read_hello_c_content();
let process = Process::spawn_user_process(hello_c_content);
let hello_c_filename = CString::new("hello_c").unwrap();
let process = Process::spawn_user_process(hello_c_filename, hello_c_content);
info!("spawn hello_c process, pid = {}", process.pid());
loop {}

View File

@ -0,0 +1,93 @@
use alloc::collections::BTreeMap;
/// This implementation is from occlum.
/// Auxiliary Vector.
///
/// # What is Auxiliary Vector?
///
/// Here is a concise description of Auxiliary Vector from GNU's manual:
///
/// > When a program is executed, it receives information from the operating system
/// about the environment in which it is operating. The form of this information
/// is a table of key-value pairs, where the keys are from the set of AT_
/// values in elf.h.
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(u8)]
pub enum AuxKey {
AT_NULL = 0, /* end of vector */
AT_IGNORE = 1, /* entry should be ignored */
AT_EXECFD = 2, /* file descriptor of program */
AT_PHDR = 3, /* program headers for program */
AT_PHENT = 4, /* size of program header entry */
AT_PHNUM = 5, /* number of program headers */
AT_PAGESZ = 6, /* system page size */
AT_BASE = 7, /* base address of interpreter */
AT_FLAGS = 8, /* flags */
AT_ENTRY = 9, /* entry point of program */
AT_NOTELF = 10, /* program is not ELF */
AT_UID = 11, /* real uid */
AT_EUID = 12, /* effective uid */
AT_GID = 13, /* real gid */
AT_EGID = 14, /* effective gid */
AT_PLATFORM = 15, /* string identifying CPU for optimizations */
AT_HWCAP = 16, /* arch dependent hints at CPU capabilities */
AT_CLKTCK = 17, /* frequency at which times() increments */
/* 18...22 not used */
AT_SECURE = 23, /* secure mode boolean */
AT_BASE_PLATFORM = 24, /* string identifying real platform, may
* differ from AT_PLATFORM. */
AT_RANDOM = 25, /* address of 16 random bytes */
AT_HWCAP2 = 26, /* extension of AT_HWCAP */
/* 28...30 not used */
AT_EXECFN = 31, /* filename of program */
AT_SYSINFO = 32,
}
impl AuxKey {
pub fn as_u64(&self) -> u64 {
*self as u64
}
}
#[derive(Clone, Default, Debug)]
pub struct AuxVec {
table: BTreeMap<AuxKey, u64>,
}
impl AuxVec {
pub const fn new() -> AuxVec {
AuxVec {
table: BTreeMap::new(),
}
}
}
impl AuxVec {
pub fn set(&mut self, key: AuxKey, val: u64) -> Result<(), &'static str> {
if key == AuxKey::AT_NULL || key == AuxKey::AT_IGNORE {
return Err("Illegal key");
}
self.table
.entry(key)
.and_modify(|val_mut| *val_mut = val)
.or_insert(val);
Ok(())
}
pub fn get(&self, key: AuxKey) -> Option<u64> {
self.table.get(&key).map(|val_ref| *val_ref)
}
pub fn del(&mut self, key: AuxKey) -> Option<u64> {
self.table.remove(&key)
}
pub fn table(&self) -> &BTreeMap<AuxKey, u64> {
&self.table
}
}

View File

@ -1,10 +1,10 @@
use core::{cmp::Ordering, ops::Range};
use alloc::ffi::CString;
use alloc::vec;
use alloc::vec::Vec;
use kxos_frame::{
config::PAGE_SIZE,
debug,
vm::{Vaddr, VmIo, VmPerm, VmSpace},
Error,
};
@ -14,12 +14,12 @@ use xmas_elf::{
ElfFile,
};
use super::{user_stack::UserStack, vm_page::VmPageRange};
use super::{init_stack::InitStack, vm_page::VmPageRange};
pub struct ElfLoadInfo<'a> {
entry_point: Vaddr,
segments: Vec<ElfSegment<'a>>,
user_stack: UserStack,
init_stack: InitStack,
}
pub struct ElfSegment<'a> {
@ -85,11 +85,11 @@ impl<'a> ElfSegment<'a> {
// return Err(ElfError::SegmentNotPageAligned);
// }
// map page
debug!(
"map_segment: 0x{:x} - 0x{:x}",
self.start_address(),
self.end_address()
);
// debug!(
// "map_segment: 0x{:x} - 0x{:x}",
// self.start_address(),
// self.end_address()
// );
let vm_page_range = VmPageRange::new_range(self.start_address()..self.end_address());
for page in vm_page_range.iter() {
// map page if the page is not mapped
@ -99,11 +99,11 @@ impl<'a> ElfSegment<'a> {
}
}
debug!(
"copy_segment: 0x{:x} - 0x{:x}",
self.start_address(),
self.end_address()
);
// debug!(
// "copy_segment: 0x{:x} - 0x{:x}",
// self.start_address(),
// self.end_address()
// );
// copy segment
vm_space.write_bytes(self.start_address(), self.data)?;
Ok(())
@ -115,11 +115,11 @@ impl<'a> ElfSegment<'a> {
}
impl<'a> ElfLoadInfo<'a> {
fn with_capacity(entry_point: Vaddr, capacity: usize, user_stack: UserStack) -> Self {
fn with_capacity(entry_point: Vaddr, capacity: usize, init_stack: InitStack) -> Self {
Self {
entry_point,
segments: Vec::with_capacity(capacity),
user_stack,
init_stack,
}
}
@ -127,7 +127,7 @@ impl<'a> ElfLoadInfo<'a> {
self.segments.push(elf_segment);
}
pub fn parse_elf_data(elf_file_content: &'a [u8]) -> Result<Self, ElfError> {
pub fn parse_elf_data(elf_file_content: &'a [u8], filename: CString) -> Result<Self, ElfError> {
let elf_file = match ElfFile::new(elf_file_content) {
Err(error_msg) => return Err(ElfError::from(error_msg)),
Ok(elf_file) => elf_file,
@ -137,8 +137,8 @@ impl<'a> ElfLoadInfo<'a> {
let entry_point = elf_file.header.pt2.entry_point() as Vaddr;
// FIXME: only contains load segment?
let segments_count = elf_file.program_iter().count();
let user_stack = UserStack::new_default_config();
let mut elf_load_info = ElfLoadInfo::with_capacity(entry_point, segments_count, user_stack);
let init_stack = InitStack::new_default_config(filename);
let mut elf_load_info = ElfLoadInfo::with_capacity(entry_point, segments_count, init_stack);
// parse each segemnt
for segment in elf_file.program_iter() {
@ -177,8 +177,8 @@ impl<'a> ElfLoadInfo<'a> {
Ok(())
}
pub fn map_and_clear_user_stack(&self, vm_space: &VmSpace) {
self.user_stack.map_and_zeroed(vm_space);
pub fn init_stack(&mut self, vm_space: &VmSpace) {
self.init_stack.init(vm_space).expect("Init User Stack failed");
}
/// return the perm of elf pages
@ -192,7 +192,23 @@ impl<'a> ElfLoadInfo<'a> {
}
pub fn user_stack_top(&self) -> u64 {
self.user_stack.stack_top() as u64
self.init_stack.user_stack_top() as u64
}
pub fn argc(&self) -> u64 {
self.init_stack.argc()
}
pub fn argv(&self) -> u64 {
self.init_stack.argv()
}
pub fn envc(&self) -> u64 {
self.init_stack.envc()
}
pub fn envp(&self) -> u64 {
self.init_stack.envp()
}
/// read content from vmspace to ensure elf data is correctly copied to user space
@ -205,6 +221,17 @@ impl<'a> ElfLoadInfo<'a> {
.read_bytes(start_address, &mut read_buffer)
.expect("read bytes failed");
let res = segment.data.cmp(&read_buffer);
// if res != Ordering::Equal {
// debug!("segment: 0x{:x} - 0x{:x}", segment.start_address(), segment.end_address());
// debug!("read buffer len: 0x{:x}", read_buffer.len());
// for i in 0..segment.data.len() {
// if segment.data[i] != read_buffer[i] {
// debug!("i = 0x{:x}", i);
// break;
// }
// }
// }
assert_eq!(res, Ordering::Equal);
}
}

View File

@ -0,0 +1,276 @@
use core::mem;
use alloc::{ffi::CString, vec::Vec};
use alloc::vec;
use kxos_frame::{config::PAGE_SIZE, debug, vm::{Vaddr, VmIo, VmPerm, VmSpace}};
use super::{aux_vec::{AuxKey, AuxVec}, elf::ElfError, vm_page::VmPageRange};
pub const INIT_STACK_BASE: Vaddr = 0x0000_0000_1000_0000;
pub const INIT_STACK_SIZE: usize = 0x1000 * 16; // 64KB
/// The process initial stack, contains arguments, environmental variables and auxiliary vectors
/// The data layout of init stack can be seen in Figure 3.9 in https://uclibc.org/docs/psABI-x86_64.pdf
/*
* The initial stack of a process looks like below(This figure is from occlum):
*
*
* +---------------------+ <------+ Top of stack
* | | (high address)
* | Null-terminated |
* | strings referenced |
* | by variables below |
* | |
* +---------------------+
* | AT_NULL |
* +---------------------+
* | AT_NULL |
* +---------------------+
* | ... |
* +---------------------+
* | aux_val[0] |
* +---------------------+
* | aux_key[0] | <------+ Auxiliary table
* +---------------------+
* | NULL |
* +---------------------+
* | ... |
* +---------------------+
* | char* envp[0] | <------+ Environment variabls
* +---------------------+
* | NULL |
* +---------------------+
* | char* argv[argc-1] |
* +---------------------+
* | ... |
* +---------------------+
* | char* argv[0] |
* +---------------------+
* | long argc | <------+ Program arguments
* +---------------------+
* | |
* | |
* + +
*
*/
pub struct InitStack {
/// The high address of init stack
init_stack_top: Vaddr,
init_stack_size: usize,
offset: usize,
/// Command line args
argv: Vec<CString>,
/// Environmental variables
envp: Vec<CString>,
/// Auxiliary Vector
aux_vec: AuxVec,
}
impl InitStack {
/// initialize user stack on base addr
pub fn new(filename: CString, stack_top: Vaddr, stack_size: usize) -> Self {
let argv = vec![filename];
Self {
init_stack_top: stack_top,
init_stack_size: stack_size,
offset: 0,
argv,
envp: Vec::new(),
aux_vec: AuxVec::new(),
}
}
/// This function only work for first process
pub fn new_default_config(filename: CString) -> Self {
let argv = vec![filename];
Self {
// add a guard page at stack top
init_stack_top: INIT_STACK_BASE - PAGE_SIZE,
init_stack_size: INIT_STACK_SIZE,
offset: 0,
argv,
envp: Vec::new(),
aux_vec: AuxVec::new(),
}
}
/// the user stack top(high address), used to setup rsp
pub fn user_stack_top(&self) -> Vaddr {
let stack_top = self.init_stack_top - self.offset;
debug!("user stack top: 0x{:x}", stack_top);
// ensure stack top is 16-bytes aligned
assert!(stack_top & !0xf == stack_top);
stack_top
}
/// the user stack bottom(low address)
const fn user_stack_bottom(&self) -> Vaddr {
self.init_stack_top - self.init_stack_size
}
pub fn init(&mut self, vm_space: &VmSpace) -> Result<(), ElfError> {
self.map_and_zeroed(vm_space);
self.write_stack_content(vm_space);
Ok(())
}
fn map_and_zeroed(&self, vm_space: &VmSpace) {
let mut vm_page_range = VmPageRange::new_range(self.user_stack_bottom()..self.user_stack_top());
let vm_perm = InitStack::perm();
vm_page_range.map_zeroed(vm_space, vm_perm);
}
/// Libc ABI requires 16-byte alignment of the stack entrypoint.
/// Current postion of the stack is 8-byte aligned already, insert 8 byte
/// to meet the requirement if necessary.
fn adjust_stack_alignment(&mut self, vm_space: &VmSpace, envp_pointers: &Vec<u64>, argv_pointers: &Vec<u64>) {
// ensure 8-byte alignment
self.write_u64(0, vm_space);
let auxvec_size = (self.aux_vec.table().len() + 1) * (mem::size_of::<u64>() * 2);
let envp_pointers_size = (envp_pointers.len() + 1) * mem::size_of::<u64>();
let argv_pointers_size = (argv_pointers.len() + 1) * mem::size_of::<u64>();
let argc_size = mem::size_of::<u64>();
let to_write_size = auxvec_size + envp_pointers_size + argv_pointers_size + argc_size;
if (self.init_stack_top - self.offset - to_write_size) % 16 != 0 {
self.write_u64(0, vm_space);
}
}
fn write_stack_content(&mut self, vm_space: &VmSpace) {
// write envp string
let envp_pointers = self.write_envp_strings(vm_space);
// write argv string
let argv_pointers = self.write_argv_strings(vm_space);
// write random value
let random_value = generate_random_for_aux_vec();
let random_value_pointer = self.write_bytes(&random_value, vm_space);
self.aux_vec.set(AuxKey::AT_RANDOM, random_value_pointer).expect("Set random value failed");
self.adjust_stack_alignment(vm_space, &envp_pointers, &argv_pointers);
self.write_aux_vec(vm_space);
self.write_envp_pointers(vm_space, envp_pointers);
self.write_argv_pointers(vm_space, argv_pointers);
// write argc
let argc = self.argc();
self.write_u64(argc, vm_space);
}
fn write_envp_strings(&mut self, vm_space: &VmSpace) -> Vec<u64> {
let envp = self.envp.iter().map(|envp| envp.clone()).collect::<Vec<_>>();
let mut envp_pointers = Vec::with_capacity(envp.len());
for envp in envp.iter() {
let pointer = self.write_cstring(envp, vm_space);
envp_pointers.push(pointer);
}
envp_pointers
}
fn write_argv_strings(&mut self, vm_space: &VmSpace) -> Vec<u64> {
let argv = self.argv.iter().map(|argv| argv.clone()).collect::<Vec<_>>();
let mut argv_pointers = Vec::with_capacity(argv.len());
for argv in argv.iter().rev() {
let pointer = self.write_cstring(argv, vm_space);
argv_pointers.push(pointer);
}
argv_pointers.reverse();
argv_pointers
}
fn write_aux_vec(&mut self, vm_space: &VmSpace) {
// Write NULL auxilary
self.write_u64(0, vm_space);
self.write_u64(AuxKey::AT_NULL as u64, vm_space);
// Write Auxiliary vectors
let aux_vec: Vec<_> = self.aux_vec.table().iter().map(|(aux_key, aux_value)| (*aux_key, *aux_value)).collect();
for (aux_key, aux_value) in aux_vec.iter() {
self.write_u64(*aux_value, vm_space);
self.write_u64(*aux_key as u64, vm_space);
}
}
fn write_envp_pointers(&mut self, vm_space: &VmSpace, mut envp_pointers: Vec<u64>) {
// write NULL pointer
self.write_u64(0, vm_space);
// write envp pointers
envp_pointers.reverse();
for envp_pointer in envp_pointers {
self.write_u64(envp_pointer, vm_space);
}
}
fn write_argv_pointers(&mut self, vm_space: &VmSpace, mut argv_pointers: Vec<u64>) {
// write 0
self.write_u64(0, vm_space);
// write argv pointers
argv_pointers.reverse();
for argv_pointer in argv_pointers {
self.write_u64(argv_pointer, vm_space);
}
}
/// Command line argument counter
pub fn argc(&self) -> u64 {
1 + self.argv.len() as u64
}
/// Command linke argument start address
pub fn argv(&self) -> u64{
self.user_stack_top() as u64 + 8
}
/// Environmental variables counter
pub fn envc(&self) -> u64 {
self.envp.len() as u64
}
/// Environmental variables pointers
pub fn envp(&self) -> u64 {
0
}
/// returns the u64 start address
fn write_u64(&mut self, val: u64, vm_space: &VmSpace) -> u64 {
let start_address = align_down(self.init_stack_top - self.offset - 8, 8);
self.offset = self.init_stack_top - start_address;
debug!("start_address: 0x{:x}", start_address);
vm_space.write_val(start_address, &val).expect("Write u64 failed");
(self.init_stack_top - self.offset) as u64
}
fn write_bytes(&mut self, bytes: &[u8], vm_space: &VmSpace) -> u64 {
let len = bytes.len();
self.offset += len;
vm_space.write_bytes(self.init_stack_top - self.offset, bytes).expect("Write String failed");
(self.init_stack_top - self.offset) as u64
}
/// returns the string start address
fn write_cstring(&mut self, val: &CString, vm_space: &VmSpace) -> u64 {
let bytes = val.as_bytes();
self.write_bytes(bytes, vm_space)
}
pub const fn perm() -> VmPerm {
VmPerm::RWU
}
}
fn is_power_of_two(val: usize) -> bool {
(val != 0) && ((val & (val - 1)) == 0)
}
/// align should be the pow of 2
fn align_down(vaddr: usize, align: usize) -> usize {
assert!(is_power_of_two(align));
vaddr & !(align - 1)
}
/// generate random [u8; 16].
/// FIXME: generate really random value
fn generate_random_for_aux_vec() -> [u8; 16] {
let mut rand_val = [0; 16];
for i in 0..16u8 {
rand_val[i as usize] = 0xff - i;
}
rand_val
}

View File

@ -1,6 +1,8 @@
pub mod elf;
pub mod user_stack;
pub mod init_stack;
pub mod vm_page;
pub mod aux_vec;
use alloc::ffi::CString;
use kxos_frame::{debug, vm::VmSpace};
use self::elf::{ElfError, ElfLoadInfo};
@ -11,15 +13,14 @@ use self::elf::{ElfError, ElfLoadInfo};
/// 3. map frames to the correct vaddr
/// 4. (allocate frams and) map the user stack
pub fn load_elf_to_vm_space<'a>(
filename: CString,
elf_file_content: &'a [u8],
vm_space: &VmSpace,
) -> Result<ElfLoadInfo<'a>, ElfError> {
let elf_load_info = ElfLoadInfo::parse_elf_data(elf_file_content)?;
debug!("parse data success");
let mut elf_load_info = ElfLoadInfo::parse_elf_data(elf_file_content, filename)?;
elf_load_info.copy_data(vm_space)?;
debug!("copy_data success");
elf_load_info.debug_check_map_result(vm_space);
debug!("map elf success");
elf_load_info.map_and_clear_user_stack(vm_space);
elf_load_info.init_stack(vm_space);
Ok(elf_load_info)
}

View File

@ -1,54 +0,0 @@
use kxos_frame::{
config::PAGE_SIZE,
vm::{Vaddr, VmPerm, VmSpace},
};
use super::vm_page::VmPageRange;
pub const USER_STACK_BASE: Vaddr = 0x0000_0000_1000_0000;
pub const USER_STACK_SIZE: usize = 0x1000 * 16; // 64KB
pub struct UserStack {
/// The high address of user stack
stack_top: Vaddr,
stack_size: usize,
}
impl UserStack {
/// initialize user stack on base addr
pub const fn new(stack_top: Vaddr, stack_size: usize) -> Self {
Self {
stack_top,
stack_size,
}
}
/// This function only work for first process
pub const fn new_default_config() -> Self {
Self {
// add a guard page at stack top
stack_top: USER_STACK_BASE - PAGE_SIZE,
stack_size: USER_STACK_SIZE,
}
}
/// the user stack top(high address), used to setup rsp
pub const fn stack_top(&self) -> Vaddr {
self.stack_top
}
/// the user stack bottom(low address)
const fn stack_bottom(&self) -> Vaddr {
self.stack_top - 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_top());
let vm_perm = UserStack::perm();
vm_page_range.map_zeroed(vm_space, vm_perm);
}
pub const fn perm() -> VmPerm {
VmPerm::RWU
}
}

View File

@ -1,5 +1,6 @@
use core::sync::atomic::{AtomicI32, AtomicUsize, Ordering};
use alloc::ffi::CString;
use alloc::vec;
use alloc::{
sync::{Arc, Weak},
@ -70,8 +71,8 @@ impl Process {
}
/// init a user process and send the process to scheduler
pub fn spawn_user_process(elf_file_content: &'static [u8]) -> Arc<Self> {
let process = Process::create_user_process(elf_file_content);
pub fn spawn_user_process(filename: CString, elf_file_content: &'static [u8]) -> Arc<Self> {
let process = Process::create_user_process(filename, elf_file_content);
process.send_to_scheduler();
process
}
@ -86,12 +87,12 @@ impl Process {
process
}
fn create_user_process(elf_file_content: &'static [u8]) -> Arc<Self> {
fn create_user_process(filename: CString, elf_file_content: &'static [u8]) -> Arc<Self> {
let pid = new_pid();
Arc::new_cyclic(|weak_process_ref| {
let weak_process = weak_process_ref.clone();
let task = create_user_task_from_elf(elf_file_content, weak_process);
let task = create_user_task_from_elf(filename, elf_file_content, weak_process);
let user_space = task.user_space().map(|user_space| user_space.clone());
Process::new(pid, task, user_space)

View File

@ -1,6 +1,6 @@
use core::sync::atomic::AtomicUsize;
use alloc::sync::{Arc, Weak};
use alloc::{ffi::CString, sync::{Arc, Weak}};
use kxos_frame::{
cpu::CpuContext,
debug,
@ -19,16 +19,29 @@ use super::Process;
static COUNTER: AtomicUsize = AtomicUsize::new(0);
pub fn create_user_task_from_elf(elf_file_content: &[u8], process: Weak<Process>) -> Arc<Task> {
pub fn create_user_task_from_elf(filename: CString, elf_file_content: &[u8], process: Weak<Process>) -> Arc<Task> {
let vm_space = VmSpace::new();
let elf_load_info = load_elf_to_vm_space(elf_file_content, &vm_space).expect("Load Elf failed");
let elf_load_info = load_elf_to_vm_space(filename, elf_file_content, &vm_space).expect("Load Elf failed");
let mut cpu_ctx = CpuContext::default();
// FIXME: correct regs?
// set entry point
cpu_ctx.gp_regs.rip = elf_load_info.entry_point();
debug!("entry point: 0x{:x}", elf_load_info.entry_point());
// set user stack
cpu_ctx.gp_regs.rsp = elf_load_info.user_stack_top();
// See document: https://embeddedartistry.com/blog/2019/04/08/a-general-overview-of-what-happens-before-main/
// set argc
// cpu_ctx.gp_regs.rdi = elf_load_info.argc();
// debug!("rdi, argc = {}", elf_load_info.argc());
// // set argv
// cpu_ctx.gp_regs.rsi = elf_load_info.argv();
// debug!("rsi, argv = 0x{:x}", elf_load_info.argv());
// // set envc
// cpu_ctx.gp_regs.rdx = elf_load_info.envc();
// // set envp
// cpu_ctx.gp_regs.rcx = elf_load_info.envp();
let user_space = Arc::new(UserSpace::new(vm_space, cpu_ctx));
fn user_task_entry() {
let cur = Task::current();