From 7ee9c9e74ca65a35f26881270c0fe71cfaccc409 Mon Sep 17 00:00:00 2001 From: Jianfeng Jiang Date: Wed, 26 Oct 2022 17:47:38 +0800 Subject: [PATCH] add syscall execve --- .gitattributes | 2 + src/kxos-frame/src/cpu.rs | 6 +- src/kxos-frame/src/mm/memory_set.rs | 2 +- src/kxos-frame/src/user.rs | 1 + src/kxos-frame/src/vm/space.rs | 6 ++ src/kxos-frame/src/x86_64_util.rs | 4 ++ src/kxos-std/src/fs/mod.rs | 1 + src/kxos-std/src/fs/stat.rs | 60 ++++++++++++++++++ src/kxos-std/src/lib.rs | 51 +++++---------- src/kxos-std/src/memory/aux_vec.rs | 2 +- src/kxos-std/src/memory/elf.rs | 74 ++++++++++++++++++---- src/kxos-std/src/memory/init_stack.rs | 47 +++++++++++--- src/kxos-std/src/memory/mmap_area.rs | 12 ++-- src/kxos-std/src/memory/mod.rs | 9 ++- src/kxos-std/src/memory/user_heap.rs | 18 ++++-- src/kxos-std/src/memory/vm_page.rs | 8 +-- src/kxos-std/src/prelude.rs | 28 ++++++++ src/kxos-std/src/process/fifo_scheduler.rs | 7 +- src/kxos-std/src/process/mod.rs | 21 +++--- src/kxos-std/src/process/table.rs | 38 +++++++++++ src/kxos-std/src/process/task.rs | 9 +-- src/kxos-std/src/process/user_vm_data.rs | 6 ++ src/kxos-std/src/process/wait.rs | 2 +- src/kxos-std/src/syscall/access.rs | 13 ++++ src/kxos-std/src/syscall/arch_prctl.rs | 10 ++- src/kxos-std/src/syscall/brk.rs | 2 +- src/kxos-std/src/syscall/constants.rs | 1 + src/kxos-std/src/syscall/execve.rs | 53 ++++++++++++++++ src/kxos-std/src/syscall/exit.rs | 2 +- src/kxos-std/src/syscall/exit_group.rs | 2 +- src/kxos-std/src/syscall/fork.rs | 6 +- src/kxos-std/src/syscall/fstat.rs | 19 +++++- src/kxos-std/src/syscall/futex.rs | 7 +- src/kxos-std/src/syscall/getpid.rs | 2 +- src/kxos-std/src/syscall/gettid.rs | 2 +- src/kxos-std/src/syscall/mmap.rs | 7 +- src/kxos-std/src/syscall/mod.rs | 15 ++++- src/kxos-std/src/syscall/mprotect.rs | 8 +-- src/kxos-std/src/syscall/readlink.rs | 5 +- src/kxos-std/src/syscall/sched_yield.rs | 2 +- src/kxos-std/src/syscall/tgkill.rs | 2 +- src/kxos-std/src/syscall/uname.rs | 6 +- src/kxos-std/src/syscall/wait4.rs | 2 +- src/kxos-std/src/syscall/write.rs | 3 +- src/kxos-std/src/syscall/writev.rs | 3 +- src/kxos-std/src/user_apps.rs | 68 ++++++++++++++++++++ src/kxos-typeflags-util/src/lib.rs | 4 +- src/kxos-typeflags-util/src/set.rs | 4 +- src/kxos-user/execve/Makefile | 9 +++ src/kxos-user/execve/execve | 3 + src/kxos-user/execve/execve.c | 13 ++++ src/kxos-user/execve/hello | 3 + src/kxos-user/execve/hello.c | 6 ++ 53 files changed, 544 insertions(+), 152 deletions(-) create mode 100644 src/kxos-std/src/fs/mod.rs create mode 100644 src/kxos-std/src/fs/stat.rs create mode 100644 src/kxos-std/src/prelude.rs create mode 100644 src/kxos-std/src/process/table.rs create mode 100644 src/kxos-std/src/syscall/access.rs create mode 100644 src/kxos-std/src/syscall/constants.rs create mode 100644 src/kxos-std/src/syscall/execve.rs create mode 100644 src/kxos-std/src/user_apps.rs create mode 100644 src/kxos-user/execve/Makefile create mode 100755 src/kxos-user/execve/execve create mode 100644 src/kxos-user/execve/execve.c create mode 100755 src/kxos-user/execve/hello create mode 100644 src/kxos-user/execve/hello.c diff --git a/.gitattributes b/.gitattributes index 77f296762..e0b3ca940 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,5 @@ src/kxos-user/hello_world/hello_world filter=lfs diff=lfs merge=lfs -text src/kxos-user/fork/fork filter=lfs diff=lfs merge=lfs -text src/kxos-user/hello_c/hello filter=lfs diff=lfs merge=lfs -text +src/kxos-user/execve/execve filter=lfs diff=lfs merge=lfs -text +src/kxos-user/execve/hello filter=lfs diff=lfs merge=lfs -text diff --git a/src/kxos-frame/src/cpu.rs b/src/kxos-frame/src/cpu.rs index 83637dc85..89878205c 100644 --- a/src/kxos-frame/src/cpu.rs +++ b/src/kxos-frame/src/cpu.rs @@ -22,7 +22,7 @@ pub fn this_cpu() -> u32 { } /// Cpu context, including both general-purpose registers and floating-point registers. -#[derive(Clone, Default, Copy)] +#[derive(Clone, Default, Copy, Debug)] #[repr(C)] pub struct CpuContext { pub gp_regs: GpRegs, @@ -31,7 +31,7 @@ pub struct CpuContext { /// trap information, this field is all zero when it is syscall pub trap_information: TrapInformation, } -#[derive(Clone, Default, Copy)] +#[derive(Clone, Default, Copy, Debug)] #[repr(C)] pub struct TrapInformation { pub cr2: u64, @@ -195,7 +195,7 @@ impl Into for CpuContext { } /// The floating-point state of CPU. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] #[repr(C)] pub struct FpRegs { //buf: Aligned, diff --git a/src/kxos-frame/src/mm/memory_set.rs b/src/kxos-frame/src/mm/memory_set.rs index 957c45c9a..e0afebb5b 100644 --- a/src/kxos-frame/src/mm/memory_set.rs +++ b/src/kxos-frame/src/mm/memory_set.rs @@ -28,7 +28,7 @@ pub struct MemorySet { impl MapArea { pub fn mapped_size(&self) -> usize { - self.mapper.len() + self.size } pub fn clone(&self) -> Self { diff --git a/src/kxos-frame/src/user.rs b/src/kxos-frame/src/user.rs index 49cf58134..bbf45c585 100644 --- a/src/kxos-frame/src/user.rs +++ b/src/kxos-frame/src/user.rs @@ -134,6 +134,7 @@ impl<'a> UserMode<'a> { } else { // x86_64_util::wrfsbase(self.context.fs_base); *self.current.syscall_frame() = self.context.into(); + self.current.syscall_frame().caller.rcx = self.context.gp_regs.rip; } } diff --git a/src/kxos-frame/src/vm/space.rs b/src/kxos-frame/src/vm/space.rs index b4fe0712d..f7bf77ce2 100644 --- a/src/kxos-frame/src/vm/space.rs +++ b/src/kxos-frame/src/vm/space.rs @@ -90,6 +90,12 @@ impl VmSpace { Ok(()) } + /// clear all mappings + pub fn clear(&self) { + self.memory_set.lock().clear(); + crate::x86_64_util::flush_tlb(); + } + /// Update the VM protection permissions within the VM address range. /// /// The entire specified VM range must have been mapped with physical diff --git a/src/kxos-frame/src/x86_64_util.rs b/src/kxos-frame/src/x86_64_util.rs index 3a74269bb..10c8d05a2 100644 --- a/src/kxos-frame/src/x86_64_util.rs +++ b/src/kxos-frame/src/x86_64_util.rs @@ -223,3 +223,7 @@ pub fn enable_common_cpu_features() { } debug!("xcr0: {:?}", xcr0); } + +pub fn flush_tlb() { + x86_64::instructions::tlb::flush_all(); +} diff --git a/src/kxos-std/src/fs/mod.rs b/src/kxos-std/src/fs/mod.rs new file mode 100644 index 000000000..4f22af63a --- /dev/null +++ b/src/kxos-std/src/fs/mod.rs @@ -0,0 +1 @@ +pub mod stat; diff --git a/src/kxos-std/src/fs/stat.rs b/src/kxos-std/src/fs/stat.rs new file mode 100644 index 000000000..1a473fb2f --- /dev/null +++ b/src/kxos-std/src/fs/stat.rs @@ -0,0 +1,60 @@ +#![allow(non_camel_case_types)] + +type dev_t = usize; +type ino_t = usize; +type mode_t = u32; +type nlink_t = usize; +type uid_t = u32; +type gid_t = u32; +type off_t = u32; +type blksize_t = isize; +type blkcnt_t = isize; +type timespec = isize; + +pub const S_IFMT: u32 = 0o170000; +pub const S_IFCHR: u32 = 0o020000; +pub const S_IFDIR: u32 = 0o040000; +pub const S_IFREG: u32 = 0o100000; +pub const S_IFLNK: u32 = 0o120000; + +/// File Stat +#[derive(Debug, Clone, Copy, Pod, Default)] +pub struct Stat { + /// ID of device containing file + st_dev: dev_t, + /// Inode number + st_ino: ino_t, + /// File type and mode + st_mode: mode_t, + /// Number of hard links + st_nlink: nlink_t, + /// User ID of owner + st_uid: uid_t, + /// Group ID of owner + st_gid: gid_t, + /// Device ID (if special file) + st_rdev: dev_t, + /// Total size, in bytes + st_size: off_t, + /// Block size for filesystem I/O + st_blksize: blksize_t, + /// Number of 512B blocks allocated + st_blocks: blkcnt_t, + /// Time of last access + st_atime: timespec, + /// Time of last modification + st_mtime: timespec, + /// Time of last status change + st_ctime: timespec, +} + +impl Stat { + /// We use the same stat as linux + pub fn stdout_stat() -> Self { + let mut stat = Stat::default(); + stat.st_mode = S_IFCHR | 0o620; + stat.st_nlink = 1; + stat.st_blksize = 1024; + stat + } +} diff --git a/src/kxos-std/src/lib.rs b/src/kxos-std/src/lib.rs index d40b2febd..e2513392e 100644 --- a/src/kxos-std/src/lib.rs +++ b/src/kxos-std/src/lib.rs @@ -9,16 +9,20 @@ #![feature(exclusive_range_pattern)] #![feature(btree_drain_filter)] -use alloc::ffi::CString; use kxos_frame::{debug, info, println}; use process::Process; +use crate::user_apps::get_all_apps; + extern crate alloc; pub mod driver; +pub mod fs; mod memory; +pub mod prelude; mod process; pub mod syscall; +mod user_apps; mod util; #[macro_use] extern crate kxos_frame_pod_derive; @@ -41,27 +45,16 @@ pub fn init_process() { process.pid() ); - let hello_world_content = read_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 hello_c_content = read_hello_c_content(); - // glibc requires the filename starts as "/" - 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()); - - let fork_content = read_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() - ); + for app in get_all_apps() { + let app_name = app.app_name(); + info!("[kxos-std/lib.rs] spwan {:?} process", app.app_name()); + let process = Process::spawn_user_process(app_name, app.app_content()); + info!( + "[kxos-std/lib.rs] {:?} process exits, pid = {}", + app.app_name(), + process.pid() + ); + } loop { // We don't have preemptive scheduler now. @@ -72,19 +65,7 @@ pub fn init_process() { /// first process never return pub fn run_first_process() -> ! { - let elf_file_content = read_hello_world_content(); + // let elf_file_content = read_hello_world_content(); Process::spawn_kernel_process(init_process); unreachable!() } - -pub fn read_hello_world_content() -> &'static [u8] { - include_bytes!("../../kxos-user/hello_world/hello_world") -} - -fn read_fork_content() -> &'static [u8] { - include_bytes!("../../kxos-user/fork/fork") -} - -fn read_hello_c_content() -> &'static [u8] { - include_bytes!("../../kxos-user/hello_c/hello") -} diff --git a/src/kxos-std/src/memory/aux_vec.rs b/src/kxos-std/src/memory/aux_vec.rs index 3f3c708a3..b30ba35f1 100644 --- a/src/kxos-std/src/memory/aux_vec.rs +++ b/src/kxos-std/src/memory/aux_vec.rs @@ -1,4 +1,4 @@ -use alloc::collections::BTreeMap; +use crate::prelude::*; /// This implementation is from occlum. diff --git a/src/kxos-std/src/memory/elf.rs b/src/kxos-std/src/memory/elf.rs index 023ffbdfc..fdbfb9821 100644 --- a/src/kxos-std/src/memory/elf.rs +++ b/src/kxos-std/src/memory/elf.rs @@ -1,19 +1,15 @@ //! This module is used to parse elf file content to get elf_load_info. //! When create a process from elf file, we will use the elf_load_info to construct the VmSpace +use crate::prelude::*; use core::{cmp::Ordering, ops::Range}; - -use alloc::ffi::CString; -use alloc::vec; -use alloc::vec::Vec; use kxos_frame::{ - config::PAGE_SIZE, - vm::{Vaddr, VmIo, VmPerm, VmSpace}, + vm::{VmIo, VmPerm, VmSpace}, Error, }; use xmas_elf::{ header, - program::{self, ProgramHeader, SegmentData}, + program::{self, ProgramHeader, ProgramHeader64, SegmentData}, ElfFile, }; @@ -23,6 +19,7 @@ pub struct ElfLoadInfo<'a> { entry_point: Vaddr, segments: Vec>, init_stack: InitStack, + elf_header_info: ElfHeaderInfo, } pub struct ElfSegment<'a> { @@ -32,6 +29,17 @@ pub struct ElfSegment<'a> { vm_perm: VmPerm, } +#[derive(Debug, Clone, Copy, Default)] +/// Info parsed from elf header. Used to set aux vector. +pub struct ElfHeaderInfo { + /// page header table offset + pub ph_off: u64, + /// number of program headers + pub ph_num: u16, + /// The size of a program header + pub ph_ent: usize, +} + impl<'a> ElfSegment<'a> { fn parse_elf_segment( segment: ProgramHeader<'a>, @@ -92,9 +100,20 @@ impl<'a> ElfSegment<'a> { page.map_page(vm_space, vm_perm)?; } } - // copy segment vm_space.write_bytes(self.start_address(), self.data)?; + + // The length of segment may be greater than the length of data + // In this case, the additional bytes should be zeroed. + let segment_len = self.end_address() - self.start_address(); + let data_len = self.data.len(); + if segment_len > data_len { + let zeroed_bytes = vec![0u8; segment_len - data_len]; + let write_addr = self.start_address() + data_len; + vm_space + .write_bytes(write_addr, &zeroed_bytes) + .expect("Write zeroed bytes failed"); + } Ok(()) } @@ -104,11 +123,17 @@ impl<'a> ElfSegment<'a> { } impl<'a> ElfLoadInfo<'a> { - fn with_capacity(entry_point: Vaddr, capacity: usize, init_stack: InitStack) -> Self { + fn with_capacity( + entry_point: Vaddr, + capacity: usize, + init_stack: InitStack, + elf_header_info: ElfHeaderInfo, + ) -> Self { Self { entry_point, segments: Vec::with_capacity(capacity), init_stack, + elf_header_info, } } @@ -124,10 +149,12 @@ impl<'a> ElfLoadInfo<'a> { check_elf_header(&elf_file)?; // init elf load info let entry_point = elf_file.header.pt2.entry_point() as Vaddr; + let elf_header_info = ElfHeaderInfo::parse_elf_header(&elf_file); // FIXME: only contains load segment? let segments_count = elf_file.program_iter().count(); let init_stack = InitStack::new_default_config(filename); - let mut elf_load_info = ElfLoadInfo::with_capacity(entry_point, segments_count, init_stack); + let mut elf_load_info = + ElfLoadInfo::with_capacity(entry_point, segments_count, init_stack, elf_header_info); // parse each segemnt for segment in elf_file.program_iter() { @@ -168,10 +195,22 @@ impl<'a> ElfLoadInfo<'a> { pub fn init_stack(&mut self, vm_space: &VmSpace) { self.init_stack - .init(vm_space) + .init(vm_space, &self.elf_header_info) .expect("Init User Stack failed"); } + /// This function will write the first page of elf file to the initial stack top. + /// This function must be called after init process initial stack. + /// This infomation is used to set Auxv vectors. + pub fn write_elf_first_page(&self, vm_space: &VmSpace, file_content: &[u8]) { + let write_len = PAGE_SIZE.min(file_content.len()); + let write_content = &file_content[..write_len]; + let write_addr = self.init_stack.init_stack_top() - PAGE_SIZE; + vm_space + .write_bytes(write_addr, write_content) + .expect("Write elf content failed"); + } + /// return the perm of elf pages /// FIXME: Set the correct permission bit of user pages. fn perm() -> VmPerm { @@ -228,6 +267,19 @@ impl<'a> ElfLoadInfo<'a> { } } +impl ElfHeaderInfo { + fn parse_elf_header(elf_file: &ElfFile) -> Self { + let ph_off = elf_file.header.pt2.ph_offset(); + let ph_num = elf_file.header.pt2.ph_count(); + let ph_ent = core::mem::size_of::(); + ElfHeaderInfo { + ph_off, + ph_num, + ph_ent, + } + } +} + fn check_elf_header(elf_file: &ElfFile) -> Result<(), ElfError> { let elf_header = elf_file.header; // 64bit diff --git a/src/kxos-std/src/memory/init_stack.rs b/src/kxos-std/src/memory/init_stack.rs index e8df7d698..765eceecf 100644 --- a/src/kxos-std/src/memory/init_stack.rs +++ b/src/kxos-std/src/memory/init_stack.rs @@ -2,17 +2,14 @@ //! 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 +use crate::prelude::*; use core::mem; - -use alloc::vec; -use alloc::{ffi::CString, vec::Vec}; use kxos_frame::{ - config::PAGE_SIZE, - debug, - vm::{Vaddr, VmIo, VmPerm, VmSpace}, + vm::{VmIo, VmPerm, VmSpace}, AlignExt, }; +use super::elf::ElfHeaderInfo; use super::{ aux_vec::{AuxKey, AuxVec}, elf::ElfError, @@ -101,7 +98,6 @@ impl InitStack { /// the user stack top(high address), used to setup rsp pub fn user_stack_top(&self) -> Vaddr { let stack_top = self.pos; - debug!("user stack top: 0x{:x}", stack_top); // ensure stack top is 16-bytes aligned debug_assert!(stack_top & !0xf == stack_top); stack_top @@ -112,9 +108,14 @@ impl InitStack { self.init_stack_top - self.init_stack_size } - pub fn init(&mut self, vm_space: &VmSpace) -> Result<(), ElfError> { + pub fn init( + &mut self, + vm_space: &VmSpace, + elf_header_info: &ElfHeaderInfo, + ) -> Result<(), ElfError> { self.map_and_zeroed(vm_space); - self.write_stack_content(vm_space); + self.write_zero_page(vm_space); // This page is used to store page header table + self.write_stack_content(vm_space, elf_header_info); self.debug_print_stack_content(vm_space); Ok(()) } @@ -146,7 +147,11 @@ impl InitStack { } } - fn write_stack_content(&mut self, vm_space: &VmSpace) { + fn write_zero_page(&mut self, vm_space: &VmSpace) { + self.pos -= PAGE_SIZE; + } + + fn write_stack_content(&mut self, vm_space: &VmSpace, elf_header_info: &ElfHeaderInfo) { // write envp string let envp_pointers = self.write_envp_strings(vm_space); // write argv string @@ -157,6 +162,21 @@ impl InitStack { self.aux_vec .set(AuxKey::AT_RANDOM, random_value_pointer) .expect("Set random value failed"); + self.aux_vec + .set(AuxKey::AT_PAGESZ, PAGE_SIZE as _) + .expect("Set Page Size failed"); + self.aux_vec + .set( + AuxKey::AT_PHDR, + self.init_stack_top as u64 - PAGE_SIZE as u64 + elf_header_info.ph_off, + ) + .unwrap(); + self.aux_vec + .set(AuxKey::AT_PHNUM, elf_header_info.ph_num as u64) + .unwrap(); + self.aux_vec + .set(AuxKey::AT_PHENT, elf_header_info.ph_ent as u64) + .unwrap(); self.adjust_stack_alignment(vm_space, &envp_pointers, &argv_pointers); self.write_aux_vec(vm_space); self.write_envp_pointers(vm_space, envp_pointers); @@ -251,6 +271,13 @@ impl InitStack { pub fn envp(&self) -> u64 { 0 } + + /// returns the top address of init stack. + /// It should points to a fixed address. + pub const fn init_stack_top(&self) -> Vaddr { + self.init_stack_top + } + /// returns the u64 start address fn write_u64(&mut self, val: u64, vm_space: &VmSpace) -> u64 { let start_address = (self.pos - 8).align_down(8); diff --git a/src/kxos-std/src/memory/mmap_area.rs b/src/kxos-std/src/memory/mmap_area.rs index 9bc25b52c..cec13a8d9 100644 --- a/src/kxos-std/src/memory/mmap_area.rs +++ b/src/kxos-std/src/memory/mmap_area.rs @@ -1,10 +1,7 @@ use core::sync::atomic::{AtomicUsize, Ordering}; -use kxos_frame::{ - config::PAGE_SIZE, - debug, - vm::{Vaddr, VmPerm, VmSpace}, -}; +use crate::prelude::*; +use kxos_frame::vm::{VmPerm, VmSpace}; use super::{init_stack::INIT_STACK_BASE, vm_page::VmPageRange}; use crate::syscall::mmap::MMapFlags; @@ -52,6 +49,11 @@ impl MmapArea { debug!("mmap area start: 0x{:x}, size: {}", current, len); current } + + /// Set mmap area to the default status. i.e., point current to base. + pub fn set_default(&self) { + self.current.store(self.base_addr, Ordering::Relaxed); + } } impl Clone for MmapArea { diff --git a/src/kxos-std/src/memory/mod.rs b/src/kxos-std/src/memory/mod.rs index 372c01ab5..80d41f9bf 100644 --- a/src/kxos-std/src/memory/mod.rs +++ b/src/kxos-std/src/memory/mod.rs @@ -4,11 +4,8 @@ pub mod init_stack; pub mod mmap_area; pub mod user_heap; pub mod vm_page; -use alloc::ffi::CString; -use kxos_frame::{ - debug, - vm::{Pod, Vaddr, VmIo, VmSpace}, -}; +use crate::prelude::*; +use kxos_frame::vm::{Pod, VmIo, VmSpace}; use crate::process::Process; @@ -29,6 +26,8 @@ pub fn load_elf_to_vm_space<'a>( elf_load_info.debug_check_map_result(vm_space); debug!("map elf success"); elf_load_info.init_stack(vm_space); + elf_load_info.write_elf_first_page(vm_space, elf_file_content); + Ok(elf_load_info) } diff --git a/src/kxos-std/src/memory/user_heap.rs b/src/kxos-std/src/memory/user_heap.rs index 1f9d08c81..ad10e6635 100644 --- a/src/kxos-std/src/memory/user_heap.rs +++ b/src/kxos-std/src/memory/user_heap.rs @@ -1,9 +1,7 @@ use core::sync::atomic::{AtomicUsize, Ordering}; -use kxos_frame::{ - debug, - vm::{Vaddr, VmPerm, VmSpace}, -}; +use crate::prelude::*; +use kxos_frame::vm::{VmPerm, VmSpace}; use super::vm_page::{VmPage, VmPageRange}; @@ -28,7 +26,11 @@ impl UserHeap { match new_heap_end { None => return self.current_heap_end.load(Ordering::Relaxed), Some(new_heap_end) => { - let current_heap_end = self.current_heap_end.swap(new_heap_end, Ordering::Relaxed); + let current_heap_end = self.current_heap_end.load(Ordering::Acquire); + if new_heap_end < current_heap_end { + return current_heap_end; + } + self.current_heap_end.store(new_heap_end, Ordering::Release); let start_page = VmPage::containing_address(current_heap_end - 1).next_page(); let end_page = VmPage::containing_address(new_heap_end); if end_page >= start_page { @@ -50,6 +52,12 @@ impl UserHeap { const fn user_heap_perm() -> VmPerm { VmPerm::RWXU } + + /// Set heap to the default status. i.e., point the heap end to heap base. + pub fn set_default(&self) { + self.current_heap_end + .store(self.heap_base, Ordering::Relaxed); + } } impl Clone for UserHeap { diff --git a/src/kxos-std/src/memory/vm_page.rs b/src/kxos-std/src/memory/vm_page.rs index 2a724ecff..74ef57028 100644 --- a/src/kxos-std/src/memory/vm_page.rs +++ b/src/kxos-std/src/memory/vm_page.rs @@ -1,11 +1,7 @@ //! A Page in virtual address space +use crate::prelude::*; use core::ops::Range; - -use alloc::vec; -use kxos_frame::{ - config::PAGE_SIZE, - vm::{Vaddr, VmAllocOptions, VmFrameVec, VmIo, VmMapOptions, VmPerm, VmSpace}, -}; +use kxos_frame::vm::{VmAllocOptions, VmFrameVec, VmIo, VmMapOptions, VmPerm, VmSpace}; use super::elf::ElfError; diff --git a/src/kxos-std/src/prelude.rs b/src/kxos-std/src/prelude.rs new file mode 100644 index 000000000..58bb28c2d --- /dev/null +++ b/src/kxos-std/src/prelude.rs @@ -0,0 +1,28 @@ +#![allow(unused)] + +pub(crate) use alloc::boxed::Box; +pub(crate) use alloc::collections::BTreeMap; +pub(crate) use alloc::collections::VecDeque; +pub(crate) use alloc::ffi::CString; +pub(crate) use alloc::sync::Arc; +pub(crate) use alloc::sync::Weak; +#[allow(unused)] +pub(crate) use alloc::vec; +pub(crate) use alloc::vec::Vec; +pub(crate) use bitflags::bitflags; +pub(crate) use core::ffi::CStr; +pub(crate) use kxos_frame::config::PAGE_SIZE; +pub(crate) use kxos_frame::vm::Vaddr; +#[allow(unused)] +pub(crate) use kxos_frame::{debug, error, info, trace, warn}; +pub(crate) use spin::Mutex; + +#[macro_export] +macro_rules! current { + () => { + crate::process::Process::current() + }; +} + +pub(crate) use crate::current; +pub(crate) use lazy_static::lazy_static; diff --git a/src/kxos-std/src/process/fifo_scheduler.rs b/src/kxos-std/src/process/fifo_scheduler.rs index 2d6450bfc..9ba6f41c9 100644 --- a/src/kxos-std/src/process/fifo_scheduler.rs +++ b/src/kxos-std/src/process/fifo_scheduler.rs @@ -1,17 +1,16 @@ -use alloc::{boxed::Box, collections::VecDeque, sync::Arc}; +use crate::prelude::*; use kxos_frame::task::{set_scheduler, Scheduler, Task}; -use spin::mutex::SpinMutex; pub const TASK_INIT_CAPABILITY: usize = 16; pub struct FifoScheduler { - tasks: SpinMutex>>, + tasks: Mutex>>, } impl FifoScheduler { pub fn new() -> Self { Self { - tasks: SpinMutex::new(VecDeque::with_capacity(TASK_INIT_CAPABILITY)), + tasks: Mutex::new(VecDeque::with_capacity(TASK_INIT_CAPABILITY)), } } } diff --git a/src/kxos-std/src/process/mod.rs b/src/kxos-std/src/process/mod.rs index 4d300ce7e..75829456b 100644 --- a/src/kxos-std/src/process/mod.rs +++ b/src/kxos-std/src/process/mod.rs @@ -1,11 +1,8 @@ use core::sync::atomic::{AtomicI32, AtomicUsize, Ordering}; -use alloc::collections::BTreeMap; -use alloc::ffi::CString; -use alloc::sync::{Arc, Weak}; +use crate::prelude::*; use kxos_frame::sync::WaitQueue; -use kxos_frame::{debug, task::Task, user::UserSpace, vm::VmSpace}; -use spin::Mutex; +use kxos_frame::{task::Task, user::UserSpace, vm::VmSpace}; use crate::memory::mmap_area::MmapArea; use crate::memory::user_heap::UserHeap; @@ -18,6 +15,7 @@ use self::user_vm_data::UserVm; pub mod fifo_scheduler; pub mod process_filter; pub mod status; +pub mod table; pub mod task; pub mod user_vm_data; pub mod wait; @@ -119,14 +117,16 @@ impl Process { fn create_user_process(filename: CString, elf_file_content: &'static [u8]) -> Arc { let pid = new_pid(); - Arc::new_cyclic(|weak_process_ref| { + let user_process = Arc::new_cyclic(|weak_process_ref| { let weak_process = weak_process_ref.clone(); let cloned_filename = Some(filename.clone()); 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()); let user_vm = UserVm::new(); Process::new(pid, task, cloned_filename, Some(user_vm), user_space) - }) + }); + table::add_process(pid, user_process.clone()); + user_process } fn create_kernel_process(task_fn: F) -> Arc @@ -134,11 +134,13 @@ impl Process { F: Fn() + Send + Sync + 'static, { let pid = new_pid(); - Arc::new_cyclic(|weak_process_ref| { + let kernel_process = Arc::new_cyclic(|weak_process_ref| { let weak_process = weak_process_ref.clone(); let task = Task::new(task_fn, weak_process, None).expect("spawn kernel task failed"); Process::new(pid, task, None, None, None) - }) + }); + table::add_process(pid, kernel_process.clone()); + kernel_process } /// returns the pid of the process @@ -265,6 +267,7 @@ impl Process { pub fn reap_zombie_child(&self, pid: Pid) -> i32 { let child_process = self.children.lock().remove(&pid).unwrap(); assert!(child_process.status() == ProcessStatus::Zombie); + table::delete_process(child_process.pid()); child_process.exit_code() } diff --git a/src/kxos-std/src/process/table.rs b/src/kxos-std/src/process/table.rs new file mode 100644 index 000000000..386381cfb --- /dev/null +++ b/src/kxos-std/src/process/table.rs @@ -0,0 +1,38 @@ +//! A global table stores the pid to process mapping. +//! This table can be used to get process with pid. +//! TODO: progress group, thread all need similar mapping + +use crate::prelude::*; + +use super::{Pid, Process}; + +lazy_static! { + static ref PROCESS_TABLE: Mutex>> = Mutex::new(BTreeMap::new()); +} + +/// add a process to global table +pub fn add_process(pid: Pid, process: Arc) { + PROCESS_TABLE.lock().insert(pid, process); +} + +/// delete a process from global table +pub fn delete_process(pid: Pid) { + PROCESS_TABLE.lock().remove(&pid); +} + +/// get a process with pid +pub fn pid_to_process(pid: Pid) -> Option> { + PROCESS_TABLE + .lock() + .get(&pid) + .map(|process| process.clone()) +} + +/// get all processes +pub fn get_all_processes() -> Vec> { + PROCESS_TABLE + .lock() + .iter() + .map(|(_, process)| process.clone()) + .collect() +} diff --git a/src/kxos-std/src/process/task.rs b/src/kxos-std/src/process/task.rs index d4c5f363d..77fad432d 100644 --- a/src/kxos-std/src/process/task.rs +++ b/src/kxos-std/src/process/task.rs @@ -1,17 +1,14 @@ use core::sync::atomic::AtomicUsize; -use alloc::{ - ffi::CString, - sync::{Arc, Weak}, -}; use kxos_frame::{ cpu::CpuContext, - debug, task::Task, user::{UserEvent, UserMode, UserSpace}, vm::VmSpace, }; +use crate::prelude::*; + use crate::{memory::load_elf_to_vm_space, syscall::syscall_handler}; use super::Process; @@ -49,12 +46,12 @@ pub fn create_new_task(userspace: Arc, parent: Weak) -> Arc< debug!("[new task] rax = 0x{:x}", user_space.cpu_ctx.gp_regs.rax); 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? break; } + // debug!("before return to user space: {:#x?}", context); } let current_process = Process::current(); current_process.exit(); diff --git a/src/kxos-std/src/process/user_vm_data.rs b/src/kxos-std/src/process/user_vm_data.rs index a91bba580..e216487fa 100644 --- a/src/kxos-std/src/process/user_vm_data.rs +++ b/src/kxos-std/src/process/user_vm_data.rs @@ -57,4 +57,10 @@ impl UserVm { pub fn mmap_area(&self) -> &MmapArea { &self.mmap_area } + + /// Set user vm to the init status + pub fn set_default(&self) { + self.user_heap.set_default(); + self.mmap_area.set_default(); + } } diff --git a/src/kxos-std/src/process/wait.rs b/src/kxos-std/src/process/wait.rs index d3a54c473..14b958d23 100644 --- a/src/kxos-std/src/process/wait.rs +++ b/src/kxos-std/src/process/wait.rs @@ -1,4 +1,4 @@ -use bitflags::bitflags; +use crate::prelude::*; use super::{process_filter::ProcessFilter, ExitCode, Pid, Process}; diff --git a/src/kxos-std/src/syscall/access.rs b/src/kxos-std/src/syscall/access.rs new file mode 100644 index 000000000..452fb65e9 --- /dev/null +++ b/src/kxos-std/src/syscall/access.rs @@ -0,0 +1,13 @@ +use super::constants::*; +use super::SyscallResult; +use crate::{memory::read_bytes_from_user, prelude::*, syscall::SYS_ACCESS}; + +pub fn sys_access(filename_ptr: Vaddr, file_mode: u64) -> SyscallResult { + debug!("[syscall][id={}][SYS_ACCESS]", SYS_ACCESS); + let mut filename_buffer = vec![0u8; MAX_FILENAME_LEN]; + read_bytes_from_user(filename_ptr, &mut filename_buffer); + let filename = CString::from(CStr::from_bytes_until_nul(&filename_buffer).unwrap()); + debug!("filename: {:?}", filename); + warn!("access currenly does not check and just return success"); + SyscallResult::Return(0) +} diff --git a/src/kxos-std/src/syscall/arch_prctl.rs b/src/kxos-std/src/syscall/arch_prctl.rs index d75a84b00..27bd70eec 100644 --- a/src/kxos-std/src/syscall/arch_prctl.rs +++ b/src/kxos-std/src/syscall/arch_prctl.rs @@ -1,8 +1,10 @@ -use kxos_frame::{cpu::CpuContext, debug}; +use kxos_frame::cpu::CpuContext; +use crate::prelude::*; use crate::syscall::{SyscallResult, SYS_ARCH_PRCTL}; #[allow(non_camel_case_types)] +#[derive(Debug)] pub enum ArchPrctlCode { ARCH_SET_GS = 0x1001, ARCH_SET_FS = 0x1002, @@ -19,7 +21,10 @@ impl TryFrom for ArchPrctlCode { 0x1002 => Ok(ArchPrctlCode::ARCH_SET_FS), 0x1003 => Ok(ArchPrctlCode::ARCH_GET_FS), 0x1004 => Ok(ArchPrctlCode::ARCH_GET_GS), - _ => Err("Unknown code for arch_prctl"), + _ => { + debug!("value = 0x{:x}", value); + Err("Unknown code for arch_prctl") + } } } } @@ -27,6 +32,7 @@ impl TryFrom for ArchPrctlCode { pub fn sys_arch_prctl(code: u64, addr: u64, context: &mut CpuContext) -> SyscallResult { debug!("[syscall][id={}][SYS_ARCH_PRCTL]", SYS_ARCH_PRCTL); let arch_prctl_code = ArchPrctlCode::try_from(code); + debug!("arch_prctl_code: {:?}", arch_prctl_code); match arch_prctl_code { Err(_) => SyscallResult::Return(-1), Ok(code) => { diff --git a/src/kxos-std/src/syscall/brk.rs b/src/kxos-std/src/syscall/brk.rs index 3c13ec8cb..906570377 100644 --- a/src/kxos-std/src/syscall/brk.rs +++ b/src/kxos-std/src/syscall/brk.rs @@ -1,4 +1,4 @@ -use kxos_frame::debug; +use crate::prelude::*; use crate::{ process::Process, diff --git a/src/kxos-std/src/syscall/constants.rs b/src/kxos-std/src/syscall/constants.rs new file mode 100644 index 000000000..13868c317 --- /dev/null +++ b/src/kxos-std/src/syscall/constants.rs @@ -0,0 +1 @@ +pub const MAX_FILENAME_LEN: usize = 128; diff --git a/src/kxos-std/src/syscall/execve.rs b/src/kxos-std/src/syscall/execve.rs new file mode 100644 index 000000000..2b8774dbc --- /dev/null +++ b/src/kxos-std/src/syscall/execve.rs @@ -0,0 +1,53 @@ +use kxos_frame::cpu::CpuContext; + +use super::constants::*; +use super::SyscallResult; +use crate::{ + memory::{load_elf_to_vm_space, read_bytes_from_user}, + prelude::*, + process::Process, + syscall::SYS_EXECVE, +}; + +pub fn sys_execve( + filename_ptr: Vaddr, + argv_ptr_ptr: Vaddr, + envp_ptr_ptr: Vaddr, + context: &mut CpuContext, +) -> SyscallResult { + debug!("[syscall][id={}][SYS_EXECVE]", SYS_EXECVE); + let mut filename_buffer = vec![0u8; MAX_FILENAME_LEN]; + read_bytes_from_user(filename_ptr, &mut filename_buffer); + let filename = CString::from(CStr::from_bytes_until_nul(&filename_buffer).unwrap()); + debug!("filename: {:?}", filename); + + if filename != CString::new("./hello").unwrap() { + panic!("Unknown filename."); + } + let elf_file_content = crate::user_apps::read_execve_hello_content(); + let current = Process::current(); + // Set process vm space to default + let vm_space = current + .vm_space() + .expect("[Internal Error] User process should have vm space"); + vm_space.clear(); + let user_vm = current + .user_vm() + .expect("[Internal Error] User process should have user vm"); + user_vm.set_default(); + // load elf content to new vm space + let elf_load_info = + load_elf_to_vm_space(filename, elf_file_content, &vm_space).expect("load elf failed"); + debug!("load elf in execve succeeds"); + // set cpu context to default + let defalut_content = CpuContext::default(); + context.gp_regs = defalut_content.gp_regs; + context.fs_base = defalut_content.fs_base; + // set new entry point + context.gp_regs.rip = elf_load_info.entry_point(); + debug!("entry_point: 0x{:x}", elf_load_info.entry_point()); + // set new user stack top + context.gp_regs.rsp = elf_load_info.user_stack_top(); + debug!("user stack top: 0x{:x}", elf_load_info.user_stack_top()); + SyscallResult::Return(0) +} diff --git a/src/kxos-std/src/syscall/exit.rs b/src/kxos-std/src/syscall/exit.rs index db9014160..6c6e87d48 100644 --- a/src/kxos-std/src/syscall/exit.rs +++ b/src/kxos-std/src/syscall/exit.rs @@ -1,4 +1,4 @@ -use kxos_frame::debug; +use crate::prelude::*; use crate::{process::Process, syscall::SYS_EXIT}; diff --git a/src/kxos-std/src/syscall/exit_group.rs b/src/kxos-std/src/syscall/exit_group.rs index 421f1a9a2..5d292d30c 100644 --- a/src/kxos-std/src/syscall/exit_group.rs +++ b/src/kxos-std/src/syscall/exit_group.rs @@ -1,4 +1,4 @@ -use kxos_frame::debug; +use crate::prelude::*; use crate::{ process::Process, diff --git a/src/kxos-std/src/syscall/fork.rs b/src/kxos-std/src/syscall/fork.rs index 6a45beb44..6e426ffb1 100644 --- a/src/kxos-std/src/syscall/fork.rs +++ b/src/kxos-std/src/syscall/fork.rs @@ -1,13 +1,12 @@ -use alloc::{sync::Arc, vec}; +use crate::prelude::*; use kxos_frame::{ cpu::CpuContext, - debug, user::UserSpace, vm::{VmIo, VmSpace}, }; use crate::{ - process::{new_pid, task::create_new_task, Process}, + process::{new_pid, table, task::create_new_task, Process}, syscall::SYS_FORK, }; @@ -67,6 +66,7 @@ fn fork(parent_context: CpuContext) -> Arc { ) }); Process::current().add_child(child.clone()); + table::add_process(child_pid, child.clone()); let pid = current.pid(); debug!("*********schedule child process, pid = {}**********", pid); child.send_to_scheduler(); diff --git a/src/kxos-std/src/syscall/fstat.rs b/src/kxos-std/src/syscall/fstat.rs index 5a2a3b9ea..3cf237b50 100644 --- a/src/kxos-std/src/syscall/fstat.rs +++ b/src/kxos-std/src/syscall/fstat.rs @@ -1,11 +1,26 @@ -use kxos_frame::{debug, warn}; +use kxos_frame::vm::VmIo; + +use crate::fs::stat::Stat; +use crate::prelude::*; use crate::syscall::{SyscallResult, SYS_FSTAT}; -pub fn sys_fstat(fd: u64, stat_buf_addr: u64) -> SyscallResult { +pub fn sys_fstat(fd: u64, stat_buf_addr: Vaddr) -> SyscallResult { debug!("[syscall][id={}][SYS_FSTAT]", SYS_FSTAT); debug!("fd = {}", fd); debug!("stat_buf_addr = 0x{:x}", stat_buf_addr); + + let current = current!(); + let vm_space = current + .vm_space() + .expect("[Internel Error] User process should have vm space"); + if fd == 1 { + let stat = Stat::stdout_stat(); + vm_space + .write_val(stat_buf_addr, &stat) + .expect("Write value failed"); + return SyscallResult::Return(0); + } warn!("TODO: fstat only returns fake result now."); SyscallResult::Return(0) } diff --git a/src/kxos-std/src/syscall/futex.rs b/src/kxos-std/src/syscall/futex.rs index f3d57065f..57ff84791 100644 --- a/src/kxos-std/src/syscall/futex.rs +++ b/src/kxos-std/src/syscall/futex.rs @@ -1,11 +1,8 @@ use crate::{memory::read_val_from_user, syscall::SYS_FUTEX}; use super::SyscallResult; -use alloc::{sync::Arc, vec::Vec}; -use bitflags::bitflags; -use kxos_frame::{cpu::num_cpus, debug, sync::WaitQueue, vm::Vaddr, warn}; -use lazy_static::lazy_static; -use spin::Mutex; +use crate::prelude::*; +use kxos_frame::{cpu::num_cpus, sync::WaitQueue}; type FutexBitSet = u32; type FutexBucketRef = Arc>; diff --git a/src/kxos-std/src/syscall/getpid.rs b/src/kxos-std/src/syscall/getpid.rs index ac510c189..136760824 100644 --- a/src/kxos-std/src/syscall/getpid.rs +++ b/src/kxos-std/src/syscall/getpid.rs @@ -1,4 +1,4 @@ -use kxos_frame::{debug, info}; +use crate::prelude::*; use crate::{process::Process, syscall::SYS_GETPID}; diff --git a/src/kxos-std/src/syscall/gettid.rs b/src/kxos-std/src/syscall/gettid.rs index 97579169b..1f5b7bd7d 100644 --- a/src/kxos-std/src/syscall/gettid.rs +++ b/src/kxos-std/src/syscall/gettid.rs @@ -1,4 +1,4 @@ -use kxos_frame::debug; +use crate::prelude::*; use crate::{process::Process, syscall::SYS_GETTID}; diff --git a/src/kxos-std/src/syscall/mmap.rs b/src/kxos-std/src/syscall/mmap.rs index 41d9964e8..7f50af277 100644 --- a/src/kxos-std/src/syscall/mmap.rs +++ b/src/kxos-std/src/syscall/mmap.rs @@ -1,10 +1,7 @@ //! This mod defines mmap flags and the handler to syscall mmap -use bitflags::bitflags; -use kxos_frame::{ - debug, - vm::{Vaddr, VmPerm}, -}; +use crate::prelude::*; +use kxos_frame::vm::VmPerm; use crate::{process::Process, syscall::SYS_MMAP}; diff --git a/src/kxos-std/src/syscall/mod.rs b/src/kxos-std/src/syscall/mod.rs index ec2569d96..efd14c859 100644 --- a/src/kxos-std/src/syscall/mod.rs +++ b/src/kxos-std/src/syscall/mod.rs @@ -1,13 +1,15 @@ //! Read the Cpu context content then dispatch syscall to corrsponding handler //! The each sub module contains functions that handle real syscall logic. +use crate::prelude::*; use alloc::borrow::ToOwned; use kxos_frame::cpu::CpuContext; -use kxos_frame::{debug, warn}; use crate::process::task::HandlerResult; +use crate::syscall::access::sys_access; use crate::syscall::arch_prctl::sys_arch_prctl; use crate::syscall::brk::sys_brk; +use crate::syscall::execve::sys_execve; use crate::syscall::exit::sys_exit; use crate::syscall::exit_group::sys_exit_group; use crate::syscall::fork::sys_fork; @@ -25,8 +27,11 @@ use crate::syscall::waitid::sys_waitid; use crate::syscall::write::sys_write; use crate::syscall::writev::sys_writev; +mod access; mod arch_prctl; mod brk; +pub mod constants; +mod execve; mod exit; mod exit_group; mod fork; @@ -53,9 +58,11 @@ const SYS_BRK: u64 = 12; const SYS_RT_SIGACTION: u64 = 13; const SYS_RT_SIGPROCMASK: u64 = 14; const SYS_WRITEV: u64 = 20; +const SYS_ACCESS: u64 = 21; const SYS_SCHED_YIELD: u64 = 24; const SYS_GETPID: u64 = 39; const SYS_FORK: u64 = 57; +const SYS_EXECVE: u64 = 59; const SYS_EXIT: u64 = 60; const SYS_WAIT4: u64 = 61; const SYS_UNAME: u64 = 63; @@ -79,6 +86,7 @@ pub struct SyscallArgument { pub enum SyscallResult { Exit(i32), Return(i32), + ReturnNothing, // execve return nothing } impl SyscallArgument { @@ -110,6 +118,7 @@ pub fn syscall_handler(context: &mut CpuContext) -> HandlerResult { HandlerResult::Continue } SyscallResult::Exit(exit_code) => HandlerResult::Exit, + SyscallResult::ReturnNothing => HandlerResult::Continue, } } @@ -120,15 +129,17 @@ pub fn syscall_dispatch( ) -> SyscallResult { match syscall_number { SYS_WRITE => sys_write(args[0], args[1], args[2]), - SYS_FSTAT => sys_fstat(args[0], args[1]), + SYS_FSTAT => sys_fstat(args[0], args[1] as _), SYS_MMAP => sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5]), SYS_MPROTECT => sys_mprotect(args[0], args[1], args[2]), SYS_BRK => sys_brk(args[0]), SYS_RT_SIGACTION => sys_rt_sigaction(), SYS_RT_SIGPROCMASK => sys_rt_sigprocmask(), SYS_WRITEV => sys_writev(args[0], args[1], args[2]), + SYS_ACCESS => sys_access(args[0] as _, args[1]), SYS_GETPID => sys_getpid(), SYS_FORK => sys_fork(context.to_owned()), + SYS_EXECVE => sys_execve(args[0] as _, args[1] as _, args[2] as _, context), SYS_EXIT => sys_exit(args[0] as _), SYS_WAIT4 => sys_wait4(args[0], args[1], args[2]), SYS_UNAME => sys_uname(args[0]), diff --git a/src/kxos-std/src/syscall/mprotect.rs b/src/kxos-std/src/syscall/mprotect.rs index 164371733..259f10a53 100644 --- a/src/kxos-std/src/syscall/mprotect.rs +++ b/src/kxos-std/src/syscall/mprotect.rs @@ -1,8 +1,6 @@ -use kxos_frame::{ - debug, - vm::{Vaddr, VmPerm}, - warn, -}; +use kxos_frame::vm::VmPerm; + +use crate::prelude::*; use crate::syscall::SYS_MPROTECT; diff --git a/src/kxos-std/src/syscall/readlink.rs b/src/kxos-std/src/syscall/readlink.rs index bbb443f27..c9ae7da13 100644 --- a/src/kxos-std/src/syscall/readlink.rs +++ b/src/kxos-std/src/syscall/readlink.rs @@ -1,7 +1,4 @@ -use core::ffi::CStr; - -use alloc::ffi::CString; -use kxos_frame::{debug, vm::Vaddr}; +use crate::prelude::*; use crate::{ memory::{read_bytes_from_user, write_bytes_to_user}, diff --git a/src/kxos-std/src/syscall/sched_yield.rs b/src/kxos-std/src/syscall/sched_yield.rs index 52bcfb70b..d58217f84 100644 --- a/src/kxos-std/src/syscall/sched_yield.rs +++ b/src/kxos-std/src/syscall/sched_yield.rs @@ -1,4 +1,4 @@ -use kxos_frame::debug; +use crate::prelude::*; use crate::{process::Process, syscall::SYS_SCHED_YIELD}; diff --git a/src/kxos-std/src/syscall/tgkill.rs b/src/kxos-std/src/syscall/tgkill.rs index e564f140f..de9e419cc 100644 --- a/src/kxos-std/src/syscall/tgkill.rs +++ b/src/kxos-std/src/syscall/tgkill.rs @@ -1,4 +1,4 @@ -use kxos_frame::{debug, warn}; +use crate::prelude::*; use crate::syscall::{SyscallResult, SYS_TGKILL}; diff --git a/src/kxos-std/src/syscall/uname.rs b/src/kxos-std/src/syscall/uname.rs index a62a10d18..39b9cb998 100644 --- a/src/kxos-std/src/syscall/uname.rs +++ b/src/kxos-std/src/syscall/uname.rs @@ -1,8 +1,4 @@ -use core::ffi::CStr; - -use alloc::ffi::CString; -use kxos_frame::{debug, vm::Vaddr}; -use lazy_static::lazy_static; +use crate::prelude::*; use crate::{ memory::write_val_to_user, diff --git a/src/kxos-std/src/syscall/wait4.rs b/src/kxos-std/src/syscall/wait4.rs index 28ff3d434..1610ee4b1 100644 --- a/src/kxos-std/src/syscall/wait4.rs +++ b/src/kxos-std/src/syscall/wait4.rs @@ -5,8 +5,8 @@ use crate::{ }; use super::SyscallResult; +use crate::prelude::*; use crate::process::wait::WaitOptions; -use kxos_frame::debug; pub fn sys_wait4(wait_pid: u64, exit_status_ptr: u64, wait_options: u64) -> SyscallResult { debug!("[syscall][id={}][SYS_WAIT4]", SYS_WAIT4); diff --git a/src/kxos-std/src/syscall/write.rs b/src/kxos-std/src/syscall/write.rs index 123c68436..1d13d2551 100644 --- a/src/kxos-std/src/syscall/write.rs +++ b/src/kxos-std/src/syscall/write.rs @@ -1,5 +1,4 @@ -use alloc::vec; -use kxos_frame::{debug, info}; +use crate::prelude::*; use crate::{memory::read_bytes_from_user, syscall::SYS_WRITE}; diff --git a/src/kxos-std/src/syscall/writev.rs b/src/kxos-std/src/syscall/writev.rs index fdec71e13..1e66efc51 100644 --- a/src/kxos-std/src/syscall/writev.rs +++ b/src/kxos-std/src/syscall/writev.rs @@ -1,5 +1,4 @@ -use alloc::vec; -use kxos_frame::{debug, info, vm::Vaddr}; +use crate::prelude::*; use crate::{ memory::{read_bytes_from_user, read_val_from_user}, diff --git a/src/kxos-std/src/user_apps.rs b/src/kxos-std/src/user_apps.rs new file mode 100644 index 000000000..fe1cb92e1 --- /dev/null +++ b/src/kxos-std/src/user_apps.rs @@ -0,0 +1,68 @@ +use crate::prelude::*; + +pub struct UserApp { + app_name: CString, + app_content: &'static [u8], +} + +impl UserApp { + pub fn new(app_name: &str, app_content: &'static [u8]) -> Self { + let app_name = CString::new(app_name).unwrap(); + UserApp { + app_name, + app_content, + } + } + + pub fn app_name(&self) -> CString { + self.app_name.clone() + } + + pub fn app_content(&self) -> &'static [u8] { + self.app_content + } +} + +pub fn get_all_apps() -> Vec { + let mut res = Vec::new(); + + // Most simple hello world, written in assembly + let app1 = UserApp::new("hello_world", read_hello_world_content()); + res.push(app1); + + // Hello world, written in C language. + // Since glibc requires the app name starts with "/", and we don't have filesystem now. + // So we manually add a leading "/" for app written in C language. + let app2 = UserApp::new("/hello_c", read_hello_c_content()); + res.push(app2); + + // Fork process, written in assembly + let app3 = UserApp::new("fork", read_fork_content()); + res.push(app3); + + // Execve, written in C language. + let app4 = UserApp::new("/execve", read_execve_content()); + res.push(app4); + + res +} + +fn read_hello_world_content() -> &'static [u8] { + include_bytes!("../../kxos-user/hello_world/hello_world") +} + +fn read_hello_c_content() -> &'static [u8] { + include_bytes!("../../kxos-user/hello_c/hello") +} + +fn read_fork_content() -> &'static [u8] { + include_bytes!("../../kxos-user/fork/fork") +} + +fn read_execve_content() -> &'static [u8] { + include_bytes!("../../kxos-user/execve/execve") +} + +pub fn read_execve_hello_content() -> &'static [u8] { + include_bytes!("../../kxos-user/execve/hello") +} diff --git a/src/kxos-typeflags-util/src/lib.rs b/src/kxos-typeflags-util/src/lib.rs index a55c8af60..9d7b64004 100644 --- a/src/kxos-typeflags-util/src/lib.rs +++ b/src/kxos-typeflags-util/src/lib.rs @@ -1,7 +1,7 @@ //! The content of this crate is from another project CapComp. //! This crate defines common type level operations, like SameAsOp, and Bool type operations. //! Besides, this crate defines operations to deal with type sets, like SetContain and SetInclude. -//! When use kxos-typeflags or kxos-rights-poc, this crate should also be added as a dependency. +//! When use kxos-typeflags or kxos-rights-poc, this crate should also be added as a dependency. pub mod assert; pub mod bool; @@ -9,7 +9,7 @@ pub mod if_; pub mod same; pub mod set; -pub use crate::bool::{And, AndOp, False, Not, NotOp, Or, OrOp, True, IsFalse, IsTrue}; +pub use crate::bool::{And, AndOp, False, IsFalse, IsTrue, Not, NotOp, Or, OrOp, True}; pub use crate::same::{SameAs, SameAsOp}; pub use crate::set::{Cons, Nil, Set, SetContain, SetContainOp, SetInclude, SetIncludeOp}; pub use assert::AssertTypeSame; diff --git a/src/kxos-typeflags-util/src/set.rs b/src/kxos-typeflags-util/src/set.rs index 23cac701c..d8fae0a6c 100644 --- a/src/kxos-typeflags-util/src/set.rs +++ b/src/kxos-typeflags-util/src/set.rs @@ -3,10 +3,8 @@ use std::marker::PhantomData; use crate::{ - False, OrOp, True, - SameAs, SameAsOp, - And, AndOp, if_::{If, IfOp}, + And, AndOp, False, OrOp, SameAs, SameAsOp, True, }; use std::ops::BitOr as Or; diff --git a/src/kxos-user/execve/Makefile b/src/kxos-user/execve/Makefile new file mode 100644 index 000000000..e16195e14 --- /dev/null +++ b/src/kxos-user/execve/Makefile @@ -0,0 +1,9 @@ +.PHONY: build clean run +build: hello.c execve.c + @gcc -static hello.c -o hello + @gcc -static execve.c -o execve +clean: + @rm hello + @rm execve +run: build + @./execve \ No newline at end of file diff --git a/src/kxos-user/execve/execve b/src/kxos-user/execve/execve new file mode 100755 index 000000000..85ed4d0b3 --- /dev/null +++ b/src/kxos-user/execve/execve @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f98928f25e8223fd76d5d19db68e83913b48ea8b3cf6ae8d3120971e7271c93b +size 871952 diff --git a/src/kxos-user/execve/execve.c b/src/kxos-user/execve/execve.c new file mode 100644 index 000000000..1db4a5ab9 --- /dev/null +++ b/src/kxos-user/execve/execve.c @@ -0,0 +1,13 @@ +#include +#include + +int main() { + char* argv[] = { NULL }; + char* envp[] = { NULL }; + printf("Execve a new file ./hello:\n"); + // flust the stdout content to ensure the content print to console + fflush(stdout); + execve("./hello", argv, envp); + printf("Should not print\n"); + return 0; +} \ No newline at end of file diff --git a/src/kxos-user/execve/hello b/src/kxos-user/execve/hello new file mode 100755 index 000000000..dc2959f18 --- /dev/null +++ b/src/kxos-user/execve/hello @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b1e30d140892a01630093a376819dcfb400754c9dbf71f845df945fc14fc861 +size 871896 diff --git a/src/kxos-user/execve/hello.c b/src/kxos-user/execve/hello.c new file mode 100644 index 000000000..8bc0d9de0 --- /dev/null +++ b/src/kxos-user/execve/hello.c @@ -0,0 +1,6 @@ +#include + +int main() { + printf("Hello world from hello.c(execved in execve.c)!\n"); + return 0; +} \ No newline at end of file