Merge branch 'userspace_fexec' into 'master'

Remove old exec/clone system calls in favor of userspace_fexec

See merge request redox-os/syscall!70
This commit is contained in:
Jeremy Soller
2022-07-27 15:31:29 +00:00
10 changed files with 42 additions and 116 deletions

View File

@@ -3,6 +3,8 @@ use core::ops::{Deref, DerefMut};
use super::error::{Error, Result};
pub const PAGE_SIZE: usize = 4096;
macro_rules! syscall {
($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
$(

View File

@@ -1,5 +1,8 @@
use super::error::{Error, Result, ENOSYS};
// Doesn't really matter, but since we will most likely run on an x86_64 host, why not 4096?
pub const PAGE_SIZE: usize = 4096;
pub unsafe fn syscall0(_a: usize) -> Result<usize> {
Err(Error::new(ENOSYS))
}

View File

@@ -4,6 +4,8 @@ use core::ops::{Deref, DerefMut};
use super::error::{Error, Result};
pub const PAGE_SIZE: usize = 4096;
macro_rules! syscall {
($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
$(

View File

@@ -4,6 +4,8 @@ use core::ops::{Deref, DerefMut};
use super::error::{Error, Result};
pub const PAGE_SIZE: usize = 4096;
macro_rules! syscall {
($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
$(

View File

@@ -38,11 +38,6 @@ pub fn chmod<T: AsRef<str>>(path: T, mode: usize) -> Result<usize> {
unsafe { syscall3(SYS_CHMOD, path.as_ref().as_ptr() as usize, path.as_ref().len(), mode) }
}
/// Produce a fork of the current process, or a new process thread
pub unsafe fn clone(flags: CloneFlags) -> Result<usize> {
syscall1(SYS_CLONE, flags.bits())
}
/// Close a file
pub fn close(fd: usize) -> Result<usize> {
unsafe { syscall1(SYS_CLOSE, fd) }
@@ -85,11 +80,6 @@ pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
}
/// Replace the current process with a new executable
pub fn fexec(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result<usize> {
unsafe { syscall5(SYS_FEXEC, fd, args.as_ptr() as usize, args.len(), vars.as_ptr() as usize, vars.len()) }
}
/// Map a file into memory, but with the ability to set the address to map into, either as a hint
/// or as a requirement of the map.
///

View File

@@ -1,62 +0,0 @@
use core::convert::Infallible;
use super::{
clone,
CloneFlags,
close,
EIO,
Error,
exit,
pipe2,
read,
Result,
write,
};
#[must_use = "Daemon::ready must be called"]
pub struct Daemon {
write_pipe: usize,
}
impl Daemon {
pub fn new<F: FnOnce(Daemon) -> Infallible>(f: F) -> Result<Infallible> {
let mut pipes = [0; 2];
pipe2(&mut pipes, 0)?;
let [read_pipe, write_pipe] = pipes;
if unsafe { clone(CloneFlags::empty())? } == 0 {
let _ = close(read_pipe);
f(Daemon {
write_pipe,
});
// TODO: Replace Infallible with the never type once it is stabilized.
unreachable!();
} else {
let _ = close(write_pipe);
let mut data = [0];
let res = read(read_pipe, &mut data);
let _ = close(read_pipe);
if res? == 1 {
exit(data[0] as usize)?;
unreachable!();
} else {
Err(Error::new(EIO))
}
}
}
pub fn ready(self) -> Result<()> {
let res = write(self.write_pipe, &[0]);
let _ = close(self.write_pipe);
if res? == 1 {
Ok(())
} else {
Err(Error::new(EIO))
}
}
}

View File

@@ -32,18 +32,6 @@ macro_rules! bitflags {
}
}
bitflags! {
pub struct CloneFlags: usize {
const CLONE_VM = 0x100;
const CLONE_FS = 0x200;
const CLONE_FILES = 0x400;
const CLONE_SIGHAND = 0x800;
const CLONE_VFORK = 0x4000;
const CLONE_THREAD = 0x10000;
const CLONE_STACK = 0x1000_0000;
}
}
pub const CLOCK_REALTIME: usize = 1;
pub const CLOCK_MONOTONIC: usize = 4;
@@ -213,8 +201,10 @@ bitflags! {
/// If you don't catch this, the child is started as normal.
const PTRACE_EVENT_CLONE = 0x0000_0000_0000_0100;
const PTRACE_EVENT_MASK = 0x0000_0000_0000_0F00;
/// Sent when current-addrspace is changed, allowing the tracer to reopen the memory file.
const PTRACE_EVENT_ADDRSPACE_SWITCH = 0x0000_0000_0000_0200;
const PTRACE_EVENT_MASK = 0x0000_0000_0000_0F00;
/// Special meaning, depending on the event. Usually, when fired before
/// an action, it will skip performing that action.
@@ -292,13 +282,6 @@ bitflags! {
}
}
// Auxiliery vector types
pub const AT_NULL: usize = 0;
pub const AT_PHDR: usize = 3;
pub const AT_PHENT: usize = 4;
pub const AT_PHNUM: usize = 5;
pub const AT_ENTRY: usize = 9;
bitflags! {
pub struct WaitFlags: usize {
const WNOHANG = 0x01;
@@ -307,6 +290,11 @@ bitflags! {
}
}
pub const ADDRSPACE_OP_MMAP: usize = 0;
pub const ADDRSPACE_OP_MUNMAP: usize = 1;
pub const ADDRSPACE_OP_MPROTECT: usize = 2;
pub const ADDRSPACE_OP_TRANSFER: usize = 3;
/// True if status indicates the child is stopped.
pub fn wifstopped(status: usize) -> bool {
(status & 0xff) == 0x7f

View File

@@ -4,6 +4,7 @@ use core::{ptr, slice};
use crate::Result;
use crate::{PartialAllocStrategy, PhysallocFlags};
use crate::arch::PAGE_SIZE;
/// An RAII guard of a physical memory allocation. Currently all physically allocated memory are
/// page-aligned and take up at least 4k of space (on x86_64).
@@ -13,12 +14,23 @@ pub struct PhysBox {
size: usize
}
const fn round_up(x: usize) -> usize {
(x + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE
}
fn assert_aligned(x: usize) {
assert_eq!(x % PAGE_SIZE, 0);
}
impl PhysBox {
/// Construct a PhysBox from an address and a size.
/// Construct a PhysBox from an address and a size. The address must be page-aligned, and the
/// size must similarly be a multiple of the page size.
///
/// # Safety
/// This function is unsafe because when dropping, Self has to a valid allocation.
pub unsafe fn from_raw_parts(address: usize, size: usize) -> Self {
assert_aligned(address);
assert_aligned(size);
Self {
address,
size,
@@ -42,12 +54,10 @@ impl PhysBox {
pub fn new_with_flags(size: usize, flags: PhysallocFlags) -> Result<Self> {
assert!(!flags.contains(PhysallocFlags::PARTIAL_ALLOC));
assert_aligned(size);
let address = unsafe { crate::physalloc2(size, flags.bits())? };
Ok(Self {
address,
size,
})
Ok(unsafe { Self::from_raw_parts(address, size) })
}
/// "Partially" allocate physical memory, in the sense that the allocation may be smaller than
@@ -57,21 +67,18 @@ impl PhysBox {
/// that first allocation only returns half the size, the driver can do another allocation
/// and then let the device use both buffers.
pub fn new_partial_allocation(size: usize, flags: PhysallocFlags, strategy: Option<PartialAllocStrategy>, mut min: usize) -> Result<Self> {
assert_aligned(size);
debug_assert!(!(flags.contains(PhysallocFlags::PARTIAL_ALLOC) && strategy.is_none()));
let address = unsafe { crate::physalloc3(size, flags.bits() | strategy.map(|s| s as usize).unwrap_or(0), &mut min)? };
Ok(Self {
address,
size: min,
})
let address = unsafe { crate::physalloc3(size, flags.bits() | strategy.map_or(0, |s| s as usize), &mut min)? };
Ok(unsafe { Self::from_raw_parts(address, size) })
}
pub fn new(size: usize) -> Result<Self> {
assert_aligned(size);
let address = unsafe { crate::physalloc(size)? };
Ok(Self {
address,
size,
})
Ok(unsafe { Self::from_raw_parts(address, size) })
}
}
@@ -111,11 +118,11 @@ impl<T> Dma<T> {
}
pub fn new(value: T) -> Result<Self> {
let phys = PhysBox::new(mem::size_of::<T>())?;
let phys = PhysBox::new(round_up(mem::size_of::<T>()))?;
Self::from_physbox(phys, value)
}
pub fn zeroed() -> Result<Dma<MaybeUninit<T>>> {
let phys = PhysBox::new(mem::size_of::<T>())?;
let phys = PhysBox::new(round_up(mem::size_of::<T>()))?;
Self::from_physbox_zeroed(phys)
}
}
@@ -163,7 +170,7 @@ impl<T> Dma<[T]> {
/// * `T` must be properly aligned.
/// * `T` must be valid as zeroed (i.e. no NonNull pointers).
pub unsafe fn zeroed_unsized(count: usize) -> Result<Self> {
let phys = PhysBox::new(mem::size_of::<T>() * count)?;
let phys = PhysBox::new(round_up(mem::size_of::<T>() * count))?;
Ok(Self::from_physbox_zeroed_unsized(phys, count)?.assume_init())
}
}
@@ -195,6 +202,6 @@ impl<T: ?Sized> DerefMut for Dma<T> {
impl<T: ?Sized> Drop for Dma<T> {
fn drop(&mut self) {
unsafe { ptr::drop_in_place(self.virt) }
let _ = unsafe { crate::physunmap(self.virt as *mut u8 as usize) };
let _ = unsafe { crate::funmap(self.virt as *mut u8 as usize, self.phys.size) };
}
}

View File

@@ -5,7 +5,6 @@ extern crate core;
pub use self::arch::*;
pub use self::call::*;
pub use self::daemon::*;
pub use self::data::*;
pub use self::error::*;
pub use self::flag::*;
@@ -43,9 +42,6 @@ pub mod call;
/// Complex structures that are used for some system calls
pub mod data;
/// Wrapper to make daemons easier to write
pub mod daemon;
/// All errors that can be generated by a system call
pub mod error;

View File

@@ -26,7 +26,6 @@ pub const SYS_FCHMOD: usize = SYS_CLASS_FILE | 94;
pub const SYS_FCHOWN: usize = SYS_CLASS_FILE | 207;
pub const SYS_FCNTL: usize = SYS_CLASS_FILE | 55;
pub const SYS_FEVENT: usize = SYS_CLASS_FILE | 927;
pub const SYS_FEXEC: usize = SYS_CLASS_FILE | 11;
pub const SYS_FMAP_OLD: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 90;
pub const SYS_FMAP: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 900;
pub const SYS_FUNMAP_OLD: usize = SYS_CLASS_FILE | 91;
@@ -41,7 +40,6 @@ pub const SYS_FUTIMENS: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 320;
pub const SYS_CHDIR: usize = 12;
pub const SYS_CLOCK_GETTIME: usize = 265;
pub const SYS_CLONE: usize = 120;
pub const SYS_EXIT: usize = 1;
pub const SYS_FUTEX: usize = 240;
pub const SYS_GETCWD: usize = 183;