From 42d40da973ebf775c58a5606d8ba791806d026d5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jeremy@system76.com> Date: Sun, 31 Mar 2019 15:04:37 -0600 Subject: [PATCH] Map stacks based on provided size. --- Cargo.lock | 12 ++++----- Cargo.toml | 2 +- src/lib.rs | 1 + src/platform/linux/mod.rs | 51 +++++++++++++++++++++++++++++-------- src/platform/pal/mod.rs | 2 +- src/platform/pte.rs | 53 ++++++++++++++++++++++++++++++++++++--- src/platform/redox/mod.rs | 49 +++++++++++++++++++++++++++++------- 7 files changed, 138 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 072da425..aca68310 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,7 +173,7 @@ dependencies = [ name = "ralloc_shim" version = "0.1.1" dependencies = [ - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -220,7 +220,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -228,7 +228,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -243,7 +243,7 @@ dependencies = [ "posix-regex 0.1.0", "ralloc 1.0.0", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "va_list 0.1.0", @@ -378,7 +378,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -480,7 +480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)" = "d32b3053e5ced86e4bc0411fec997389532bf56b000e66cb4884eeeb41413d69" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" diff --git a/Cargo.toml b/Cargo.toml index da451427..e1bf2e1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ optional = true sc = "0.2.2" [target.'cfg(target_os = "redox")'.dependencies] -redox_syscall = "0.1" +redox_syscall = "0.1.52" spin = "0.4.10" [features] diff --git a/src/lib.rs b/src/lib.rs index b3757e19..e7ba6c37 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ #![allow(unused_variables)] #![feature(alloc)] #![feature(allocator_api)] +#![feature(asm)] #![feature(const_fn)] #![feature(const_raw_ptr_deref)] #![feature(const_str_as_bytes)] diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 70c6bf17..ed0cb706 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -23,6 +23,7 @@ const AT_FDCWD: c_int = -100; const AT_EMPTY_PATH: c_int = 0x1000; const AT_REMOVEDIR: c_int = 0x200; +const SYS_CLONE: usize = 56; const CLONE_VM: usize = 0x0100; const CLONE_FS: usize = 0x0200; const CLONE_FILES: usize = 0x0400; @@ -326,17 +327,45 @@ impl Pal for Sys { e(unsafe { syscall!(POLL, fds, nfds, timeout) }) as c_int } - fn pte_clone() -> pid_t { - e(unsafe { - syscall!( - CLONE, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, - 0, - 0, - 0, - 0 - ) - }) as pid_t + #[cfg(target_arch = "x86_64")] + unsafe fn pte_clone(stack: *mut usize) -> pid_t { + let flags = + CLONE_VM | + CLONE_FS | + CLONE_FILES | + CLONE_SIGHAND; + let pid; + asm!(" + # Call clone syscall + syscall + + # Check if child or parent + test rax, rax + jnz .parent + + # Call entry point + pop rdi + pop rax + call rax + + # Exit + mov rax, 60 + xor rdi, rdi + syscall + + # Invalid instruction on failure to exit + ud2 + + # Return PID if parent + .parent: + " + : "={rax}"(pid) + : "{rax}"(SYS_CLONE), "{rdi}"(flags), "{rsi}"(stack), "{rdx}"(0), "{rcx}"(0), "{r8}"(0) + : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", + "r9", "r10", "r11", "r12", "r13", "r14", "r15" + : "intel", "volatile" + ); + e(pid) as pid_t } fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t { diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index 75410834..ba1052a7 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -117,7 +117,7 @@ pub trait Pal { fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int; - fn pte_clone() -> pid_t; + unsafe fn pte_clone(stack: *mut usize) -> pid_t; fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t; diff --git a/src/platform/pte.rs b/src/platform/pte.rs index b311726d..37d14a33 100644 --- a/src/platform/pte.rs +++ b/src/platform/pte.rs @@ -5,9 +5,10 @@ use alloc::collections::BTreeMap; use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use core::{intrinsics, ptr}; +use header::sys_mman; use header::time::timespec; use mutex::{FUTEX_WAIT, FUTEX_WAKE}; -use platform::types::{c_int, c_uint, c_void, pid_t}; +use platform::types::{c_int, c_uint, c_void, pid_t, size_t}; use platform::{Pal, Sys}; pub struct Semaphore { @@ -36,6 +37,9 @@ use self::pte_osResult::*; static mut pid_mutexes: Option<BTreeMap<pte_osThreadHandle, pte_osMutexHandle>> = None; static mut pid_mutexes_lock: i32 = 0; +static mut pid_stacks: Option<BTreeMap<pte_osThreadHandle, (*mut c_void, size_t)>> = None; +static mut pid_stacks_lock: i32 = 0; + #[thread_local] static mut LOCALS: *mut BTreeMap<c_uint, *mut c_void> = ptr::null_mut(); @@ -57,17 +61,41 @@ pub unsafe extern "C" fn pte_osInit() -> pte_osResult { #[no_mangle] pub unsafe extern "C" fn pte_osThreadCreate( entryPoint: pte_osThreadEntryPoint, - _stackSize: c_int, + stackSize: c_int, _initialPriority: c_int, argv: *mut c_void, ppte_osThreadHandle: *mut pte_osThreadHandle, ) -> pte_osResult { - // XXX error handling + let stack_size = if stackSize == 0 { + 1024 * 1024 + } else { + stackSize as usize + }; + let stack_base = sys_mman::mmap( + ptr::null_mut(), + stack_size, + sys_mman::PROT_READ | sys_mman::PROT_WRITE, + sys_mman::MAP_SHARED | sys_mman::MAP_ANONYMOUS, + -1, + 0 + ); + if stack_base as isize == -1 { + return PTE_OS_GENERAL_FAILURE; + } + let stack_end = stack_base.add(stack_size); + let mut stack = stack_end as *mut usize; + { + stack = stack.offset(-1); + *stack = entryPoint as usize; + + stack = stack.offset(-1); + *stack = argv as usize; + } // Create a locked mutex, unlocked by pte_osThreadStart let mutex = Box::into_raw(Box::new(2)); { - let id = Sys::pte_clone(); + let id = Sys::pte_clone(stack); if id < 0 { return PTE_OS_GENERAL_FAILURE; } @@ -84,6 +112,14 @@ pub unsafe extern "C" fn pte_osThreadCreate( } pid_mutexes.as_mut().unwrap().insert(id, mutex); pte_osMutexUnlock(&mut pid_mutexes_lock); + + pte_osMutexLock(&mut pid_stacks_lock); + if pid_stacks.is_none() { + pid_stacks = Some(BTreeMap::new()); + } + pid_stacks.as_mut().unwrap().insert(id, (stack_base, stack_size)); + pte_osMutexUnlock(&mut pid_stacks_lock); + *ppte_osThreadHandle = id; } } @@ -129,6 +165,15 @@ pub unsafe extern "C" fn pte_osThreadDelete(handle: pte_osThreadHandle) -> pte_o } } pte_osMutexUnlock(&mut pid_mutexes_lock); + + pte_osMutexLock(&mut pid_stacks_lock); + if let Some(ref mut stacks) = pid_stacks { + if let Some((stack_base, stack_size)) = stacks.remove(&handle) { + sys_mman::munmap(stack_base, stack_size); + } + } + pte_osMutexUnlock(&mut pid_stacks_lock); + PTE_OS_OK } diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index a1b801a3..564566da 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -815,15 +815,46 @@ impl Pal for Sys { total } - fn pte_clone() -> pid_t { - e(unsafe { - syscall::clone( - syscall::CLONE_VM - | syscall::CLONE_FS - | syscall::CLONE_FILES - | syscall::CLONE_SIGHAND, - ) - }) as pid_t + #[cfg(target_arch = "x86_64")] + unsafe fn pte_clone(stack: *mut usize) -> pid_t { + let flags = + syscall::CLONE_VM | + syscall::CLONE_FS | + syscall::CLONE_FILES | + syscall::CLONE_SIGHAND | + syscall::CLONE_STACK; + let pid; + asm!(" + # Call clone syscall + syscall + + # Check if child or parent + test rax, rax + jnz .parent + + # Call entry point + pop rdi + pop rax + call rax + + # Exit + mov rax, 1 + xor rdi, rdi + syscall + + # Invalid instruction on failure to exit + ud2 + + # Return PID if parent + .parent: + " + : "={rax}"(pid) + : "{rax}"(syscall::SYS_CLONE), "{rdi}"(flags), "{rsi}"(stack) + : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", + "r9", "r10", "r11", "r12", "r13", "r14", "r15" + : "intel", "volatile" + ); + e(syscall::Error::demux(pid)) as pid_t } fn read(fd: c_int, buf: &mut [u8]) -> ssize_t { -- GitLab