|
@@ -1,5 +1,3 @@
|
|
|
-use core::ptr::NonNull;
|
|
|
|
|
-
|
|
|
|
|
use super::sysinfo::TimeVal;
|
|
use super::sysinfo::TimeVal;
|
|
|
use super::SyscallNoReturn;
|
|
use super::SyscallNoReturn;
|
|
|
use crate::io::Buffer;
|
|
use crate::io::Buffer;
|
|
@@ -9,10 +7,11 @@ use crate::kernel::constants::{
|
|
|
};
|
|
};
|
|
|
use crate::kernel::mem::PageBuffer;
|
|
use crate::kernel::mem::PageBuffer;
|
|
|
use crate::kernel::task::{
|
|
use crate::kernel::task::{
|
|
|
- new_thread_runnable, KernelStack, ProcessBuilder, ProcessList, ProgramLoader, Signal,
|
|
|
|
|
- SignalAction, SignalMask, Thread, ThreadBuilder, UserDescriptor, WaitObject, WaitType,
|
|
|
|
|
|
|
+ do_clone, futex_wait, futex_wake, FutexFlags, FutexOp, ProcessList, ProgramLoader, Signal,
|
|
|
|
|
+ SignalAction, SignalMask, Thread, WaitObject, WaitType,
|
|
|
};
|
|
};
|
|
|
-use crate::kernel::user::dataflow::UserString;
|
|
|
|
|
|
|
+use crate::kernel::task::{parse_futexop, CloneArgs};
|
|
|
|
|
+use crate::kernel::user::dataflow::{CheckedUserPointer, UserString};
|
|
|
use crate::kernel::user::{UserPointer, UserPointerMut};
|
|
use crate::kernel::user::{UserPointer, UserPointerMut};
|
|
|
use crate::kernel::vfs::{self, dentry::Dentry};
|
|
use crate::kernel::vfs::{self, dentry::Dentry};
|
|
|
use crate::path::Path;
|
|
use crate::path::Path;
|
|
@@ -21,12 +20,14 @@ use crate::{kernel::user::dataflow::UserBuffer, prelude::*};
|
|
|
use alloc::borrow::ToOwned;
|
|
use alloc::borrow::ToOwned;
|
|
|
use alloc::ffi::CString;
|
|
use alloc::ffi::CString;
|
|
|
use bitflags::bitflags;
|
|
use bitflags::bitflags;
|
|
|
|
|
+use core::ptr::NonNull;
|
|
|
|
|
+use eonix_hal::processor::UserTLS;
|
|
|
use eonix_hal::traits::trap::RawTrapContext;
|
|
use eonix_hal::traits::trap::RawTrapContext;
|
|
|
use eonix_mm::address::Addr as _;
|
|
use eonix_mm::address::Addr as _;
|
|
|
-use eonix_runtime::scheduler::Scheduler;
|
|
|
|
|
use eonix_runtime::task::Task;
|
|
use eonix_runtime::task::Task;
|
|
|
use eonix_sync::AsProof as _;
|
|
use eonix_sync::AsProof as _;
|
|
|
use posix_types::constants::{P_ALL, P_PID};
|
|
use posix_types::constants::{P_ALL, P_PID};
|
|
|
|
|
+use posix_types::ctypes::PtrT;
|
|
|
use posix_types::signal::{SigAction, SigInfo};
|
|
use posix_types::signal::{SigAction, SigInfo};
|
|
|
use posix_types::syscall_no::*;
|
|
use posix_types::syscall_no::*;
|
|
|
|
|
|
|
@@ -113,16 +114,16 @@ fn mount(source: *const u8, target: *const u8, fstype: *const u8, flags: usize)
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-fn get_strings(mut ptr_strings: UserPointer<'_, u32>) -> KResult<Vec<CString>> {
|
|
|
|
|
|
|
+fn get_strings(mut ptr_strings: UserPointer<'_, PtrT>) -> KResult<Vec<CString>> {
|
|
|
let mut strings = Vec::new();
|
|
let mut strings = Vec::new();
|
|
|
|
|
|
|
|
loop {
|
|
loop {
|
|
|
- let addr = ptr_strings.read()?;
|
|
|
|
|
- if addr == 0 {
|
|
|
|
|
|
|
+ let ptr = ptr_strings.read()?;
|
|
|
|
|
+ if ptr.is_null() {
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- let user_string = UserString::new(addr as *const u8)?;
|
|
|
|
|
|
|
+ let user_string = UserString::new(ptr.addr() as *const u8)?;
|
|
|
strings.push(user_string.as_cstr().to_owned());
|
|
strings.push(user_string.as_cstr().to_owned());
|
|
|
ptr_strings = ptr_strings.offset(1)?;
|
|
ptr_strings = ptr_strings.offset(1)?;
|
|
|
}
|
|
}
|
|
@@ -131,7 +132,7 @@ fn get_strings(mut ptr_strings: UserPointer<'_, u32>) -> KResult<Vec<CString>> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_EXECVE)]
|
|
#[eonix_macros::define_syscall(SYS_EXECVE)]
|
|
|
-fn execve(exec: *const u8, argv: *const u32, envp: *const u32) -> KResult<()> {
|
|
|
|
|
|
|
+fn execve(exec: *const u8, argv: *const PtrT, envp: *const PtrT) -> KResult<()> {
|
|
|
let exec = UserString::new(exec)?;
|
|
let exec = UserString::new(exec)?;
|
|
|
let argv = get_strings(UserPointer::new(argv)?)?;
|
|
let argv = get_strings(UserPointer::new(argv)?)?;
|
|
|
let envp = get_strings(UserPointer::new(envp)?)?;
|
|
let envp = get_strings(UserPointer::new(envp)?)?;
|
|
@@ -172,7 +173,7 @@ fn execve(exec: *const u8, argv: *const u32, envp: *const u32) -> KResult<()> {
|
|
|
fn exit(status: u32) -> SyscallNoReturn {
|
|
fn exit(status: u32) -> SyscallNoReturn {
|
|
|
unsafe {
|
|
unsafe {
|
|
|
let mut procs = Task::block_on(ProcessList::get().write());
|
|
let mut procs = Task::block_on(ProcessList::get().write());
|
|
|
- procs.do_kill_process(&thread.process, WaitType::Exited(status));
|
|
|
|
|
|
|
+ Task::block_on(procs.do_exit(&thread, WaitType::Exited(status), false));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
SyscallNoReturn
|
|
SyscallNoReturn
|
|
@@ -180,7 +181,12 @@ fn exit(status: u32) -> SyscallNoReturn {
|
|
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_EXIT_GROUP)]
|
|
#[eonix_macros::define_syscall(SYS_EXIT_GROUP)]
|
|
|
fn exit_group(status: u32) -> SyscallNoReturn {
|
|
fn exit_group(status: u32) -> SyscallNoReturn {
|
|
|
- sys_exit(thread, status)
|
|
|
|
|
|
|
+ unsafe {
|
|
|
|
|
+ let mut procs = Task::block_on(ProcessList::get().write());
|
|
|
|
|
+ Task::block_on(procs.do_exit(&thread, WaitType::Exited(status), true));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ SyscallNoReturn
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
enum WaitInfo {
|
|
enum WaitInfo {
|
|
@@ -376,8 +382,7 @@ fn geteuid32() -> KResult<u32> {
|
|
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_GETEUID)]
|
|
#[eonix_macros::define_syscall(SYS_GETEUID)]
|
|
|
fn geteuid() -> KResult<u32> {
|
|
fn geteuid() -> KResult<u32> {
|
|
|
- // All users are root for now.
|
|
|
|
|
- Ok(0)
|
|
|
|
|
|
|
+ do_geteuid(thread)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_GETGID)]
|
|
#[eonix_macros::define_syscall(SYS_GETGID)]
|
|
@@ -397,14 +402,44 @@ fn gettid() -> KResult<u32> {
|
|
|
Ok(thread.tid)
|
|
Ok(thread.tid)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+pub fn parse_user_tls(arch_tls: usize) -> KResult<UserTLS> {
|
|
|
|
|
+ #[cfg(target_arch = "x86_64")]
|
|
|
|
|
+ {
|
|
|
|
|
+ let desc = arch_tls as *mut posix_types::x86_64::UserDescriptor;
|
|
|
|
|
+ let desc_pointer = UserPointerMut::new(desc)?;
|
|
|
|
|
+ let mut desc = desc_pointer.read()?;
|
|
|
|
|
+
|
|
|
|
|
+ // Clear the TLS area if it is not present.
|
|
|
|
|
+ if desc.flags.is_read_exec_only() && !desc.flags.is_present() {
|
|
|
|
|
+ if desc.limit != 0 && desc.base != 0 {
|
|
|
|
|
+ let len = if desc.flags.is_limit_in_pages() {
|
|
|
|
|
+ (desc.limit as usize) << 12
|
|
|
|
|
+ } else {
|
|
|
|
|
+ desc.limit as usize
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ CheckedUserPointer::new(desc.base as _, len)?.zero()?;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let (new_tls, entry) =
|
|
|
|
|
+ UserTLS::new32(desc.base, desc.limit, desc.flags.is_limit_in_pages());
|
|
|
|
|
+ desc.entry = entry;
|
|
|
|
|
+ desc_pointer.write(desc)?;
|
|
|
|
|
+
|
|
|
|
|
+ Ok(new_tls)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(target_arch = "riscv64")]
|
|
|
|
|
+ {
|
|
|
|
|
+ Ok(UserTLS::new(arch_tls as u64))
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_SET_THREAD_AREA)]
|
|
#[eonix_macros::define_syscall(SYS_SET_THREAD_AREA)]
|
|
|
-fn set_thread_area(desc: *mut UserDescriptor) -> KResult<()> {
|
|
|
|
|
- let desc_pointer = UserPointerMut::new(desc)?;
|
|
|
|
|
- let mut desc = desc_pointer.read()?;
|
|
|
|
|
-
|
|
|
|
|
- thread.set_thread_area(&mut desc)?;
|
|
|
|
|
- desc_pointer.write(desc)?;
|
|
|
|
|
|
|
+fn set_thread_area(arch_tls: usize) -> KResult<()> {
|
|
|
|
|
+ thread.set_user_tls(parse_user_tls(arch_tls)?)?;
|
|
|
|
|
|
|
|
// SAFETY: Preemption is disabled on calling `load_thread_area32()`.
|
|
// SAFETY: Preemption is disabled on calling `load_thread_area32()`.
|
|
|
unsafe {
|
|
unsafe {
|
|
@@ -417,9 +452,8 @@ fn set_thread_area(desc: *mut UserDescriptor) -> KResult<()> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_SET_TID_ADDRESS)]
|
|
#[eonix_macros::define_syscall(SYS_SET_TID_ADDRESS)]
|
|
|
-fn set_tid_address(tidptr: *mut u32) -> KResult<u32> {
|
|
|
|
|
- // TODO!!!: Implement this. We don't use it for now.
|
|
|
|
|
- let _tidptr = UserPointerMut::new(tidptr)?;
|
|
|
|
|
|
|
+fn set_tid_address(tidptr: usize) -> KResult<u32> {
|
|
|
|
|
+ thread.clear_child_tid(Some(tidptr));
|
|
|
Ok(thread.tid)
|
|
Ok(thread.tid)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -639,31 +673,65 @@ fn chmod(pathname: *const u8, mode: u32) -> KResult<()> {
|
|
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_VFORK)]
|
|
#[eonix_macros::define_syscall(SYS_VFORK)]
|
|
|
-fn vfork() -> u32 {
|
|
|
|
|
- sys_fork(thread)
|
|
|
|
|
|
|
+fn vfork() -> KResult<u32> {
|
|
|
|
|
+ let clone_args = CloneArgs::for_vfork();
|
|
|
|
|
+
|
|
|
|
|
+ do_clone(thread, clone_args)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_FORK)]
|
|
#[eonix_macros::define_syscall(SYS_FORK)]
|
|
|
-fn fork() -> u32 {
|
|
|
|
|
- let mut procs = Task::block_on(ProcessList::get().write());
|
|
|
|
|
|
|
+fn fork() -> KResult<u32> {
|
|
|
|
|
+ let clone_args = CloneArgs::for_fork();
|
|
|
|
|
+
|
|
|
|
|
+ do_clone(thread, clone_args)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#[eonix_macros::define_syscall(SYS_CLONE)]
|
|
|
|
|
+fn clone(
|
|
|
|
|
+ clone_flags: usize,
|
|
|
|
|
+ new_sp: usize,
|
|
|
|
|
+ parent_tidptr: usize,
|
|
|
|
|
+ tls: usize,
|
|
|
|
|
+ child_tidptr: usize,
|
|
|
|
|
+) -> KResult<u32> {
|
|
|
|
|
+ let clone_args = CloneArgs::for_clone(clone_flags, new_sp, child_tidptr, parent_tidptr, tls)?;
|
|
|
|
|
|
|
|
- let current_process = thread.process.clone();
|
|
|
|
|
- let current_pgroup = current_process.pgroup(procs.prove()).clone();
|
|
|
|
|
- let current_session = current_process.session(procs.prove()).clone();
|
|
|
|
|
|
|
+ do_clone(thread, clone_args)
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- let thread_builder = ThreadBuilder::new().fork_from(&thread);
|
|
|
|
|
- let (new_thread, new_process) = ProcessBuilder::new()
|
|
|
|
|
- .mm_list(Task::block_on(current_process.mm_list.new_cloned()))
|
|
|
|
|
- .parent(current_process)
|
|
|
|
|
- .pgroup(current_pgroup)
|
|
|
|
|
- .session(current_session)
|
|
|
|
|
- .thread_builder(thread_builder)
|
|
|
|
|
- .build(&mut procs);
|
|
|
|
|
|
|
+#[eonix_macros::define_syscall(SYS_FUTEX)]
|
|
|
|
|
+fn futex(
|
|
|
|
|
+ uaddr: usize,
|
|
|
|
|
+ op: u32,
|
|
|
|
|
+ val: u32,
|
|
|
|
|
+ _time_out: usize,
|
|
|
|
|
+ _uaddr2: usize,
|
|
|
|
|
+ _val3: u32,
|
|
|
|
|
+) -> KResult<usize> {
|
|
|
|
|
+ let (futex_op, futex_flag) = parse_futexop(op)?;
|
|
|
|
|
|
|
|
- Scheduler::get().spawn::<KernelStack, _>(new_thread_runnable(new_thread));
|
|
|
|
|
|
|
+ let pid = if futex_flag.contains(FutexFlags::FUTEX_PRIVATE) {
|
|
|
|
|
+ Some(thread.process.pid)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ None
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- new_process.pid
|
|
|
|
|
|
|
+ match futex_op {
|
|
|
|
|
+ FutexOp::FUTEX_WAIT => {
|
|
|
|
|
+ Task::block_on(futex_wait(uaddr, pid, val as u32, None))?;
|
|
|
|
|
+ return Ok(0);
|
|
|
|
|
+ }
|
|
|
|
|
+ FutexOp::FUTEX_WAKE => {
|
|
|
|
|
+ return Task::block_on(futex_wake(uaddr, pid, val as u32));
|
|
|
|
|
+ }
|
|
|
|
|
+ FutexOp::FUTEX_REQUEUE => {
|
|
|
|
|
+ todo!()
|
|
|
|
|
+ }
|
|
|
|
|
+ _ => {
|
|
|
|
|
+ todo!()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
#[cfg(target_arch = "x86_64")]
|
|
@@ -680,7 +748,7 @@ fn sigreturn() -> KResult<SyscallNoReturn> {
|
|
|
"`sigreturn` failed in thread {} with error {err}!",
|
|
"`sigreturn` failed in thread {} with error {err}!",
|
|
|
thread.tid
|
|
thread.tid
|
|
|
);
|
|
);
|
|
|
- Task::block_on(thread.process.force_kill(Signal::SIGSEGV));
|
|
|
|
|
|
|
+ Task::block_on(thread.force_kill(Signal::SIGSEGV));
|
|
|
})?;
|
|
})?;
|
|
|
|
|
|
|
|
Ok(SyscallNoReturn)
|
|
Ok(SyscallNoReturn)
|