Almost forking, UB
This commit is contained in:
@@ -16,6 +16,6 @@
|
||||
|
||||
"os": "none",
|
||||
"pre-link-args": {
|
||||
"ld.lld": [ "-Tetc/aarch64-osdev5.ld" ]
|
||||
"ld.lld": [ "-Tetc/x86_64-osdev5.ld" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
ENTRY(_start);
|
||||
|
||||
PHDRS {
|
||||
text PT_LOAD ;
|
||||
rodata PT_LOAD ;
|
||||
data PT_LOAD ;
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
. = 0x400000;
|
||||
|
||||
.text : {
|
||||
*(.text._start)
|
||||
*(.text*)
|
||||
*(.eh_frame*)
|
||||
} :text
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
} :rodata
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
.data : {
|
||||
*(.data*)
|
||||
} :data
|
||||
|
||||
.bss : {
|
||||
*(COMMON)
|
||||
*(.bss*)
|
||||
} :data
|
||||
}
|
||||
@@ -7,7 +7,7 @@ use crate::config::{ConfigKey, CONFIG};
|
||||
use crate::debug;
|
||||
use crate::dev::{display::FramebufferInfo, pseudo, Device};
|
||||
use crate::font;
|
||||
use crate::fs::{devfs, sysfs};
|
||||
use crate::fs::{devfs::{self, CharDeviceType}, sysfs};
|
||||
use crate::mem::{
|
||||
self, heap,
|
||||
phys::{self, MemoryRegion, PageUsage, ReservedRegion},
|
||||
@@ -100,6 +100,7 @@ extern "C" fn __x86_64_bsp_main(mb_checksum: u32, mb_info_ptr: u32) -> ! {
|
||||
devfs::init();
|
||||
sysfs::init();
|
||||
|
||||
devfs::add_char_device(&x86_64::COM1, CharDeviceType::TtySerial).unwrap();
|
||||
devfs::add_named_char_device(&pseudo::ZERO, "zero").unwrap();
|
||||
devfs::add_named_char_device(&pseudo::RANDOM, "random").unwrap();
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ pub(self) mod gdt;
|
||||
pub(self) mod idt;
|
||||
pub(self) mod exception;
|
||||
|
||||
pub use syscall::SyscallFrame as ForkFrame;
|
||||
|
||||
/// Masks IRQs and returns previous IRQ mask state
|
||||
///
|
||||
/// # Safety
|
||||
|
||||
@@ -1,4 +1,60 @@
|
||||
.section .text
|
||||
.global __x86_64_syscall_entry
|
||||
__x86_64_syscall_entry:
|
||||
jmp .
|
||||
// Syscalls only happen from user space, so
|
||||
// relying on TSS.RSP0 is safe here I guess
|
||||
mov %rsp, scratch(%rip)
|
||||
mov (4 + TSS)(%rip), %rsp
|
||||
|
||||
// Now on kernel stack
|
||||
// Push the whole state
|
||||
push %rcx // saved %rip
|
||||
push %r11 // saved %rflags
|
||||
mov scratch(%rip), %r11
|
||||
push %r11 // saved %rsp
|
||||
|
||||
push %r12
|
||||
push %r13
|
||||
push %r14
|
||||
push %r15
|
||||
push %rbp
|
||||
push %rbx
|
||||
|
||||
push %rax
|
||||
|
||||
push %r9
|
||||
push %r8
|
||||
push %r10
|
||||
push %rdx
|
||||
push %rsi
|
||||
push %rdi
|
||||
|
||||
mov %rsp, %rdi
|
||||
call __x86_64_syscall
|
||||
|
||||
pop %rdi
|
||||
pop %rsi
|
||||
pop %rdx
|
||||
pop %r10
|
||||
pop %r8
|
||||
pop %r9
|
||||
|
||||
pop %rax
|
||||
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
pop %r15
|
||||
pop %r14
|
||||
pop %r13
|
||||
pop %r12
|
||||
|
||||
pop %rdi
|
||||
pop %r11
|
||||
pop %rcx
|
||||
mov %rdi, %rsp
|
||||
|
||||
sysretq
|
||||
|
||||
.section .bss
|
||||
scratch:
|
||||
.skip 8
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
use crate::arch::x86_64::reg::{MSR_IA32_EFER, MSR_IA32_LSTAR, MSR_IA32_SFMASK, MSR_IA32_STAR};
|
||||
use core::arch::global_asm;
|
||||
use tock_registers::interfaces::{ReadWriteable, Writeable};
|
||||
use libsys::abi::SystemCall;
|
||||
use crate::syscall;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SyscallFrame {
|
||||
x: [usize; 13],
|
||||
|
||||
saved_rsp: usize,
|
||||
saved_rflags: usize,
|
||||
saved_rip: usize,
|
||||
}
|
||||
|
||||
pub(super) fn init() {
|
||||
extern "C" {
|
||||
@@ -14,4 +25,29 @@ pub(super) fn init() {
|
||||
MSR_IA32_EFER.modify(MSR_IA32_EFER::SCE::SET);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn __x86_64_syscall(frame: &mut SyscallFrame) {
|
||||
let num = SystemCall::from_repr(frame.x[6]);
|
||||
if num.is_none() {
|
||||
todo!();
|
||||
}
|
||||
let num = num.unwrap();
|
||||
if num == SystemCall::Fork {
|
||||
match unsafe { syscall::sys_fork(frame) } {
|
||||
Ok(pid) => frame.x[6] = u32::from(pid) as usize,
|
||||
Err(err) => {
|
||||
frame.x[6] = err.to_negative_isize() as usize;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
match syscall::syscall(num, &frame.x[..6]) {
|
||||
Ok(val) => frame.x[6] = val,
|
||||
Err(err) => {
|
||||
frame.x[6] = err.to_negative_isize() as usize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global_asm!(include_str!("syscall.S"), options(att_syntax));
|
||||
|
||||
@@ -206,6 +206,58 @@ impl AddressSpace for Space {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs a copy of the address space, cloning data owned by it
|
||||
fn fork(&mut self) -> Result<&'static mut Self, Errno> {
|
||||
let res = Self::alloc_empty()?;
|
||||
let pdpt0 = self.0.next_level_table(0).unwrap();
|
||||
|
||||
for pdpti in 0..512 {
|
||||
if let Some(pd) = pdpt0.next_level_table(pdpti) {
|
||||
for pdi in 0..512 {
|
||||
if let Some(pt) = pd.next_level_table(pdi) {
|
||||
for pti in 0..512 {
|
||||
let entry = pt[pti];
|
||||
|
||||
if !entry.is_present() {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert!(entry.is_table());
|
||||
|
||||
todo!();
|
||||
// let src_phys = unsafe { entry.address_unchecked() };
|
||||
// let virt_addr = (l0i << 30) | (l1i << 21) | (l2i << 12);
|
||||
// let dst_phys = unsafe { phys::fork_page(src_phys)? };
|
||||
|
||||
// let mut flags = unsafe { entry.fork_flags() };
|
||||
// if dst_phys != src_phys {
|
||||
// todo!();
|
||||
// // res.map(virt_addr, dst_phys, flags)?;
|
||||
// } else {
|
||||
// let writable = flags & MapAttributes::AP_BOTH_READONLY
|
||||
// == MapAttributes::AP_BOTH_READWRITE;
|
||||
|
||||
// if writable {
|
||||
// flags |=
|
||||
// MapAttributes::AP_BOTH_READONLY | MapAttributes::EX_COW;
|
||||
// l2_table[l2i].set_cow();
|
||||
|
||||
// unsafe {
|
||||
// asm!("tlbi vaae1, {}", in(reg) virt_addr);
|
||||
// }
|
||||
// }
|
||||
|
||||
// res.map(virt_addr, dst_phys, flags)?;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Index<usize> for Table {
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
use crate::dev::{Device, serial::SerialDevice};
|
||||
use crate::arch::x86_64::PortIo;
|
||||
use libsys::error::Errno;
|
||||
use crate::dev::{
|
||||
tty::{CharRing, TtyDevice},
|
||||
irq::{IntController, IntSource},
|
||||
serial::SerialDevice,
|
||||
Device,
|
||||
};
|
||||
|
||||
#[derive(TtyCharDevice)]
|
||||
pub(super) struct Uart {
|
||||
dr: PortIo<u8>
|
||||
dr: PortIo<u8>,
|
||||
ring: CharRing<16>
|
||||
}
|
||||
|
||||
impl Device for Uart {
|
||||
@@ -16,6 +23,12 @@ impl Device for Uart {
|
||||
}
|
||||
}
|
||||
|
||||
impl TtyDevice<16> for Uart {
|
||||
fn ring(&self) -> &CharRing<16> {
|
||||
&self.ring
|
||||
}
|
||||
}
|
||||
|
||||
impl SerialDevice for Uart {
|
||||
fn send(&self, byte: u8) -> Result<(), Errno> {
|
||||
self.dr.write(byte);
|
||||
@@ -30,7 +43,8 @@ impl SerialDevice for Uart {
|
||||
impl Uart {
|
||||
pub const unsafe fn new(base: u16) -> Self {
|
||||
Self {
|
||||
dr: PortIo::new(base)
|
||||
dr: PortIo::new(base),
|
||||
ring: CharRing::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ pub mod display;
|
||||
pub mod serial;
|
||||
pub mod timer;
|
||||
pub mod pseudo;
|
||||
// pub mod tty;
|
||||
pub mod tty;
|
||||
|
||||
/// Generic device trait
|
||||
pub trait Device {
|
||||
|
||||
@@ -126,7 +126,8 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
// TODO send to pgid
|
||||
let proc = Process::get(pgid);
|
||||
if let Some(proc) = proc {
|
||||
proc.set_signal(Signal::Interrupt);
|
||||
// TODO
|
||||
// proc.set_signal(Signal::Interrupt);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
+18
-18
@@ -36,26 +36,26 @@ pub extern "C" fn init_fn(_arg: usize) -> ! {
|
||||
|
||||
proc.io.lock().set_ioctx(ioctx);
|
||||
|
||||
// // Open stdin/stdout/stderr
|
||||
// {
|
||||
// let devfs_root = devfs::root();
|
||||
// let tty_node = if console.is_empty() {
|
||||
// devfs_root.lookup("ttyS0")
|
||||
// } else {
|
||||
// devfs_root.lookup(console)
|
||||
// }
|
||||
// .expect("Failed to open stdout for init process");
|
||||
// Open stdin/stdout/stderr
|
||||
{
|
||||
let devfs_root = devfs::root();
|
||||
let tty_node = if console.is_empty() {
|
||||
devfs_root.lookup("ttyS0")
|
||||
} else {
|
||||
devfs_root.lookup(console)
|
||||
}
|
||||
.expect("Failed to open stdout for init process");
|
||||
|
||||
// let mut io = proc.io.lock();
|
||||
// let stdin = tty_node.open(OpenFlags::O_RDONLY).unwrap();
|
||||
// let stdout = tty_node.open(OpenFlags::O_WRONLY).unwrap();
|
||||
// let stderr = stdout.clone();
|
||||
let mut io = proc.io.lock();
|
||||
let stdin = tty_node.open(OpenFlags::O_RDONLY).unwrap();
|
||||
let stdout = tty_node.open(OpenFlags::O_WRONLY).unwrap();
|
||||
let stderr = stdout.clone();
|
||||
|
||||
// io.set_file(FileDescriptor::STDIN, stdin).unwrap();
|
||||
// io.set_file(FileDescriptor::STDOUT, stdout).unwrap();
|
||||
// io.set_file(FileDescriptor::STDERR, stderr).unwrap();
|
||||
// io.set_ctty(tty_node);
|
||||
// }
|
||||
io.set_file(FileDescriptor::STDIN, stdin).unwrap();
|
||||
io.set_file(FileDescriptor::STDOUT, stdout).unwrap();
|
||||
io.set_file(FileDescriptor::STDERR, stderr).unwrap();
|
||||
io.set_ctty(tty_node);
|
||||
}
|
||||
|
||||
drop(cfg);
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ pub trait AddressSpace {
|
||||
type Entry: Entry;
|
||||
|
||||
fn alloc_empty() -> Result<&'static mut Self, Errno>;
|
||||
fn fork(&mut self) -> Result<&'static mut Self, Errno>;
|
||||
fn release(space: &mut Self);
|
||||
fn address_phys(&mut self) -> usize;
|
||||
fn read_last_level_entry(&mut self, virt: usize) -> Result<Self::Entry, Errno>;
|
||||
@@ -48,12 +49,40 @@ pub trait AddressSpace {
|
||||
map_intermediate: bool,
|
||||
) -> Result<(), Errno>;
|
||||
|
||||
#[inline(always)]
|
||||
fn map(&mut self, virt: usize, phys: usize, attrs: MapAttributes) -> Result<(), Errno> {
|
||||
let entry = Entry::from_parts(phys, attrs);
|
||||
self.write_last_level_entry(virt, entry, true).map(|_| ())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn translate(&mut self, virt: usize) -> Result<usize, Errno> {
|
||||
self.read_last_level_entry(virt).map(Entry::target)
|
||||
}
|
||||
|
||||
/// Allocates a contiguous region from the address space and maps
|
||||
/// physical pages to it
|
||||
fn allocate(
|
||||
&mut self,
|
||||
start: usize,
|
||||
end: usize,
|
||||
len: usize,
|
||||
flags: MapAttributes,
|
||||
usage: PageUsage,
|
||||
) -> Result<usize, Errno> {
|
||||
'l0: for page in (start..end).step_by(0x1000) {
|
||||
for i in 0..len {
|
||||
if self.translate(page + i * 0x1000).is_ok() {
|
||||
continue 'l0;
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..len {
|
||||
let phys = phys::alloc_page(usage).unwrap();
|
||||
self.map(page + i * 0x1000, phys, flags).unwrap();
|
||||
}
|
||||
return Ok(page);
|
||||
}
|
||||
Err(Errno::OutOfMemory)
|
||||
}
|
||||
}
|
||||
|
||||
+37
-34
@@ -1,5 +1,5 @@
|
||||
//! Process data and control
|
||||
// use crate::arch::aarch64::exception::ExceptionFrame;
|
||||
use crate::arch::platform::ForkFrame;
|
||||
use crate::mem::{
|
||||
self,
|
||||
phys::{self, PageUsage},
|
||||
@@ -55,7 +55,7 @@ pub struct Process {
|
||||
|
||||
impl Process {
|
||||
const USTACK_VIRT_TOP: usize = 0x100000000;
|
||||
const USTACK_PAGES: usize = 4;
|
||||
const USTACK_PAGES: usize = 8;
|
||||
|
||||
/// Returns the process ID
|
||||
#[inline]
|
||||
@@ -229,45 +229,48 @@ impl Process {
|
||||
// Ok(tid)
|
||||
// }
|
||||
|
||||
// /// Creates a "fork" of the process, cloning its address space and
|
||||
// /// resources
|
||||
// pub fn fork(&self, frame: &mut ExceptionFrame) -> Result<Pid, Errno> {
|
||||
// let src_io = self.io.lock();
|
||||
// let mut src_inner = self.inner.lock();
|
||||
/// Creates a "fork" of the process, cloning its address space and
|
||||
/// resources
|
||||
pub fn fork(&self, frame: &mut ForkFrame) -> Result<Pid, Errno> {
|
||||
todo!();
|
||||
let src_io = self.io.lock();
|
||||
let mut src_inner = self.inner.lock();
|
||||
|
||||
// let dst_id = new_user_pid();
|
||||
// let dst_space = src_inner.space.as_mut().unwrap().fork()?;
|
||||
let dst_id = new_user_pid();
|
||||
let dst_space = src_inner.space.as_mut().unwrap().fork()?;
|
||||
|
||||
// let dst_space_phys = (dst_space as *mut _ as usize) - mem::KERNEL_OFFSET;
|
||||
// let dst_ttbr0 = dst_space_phys | ((dst_id.asid() as usize) << 48);
|
||||
todo!()
|
||||
|
||||
// let mut threads = Vec::new();
|
||||
// let tid = Thread::fork(Some(dst_id), frame, dst_ttbr0)?.id();
|
||||
// threads.push(tid);
|
||||
// let dst_space_phys = (dst_space as *mut _ as usize) - mem::KERNEL_OFFSET;
|
||||
// let dst_ttbr0 = dst_space_phys | ((dst_id.asid() as usize) << 48);
|
||||
|
||||
// let dst = Rc::new(Self {
|
||||
// exit_wait: Wait::new("process_exit"),
|
||||
// io: IrqSafeSpinLock::new(src_io.fork()?),
|
||||
// signal_state: AtomicU32::new(0),
|
||||
// inner: IrqSafeSpinLock::new(ProcessInner {
|
||||
// threads,
|
||||
// exit: None,
|
||||
// space: Some(dst_space),
|
||||
// state: ProcessState::Active,
|
||||
// id: dst_id,
|
||||
// pgid: src_inner.pgid,
|
||||
// ppid: Some(src_inner.id),
|
||||
// sid: src_inner.sid,
|
||||
// }),
|
||||
// });
|
||||
// let mut threads = Vec::new();
|
||||
// let tid = Thread::fork(Some(dst_id), frame, dst_ttbr0)?.id();
|
||||
// threads.push(tid);
|
||||
|
||||
// debugln!("Process {:?} forked into {:?}", src_inner.id, dst_id);
|
||||
// assert!(PROCESSES.lock().insert(dst_id, dst).is_none());
|
||||
// let dst = Rc::new(Self {
|
||||
// exit_wait: Wait::new("process_exit"),
|
||||
// io: IrqSafeSpinLock::new(src_io.fork()?),
|
||||
// signal_state: AtomicU32::new(0),
|
||||
// inner: IrqSafeSpinLock::new(ProcessInner {
|
||||
// threads,
|
||||
// exit: None,
|
||||
// space: Some(dst_space),
|
||||
// state: ProcessState::Active,
|
||||
// id: dst_id,
|
||||
// pgid: src_inner.pgid,
|
||||
// ppid: Some(src_inner.id),
|
||||
// sid: src_inner.sid,
|
||||
// }),
|
||||
// });
|
||||
|
||||
// SCHED.enqueue(tid);
|
||||
// debugln!("Process {:?} forked into {:?}", src_inner.id, dst_id);
|
||||
// assert!(PROCESSES.lock().insert(dst_id, dst).is_none());
|
||||
|
||||
// Ok(dst_id)
|
||||
// }
|
||||
// SCHED.enqueue(tid);
|
||||
|
||||
// Ok(dst_id)
|
||||
}
|
||||
|
||||
/// Terminates a process.
|
||||
pub fn exit(self: ProcessRef, status: ExitCode) {
|
||||
|
||||
+28
-16
@@ -12,28 +12,39 @@ macro_rules! invalid_memory {
|
||||
warnln!($($args)+);
|
||||
#[cfg(feature = "aggressive_syscall")]
|
||||
{
|
||||
use libsys::signal::Signal;
|
||||
use crate::proc::Thread;
|
||||
todo!()
|
||||
// use libsys::signal::Signal;
|
||||
// use crate::proc::Thread;
|
||||
|
||||
let thread = Thread::current();
|
||||
let proc = thread.owner().unwrap();
|
||||
proc.enter_fault_signal(thread, Signal::SegmentationFault);
|
||||
// let thread = Thread::current();
|
||||
// let proc = thread.owner().unwrap();
|
||||
// proc.enter_fault_signal(thread, Signal::SegmentationFault);
|
||||
}
|
||||
return Err(Errno::InvalidArgument);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn is_el0_accessible(virt: usize, write: bool) -> bool {
|
||||
let mut res: usize;
|
||||
unsafe {
|
||||
if write {
|
||||
asm!("at s1e0w, {}; mrs {}, par_el1", in(reg) virt, out(reg) res);
|
||||
} else {
|
||||
asm!("at s1e0r, {}; mrs {}, par_el1", in(reg) virt, out(reg) res);
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "aarch64")] {
|
||||
#[inline(always)]
|
||||
fn is_el0_accessible(virt: usize, write: bool) -> bool {
|
||||
let mut res: usize;
|
||||
unsafe {
|
||||
if write {
|
||||
asm!("at s1e0w, {}; mrs {}, par_el1", in(reg) virt, out(reg) res);
|
||||
} else {
|
||||
asm!("at s1e0r, {}; mrs {}, par_el1", in(reg) virt, out(reg) res);
|
||||
}
|
||||
}
|
||||
res & 1 == 0
|
||||
}
|
||||
} else {
|
||||
#[inline(always)]
|
||||
fn is_el0_accessible(virt: usize, write: bool) -> bool {
|
||||
// TODO implement this
|
||||
true
|
||||
}
|
||||
}
|
||||
res & 1 == 0
|
||||
}
|
||||
|
||||
/// Checks given argument and interprets it as a `T` reference
|
||||
@@ -129,9 +140,10 @@ pub fn validate_ptr(base: usize, len: usize, write: bool) -> Result<(), Errno> {
|
||||
// It's possible a CoW page hasn't yet been cloned when trying
|
||||
// a write access
|
||||
let res = if write {
|
||||
todo!();
|
||||
process.manipulate_space(|space| {
|
||||
space.try_cow_copy(i * mem::PAGE_SIZE)?;
|
||||
Process::invalidate_asid(asid);
|
||||
// space.try_cow_copy(i * mem::PAGE_SIZE)?;
|
||||
// Process::invalidate_asid(asid);
|
||||
Ok(())
|
||||
})
|
||||
} else {
|
||||
|
||||
+416
-413
@@ -1,10 +1,14 @@
|
||||
//! System call implementation
|
||||
|
||||
// use crate::arch::{machine, platform::exception::ExceptionFrame};
|
||||
// use crate::debug::Level;
|
||||
use crate::arch::platform::ForkFrame;
|
||||
use crate::debug::Level;
|
||||
// use crate::dev::timer::TimestampSource;
|
||||
// use crate::fs::create_filesystem;
|
||||
// use crate::mem::{phys::PageUsage, virt::MapAttributes};
|
||||
use crate::fs::create_filesystem;
|
||||
use crate::mem::{
|
||||
phys::PageUsage,
|
||||
virt::table::{AddressSpace, MapAttributes},
|
||||
};
|
||||
use crate::proc::{self, elf, wait, Process, ProcessIo, Thread};
|
||||
// use core::mem::size_of;
|
||||
use core::ops::DerefMut;
|
||||
@@ -24,18 +28,18 @@ use libsys::{
|
||||
};
|
||||
use vfs::VnodeRef;
|
||||
|
||||
// pub mod arg;
|
||||
pub mod arg;
|
||||
|
||||
// /// Creates a "fork" process from current one using its register frame.
|
||||
// /// See [Process::fork()].
|
||||
// ///
|
||||
// /// # Safety
|
||||
// ///
|
||||
// /// Unsafe: accepts and clones process states. Only legal to call
|
||||
// /// from exception handlers.
|
||||
// pub unsafe fn sys_fork(regs: &mut ExceptionFrame) -> Result<Pid, Errno> {
|
||||
// Process::current().fork(regs)
|
||||
// }
|
||||
/// Creates a "fork" process from current one using its register frame.
|
||||
/// See [Process::fork()].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: accepts and clones process states. Only legal to call
|
||||
/// from exception handlers.
|
||||
pub unsafe fn sys_fork(regs: &mut ForkFrame) -> Result<Pid, Errno> {
|
||||
Process::current().fork(regs)
|
||||
}
|
||||
|
||||
fn find_at_node<T: DerefMut<Target = ProcessIo>>(
|
||||
io: &mut T,
|
||||
@@ -57,407 +61,406 @@ fn find_at_node<T: DerefMut<Target = ProcessIo>>(
|
||||
}
|
||||
|
||||
fn _syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
loop {}
|
||||
// match num {
|
||||
// // I/O
|
||||
// SystemCall::Read => {
|
||||
// let proc = Process::current();
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
// let mut io = proc.io.lock();
|
||||
// let buf = arg::buf_mut(args[1], args[2])?;
|
||||
//
|
||||
// io.file(fd)?.borrow_mut().read(buf)
|
||||
// }
|
||||
// SystemCall::Write => {
|
||||
// let proc = Process::current();
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
// let mut io = proc.io.lock();
|
||||
// let buf = arg::buf_ref(args[1], args[2])?;
|
||||
//
|
||||
// io.file(fd)?.borrow_mut().write(buf)
|
||||
// }
|
||||
// SystemCall::Open => {
|
||||
// let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
// let path = arg::str_ref(args[1], args[2])?;
|
||||
// let mode = FileMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
// let opts = OpenFlags::from_bits(args[4] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// let at = if let Some(fd) = at_fd {
|
||||
// io.file(fd)?.borrow().node()
|
||||
// } else {
|
||||
// None
|
||||
// };
|
||||
//
|
||||
// let file = io.ioctx().open(at, path, mode, opts)?;
|
||||
// Ok(u32::from(io.place_file(file)?) as usize)
|
||||
// }
|
||||
// SystemCall::Close => {
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
//
|
||||
// io.close_file(fd)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::FileStatus => {
|
||||
// let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
// let filename = arg::str_ref(args[1], args[2])?;
|
||||
// let buf = arg::struct_mut::<Stat>(args[3])?;
|
||||
// let flags = args[4] as u32;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
// let stat =
|
||||
// find_at_node(&mut io, at_fd, filename, flags & AT_EMPTY_PATH != 0)?.stat()?;
|
||||
// *buf = stat;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::Ioctl => {
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
// let cmd = IoctlCmd::try_from(args[1] as u32)?;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// let node = io.file(fd)?.borrow().node().ok_or(Errno::InvalidFile)?;
|
||||
// node.ioctl(cmd, args[2], args[3])
|
||||
// }
|
||||
// SystemCall::Select => {
|
||||
// let rfds = arg::option_struct_mut::<FdSet>(args[0])?;
|
||||
// let wfds = arg::option_struct_mut::<FdSet>(args[1])?;
|
||||
// let timeout = if args[2] == 0 {
|
||||
// None
|
||||
// } else {
|
||||
// Some(Duration::from_nanos(args[2] as u64))
|
||||
// };
|
||||
//
|
||||
// wait::select(Thread::current(), rfds, wfds, timeout)
|
||||
// }
|
||||
// SystemCall::Access => {
|
||||
// let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
// let path = arg::str_ref(args[1], args[2])?;
|
||||
// let mode = AccessMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
// let flags = args[4] as u32;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// find_at_node(&mut io, at_fd, path, flags & AT_EMPTY_PATH != 0)?
|
||||
// .check_access(io.ioctx(), mode)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::ReadDirectory => {
|
||||
// let proc = Process::current();
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
// let mut io = proc.io.lock();
|
||||
// let buf = arg::struct_buf_mut::<DirectoryEntry>(args[1], args[2])?;
|
||||
//
|
||||
// io.file(fd)?.borrow_mut().readdir(buf)
|
||||
// }
|
||||
// SystemCall::GetUserId => {
|
||||
// let proc = Process::current();
|
||||
// let uid = proc.io.lock().uid();
|
||||
// Ok(u32::from(uid) as usize)
|
||||
// }
|
||||
// SystemCall::GetGroupId => {
|
||||
// let proc = Process::current();
|
||||
// let gid = proc.io.lock().gid();
|
||||
// Ok(u32::from(gid) as usize)
|
||||
// }
|
||||
// SystemCall::DuplicateFd => {
|
||||
// let src = FileDescriptor::from(args[0] as u32);
|
||||
// let dst = FileDescriptor::from_i32(args[1] as i32)?;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// let res = io.duplicate_file(src, dst)?;
|
||||
//
|
||||
// Ok(u32::from(res) as usize)
|
||||
// }
|
||||
// SystemCall::SetUserId => {
|
||||
// let uid = UserId::from(args[0] as u32);
|
||||
// let proc = Process::current();
|
||||
// proc.io.lock().set_uid(uid)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::SetGroupId => {
|
||||
// let gid = GroupId::from(args[0] as u32);
|
||||
// let proc = Process::current();
|
||||
// proc.io.lock().set_gid(gid)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::SetCurrentDirectory => {
|
||||
// let path = arg::str_ref(args[0], args[1])?;
|
||||
// let proc = Process::current();
|
||||
// proc.io.lock().ioctx().chdir(path)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::GetCurrentDirectory => {
|
||||
// todo!()
|
||||
// }
|
||||
// SystemCall::Seek => {
|
||||
// todo!()
|
||||
// }
|
||||
// SystemCall::MapMemory => {
|
||||
// let len = args[1];
|
||||
// if len == 0 || (len & 0xFFF) != 0 {
|
||||
// return Err(Errno::InvalidArgument);
|
||||
// }
|
||||
// let acc = MemoryAccess::from_bits(args[2] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
// let _flags = MemoryAccess::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
//
|
||||
// let mut attrs =
|
||||
// MapAttributes::NOT_GLOBAL | MapAttributes::SH_OUTER | MapAttributes::PXN;
|
||||
// if !acc.contains(MemoryAccess::READ) {
|
||||
// return Err(Errno::NotImplemented);
|
||||
// }
|
||||
// if acc.contains(MemoryAccess::WRITE) {
|
||||
// if acc.contains(MemoryAccess::EXEC) {
|
||||
// return Err(Errno::PermissionDenied);
|
||||
// }
|
||||
// attrs |= MapAttributes::AP_BOTH_READWRITE;
|
||||
// } else {
|
||||
// attrs |= MapAttributes::AP_BOTH_READONLY;
|
||||
// }
|
||||
// if !acc.contains(MemoryAccess::EXEC) {
|
||||
// attrs |= MapAttributes::UXN;
|
||||
// }
|
||||
//
|
||||
// // TODO don't ignore flags
|
||||
// let usage = PageUsage::UserPrivate;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
//
|
||||
// proc.manipulate_space(move |space| {
|
||||
// space.allocate(0x100000000, 0xF00000000, len / 4096, attrs, usage)
|
||||
// })
|
||||
// }
|
||||
// SystemCall::UnmapMemory => {
|
||||
// let addr = args[0];
|
||||
// let len = args[1];
|
||||
//
|
||||
// if addr == 0 || len == 0 || addr & 0xFFF != 0 || len & 0xFFF != 0 {
|
||||
// return Err(Errno::InvalidArgument);
|
||||
// }
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// proc.manipulate_space(move |space| space.free(addr, len / 4096))?;
|
||||
// Ok(0)
|
||||
// }
|
||||
//
|
||||
// // Process
|
||||
// SystemCall::Clone => {
|
||||
// let entry = args[0];
|
||||
// let stack = args[1];
|
||||
// let arg = args[2];
|
||||
//
|
||||
// Process::current()
|
||||
// .new_user_thread(entry, stack, arg)
|
||||
// .map(|e| u32::from(e) as usize)
|
||||
// }
|
||||
// SystemCall::Exec => {
|
||||
// let filename = arg::str_ref(args[0], args[1])?;
|
||||
// let argv = arg::struct_buf_ref::<&str>(args[2], args[3])?;
|
||||
// // Validate each argument as well
|
||||
// for item in argv.iter() {
|
||||
// arg::validate_ptr(item.as_ptr() as usize, item.len(), false)?;
|
||||
// }
|
||||
// let node = {
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
// // TODO argv, envp array passing ABI?
|
||||
// let node = io.ioctx().find(None, filename, true)?;
|
||||
// drop(io);
|
||||
// node
|
||||
// };
|
||||
// let file = node.open(OpenFlags::O_RDONLY)?;
|
||||
// Process::execve(move |space| elf::load_elf(space, file), argv).unwrap();
|
||||
// panic!();
|
||||
// }
|
||||
// SystemCall::Exit => {
|
||||
// let status = ExitCode::from(args[0] as i32);
|
||||
// let flags = args[1];
|
||||
//
|
||||
// if flags & (1 << 0) != 0 {
|
||||
// Process::exit_thread(Thread::current(), status);
|
||||
// } else {
|
||||
// Process::current().exit(status);
|
||||
// }
|
||||
//
|
||||
// unreachable!();
|
||||
// }
|
||||
// SystemCall::WaitPid => {
|
||||
// // TODO special "pid" values
|
||||
// let pid = Pid::try_from(args[0] as u32)?;
|
||||
// let status = arg::struct_mut::<i32>(args[1])?;
|
||||
//
|
||||
// match Process::waitpid(pid) {
|
||||
// Ok(exit) => {
|
||||
// *status = i32::from(exit);
|
||||
// Ok(0)
|
||||
// }
|
||||
// e => e.map(|e| i32::from(e) as usize),
|
||||
// }
|
||||
// }
|
||||
// SystemCall::WaitTid => {
|
||||
// let tid = Tid::from(args[0] as u32);
|
||||
//
|
||||
// match Thread::waittid(tid) {
|
||||
// Ok(_) => Ok(0),
|
||||
// _ => todo!(),
|
||||
// }
|
||||
// }
|
||||
// SystemCall::GetPid => Ok(u32::from(Process::current().id()) as usize),
|
||||
// SystemCall::GetTid => Ok(u32::from(Thread::current().id()) as usize),
|
||||
// SystemCall::Sleep => {
|
||||
// let rem_buf = arg::option_buf_ref(args[1], size_of::<u64>() * 2)?;
|
||||
// let mut rem = Duration::new(0, 0);
|
||||
// let res = wait::sleep(Duration::from_nanos(args[0] as u64), &mut rem);
|
||||
// if res == Err(Errno::Interrupt) {
|
||||
// warnln!("Sleep interrupted, {:?} remaining", rem);
|
||||
// if rem_buf.is_some() {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
// res.map(|_| 0)
|
||||
// }
|
||||
// SystemCall::SetSignalEntry => {
|
||||
// Thread::current().set_signal_entry(args[0], args[1]);
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::SignalReturn => {
|
||||
// Thread::current().return_from_signal();
|
||||
// unreachable!();
|
||||
// }
|
||||
// SystemCall::SendSignal => {
|
||||
// let target = SignalDestination::from(args[0] as isize);
|
||||
// let signal = Signal::try_from(args[1] as u32)?;
|
||||
//
|
||||
// match target {
|
||||
// SignalDestination::This => Process::current().set_signal(signal),
|
||||
// SignalDestination::Process(pid) => Process::get(pid)
|
||||
// .ok_or(Errno::DoesNotExist)?
|
||||
// .set_signal(signal),
|
||||
// _ => todo!(),
|
||||
// };
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::Yield => {
|
||||
// proc::switch();
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::GetSid => {
|
||||
// // TODO handle kernel processes here?
|
||||
// let pid = Pid::to_option(args[0] as u32);
|
||||
// let current = Process::current();
|
||||
// let proc = if let Some(pid) = pid {
|
||||
// let proc = Process::get(pid).ok_or(Errno::DoesNotExist)?;
|
||||
// if proc.sid() != current.sid() {
|
||||
// return Err(Errno::PermissionDenied);
|
||||
// }
|
||||
// proc
|
||||
// } else {
|
||||
// current
|
||||
// };
|
||||
//
|
||||
// Ok(u32::from(proc.sid()) as usize)
|
||||
// }
|
||||
// SystemCall::GetPgid => {
|
||||
// // TODO handle kernel processes here?
|
||||
// let pid = Pid::to_option(args[0] as u32);
|
||||
// let current = Process::current();
|
||||
// let proc = if let Some(pid) = pid {
|
||||
// Process::get(pid).ok_or(Errno::DoesNotExist)?
|
||||
// } else {
|
||||
// current
|
||||
// };
|
||||
//
|
||||
// Ok(u32::from(proc.pgid()) as usize)
|
||||
// }
|
||||
// SystemCall::GetPpid => Ok(u32::from(Process::current().ppid().unwrap()) as usize),
|
||||
// SystemCall::SetSid => {
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// if let Some(_ctty) = io.ctty() {
|
||||
// todo!();
|
||||
// }
|
||||
//
|
||||
// let id = proc.id();
|
||||
// proc.set_sid(id);
|
||||
// Ok(u32::from(id) as usize)
|
||||
// }
|
||||
// SystemCall::SetPgid => {
|
||||
// let pid = Pid::to_option(args[0] as u32);
|
||||
// let pgid = Pid::to_option(args[1] as u32);
|
||||
//
|
||||
// let current = Process::current();
|
||||
// let proc = if let Some(_pid) = pid {
|
||||
// todo!()
|
||||
// } else {
|
||||
// current
|
||||
// };
|
||||
//
|
||||
// if let Some(_pgid) = pgid {
|
||||
// todo!();
|
||||
// } else {
|
||||
// proc.set_pgid(proc.id());
|
||||
// }
|
||||
//
|
||||
// Ok(u32::from(proc.pgid()) as usize)
|
||||
// }
|
||||
//
|
||||
// // System
|
||||
// SystemCall::GetCpuTime => {
|
||||
// let time = machine::local_timer().timestamp()?;
|
||||
// Ok(time.as_nanos() as usize)
|
||||
// }
|
||||
// SystemCall::Mount => {
|
||||
// let target = arg::str_ref(args[0], args[1])?;
|
||||
// let options = arg::struct_ref::<MountOptions>(args[2])?;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// debugln!("mount(target={:?}, options={:#x?})", target, options);
|
||||
//
|
||||
// let target_node = io.ioctx().find(None, target, true)?;
|
||||
// let root = create_filesystem(options)?;
|
||||
//
|
||||
// target_node.mount(root)?;
|
||||
//
|
||||
// Ok(0)
|
||||
// }
|
||||
//
|
||||
// // Debugging
|
||||
// SystemCall::DebugTrace => {
|
||||
// let level = TraceLevel::from_repr(args[0])
|
||||
// .map(Level::from)
|
||||
// .ok_or(Errno::InvalidArgument)?;
|
||||
// let buf = arg::str_ref(args[1], args[2])?;
|
||||
// let thread = Thread::current();
|
||||
// let proc = thread.owner().unwrap();
|
||||
// println!(level, "[trace {:?}:{:?}] {}", proc.id(), thread.id(), buf);
|
||||
// Ok(args[1])
|
||||
// }
|
||||
//
|
||||
// // Handled elsewhere
|
||||
// SystemCall::Fork => unreachable!(),
|
||||
// }
|
||||
match num {
|
||||
// I/O
|
||||
SystemCall::Read => {
|
||||
let proc = Process::current();
|
||||
let fd = FileDescriptor::from(args[0] as u32);
|
||||
let mut io = proc.io.lock();
|
||||
let buf = arg::buf_mut(args[1], args[2])?;
|
||||
|
||||
io.file(fd)?.borrow_mut().read(buf)
|
||||
}
|
||||
SystemCall::Write => {
|
||||
let proc = Process::current();
|
||||
let fd = FileDescriptor::from(args[0] as u32);
|
||||
let mut io = proc.io.lock();
|
||||
let buf = arg::buf_ref(args[1], args[2])?;
|
||||
|
||||
io.file(fd)?.borrow_mut().write(buf)
|
||||
}
|
||||
// SystemCall::Open => {
|
||||
// let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
// let path = arg::str_ref(args[1], args[2])?;
|
||||
// let mode = FileMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
// let opts = OpenFlags::from_bits(args[4] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// let at = if let Some(fd) = at_fd {
|
||||
// io.file(fd)?.borrow().node()
|
||||
// } else {
|
||||
// None
|
||||
// };
|
||||
//
|
||||
// let file = io.ioctx().open(at, path, mode, opts)?;
|
||||
// Ok(u32::from(io.place_file(file)?) as usize)
|
||||
// }
|
||||
// SystemCall::Close => {
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
//
|
||||
// io.close_file(fd)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::FileStatus => {
|
||||
// let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
// let filename = arg::str_ref(args[1], args[2])?;
|
||||
// let buf = arg::struct_mut::<Stat>(args[3])?;
|
||||
// let flags = args[4] as u32;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
// let stat =
|
||||
// find_at_node(&mut io, at_fd, filename, flags & AT_EMPTY_PATH != 0)?.stat()?;
|
||||
// *buf = stat;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::Ioctl => {
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
// let cmd = IoctlCmd::try_from(args[1] as u32)?;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// let node = io.file(fd)?.borrow().node().ok_or(Errno::InvalidFile)?;
|
||||
// node.ioctl(cmd, args[2], args[3])
|
||||
// }
|
||||
// SystemCall::Select => {
|
||||
// let rfds = arg::option_struct_mut::<FdSet>(args[0])?;
|
||||
// let wfds = arg::option_struct_mut::<FdSet>(args[1])?;
|
||||
// let timeout = if args[2] == 0 {
|
||||
// None
|
||||
// } else {
|
||||
// Some(Duration::from_nanos(args[2] as u64))
|
||||
// };
|
||||
//
|
||||
// wait::select(Thread::current(), rfds, wfds, timeout)
|
||||
// }
|
||||
// SystemCall::Access => {
|
||||
// let at_fd = FileDescriptor::from_i32(args[0] as i32)?;
|
||||
// let path = arg::str_ref(args[1], args[2])?;
|
||||
// let mode = AccessMode::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
// let flags = args[4] as u32;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// find_at_node(&mut io, at_fd, path, flags & AT_EMPTY_PATH != 0)?
|
||||
// .check_access(io.ioctx(), mode)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::ReadDirectory => {
|
||||
// let proc = Process::current();
|
||||
// let fd = FileDescriptor::from(args[0] as u32);
|
||||
// let mut io = proc.io.lock();
|
||||
// let buf = arg::struct_buf_mut::<DirectoryEntry>(args[1], args[2])?;
|
||||
//
|
||||
// io.file(fd)?.borrow_mut().readdir(buf)
|
||||
// }
|
||||
// SystemCall::GetUserId => {
|
||||
// let proc = Process::current();
|
||||
// let uid = proc.io.lock().uid();
|
||||
// Ok(u32::from(uid) as usize)
|
||||
// }
|
||||
// SystemCall::GetGroupId => {
|
||||
// let proc = Process::current();
|
||||
// let gid = proc.io.lock().gid();
|
||||
// Ok(u32::from(gid) as usize)
|
||||
// }
|
||||
// SystemCall::DuplicateFd => {
|
||||
// let src = FileDescriptor::from(args[0] as u32);
|
||||
// let dst = FileDescriptor::from_i32(args[1] as i32)?;
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// let res = io.duplicate_file(src, dst)?;
|
||||
//
|
||||
// Ok(u32::from(res) as usize)
|
||||
// }
|
||||
// SystemCall::SetUserId => {
|
||||
// let uid = UserId::from(args[0] as u32);
|
||||
// let proc = Process::current();
|
||||
// proc.io.lock().set_uid(uid)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::SetGroupId => {
|
||||
// let gid = GroupId::from(args[0] as u32);
|
||||
// let proc = Process::current();
|
||||
// proc.io.lock().set_gid(gid)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::SetCurrentDirectory => {
|
||||
// let path = arg::str_ref(args[0], args[1])?;
|
||||
// let proc = Process::current();
|
||||
// proc.io.lock().ioctx().chdir(path)?;
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::GetCurrentDirectory => {
|
||||
// todo!()
|
||||
// }
|
||||
// SystemCall::Seek => {
|
||||
// todo!()
|
||||
// }
|
||||
SystemCall::MapMemory => {
|
||||
let len = args[1];
|
||||
if len == 0 || (len & 0xFFF) != 0 {
|
||||
return Err(Errno::InvalidArgument);
|
||||
}
|
||||
let acc = MemoryAccess::from_bits(args[2] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
let _flags = MemoryAccess::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
|
||||
let mut attrs =
|
||||
MapAttributes::NOT_GLOBAL | MapAttributes::SHARE_OUTER | MapAttributes::USER_READ;
|
||||
if !acc.contains(MemoryAccess::READ) {
|
||||
return Err(Errno::NotImplemented);
|
||||
}
|
||||
if acc.contains(MemoryAccess::WRITE) {
|
||||
if acc.contains(MemoryAccess::EXEC) {
|
||||
return Err(Errno::PermissionDenied);
|
||||
}
|
||||
attrs |= MapAttributes::USER_WRITE | MapAttributes::KERNEL_WRITE;
|
||||
} else {
|
||||
attrs |= MapAttributes::USER_READ;
|
||||
}
|
||||
if !acc.contains(MemoryAccess::EXEC) {
|
||||
attrs |= MapAttributes::USER_EXEC;
|
||||
}
|
||||
|
||||
// TODO don't ignore flags
|
||||
let usage = PageUsage::UserPrivate;
|
||||
|
||||
let proc = Process::current();
|
||||
|
||||
proc.manipulate_space(move |space| {
|
||||
space.allocate(0x100000000, 0xF00000000, len / 4096, attrs, usage)
|
||||
})
|
||||
}
|
||||
// SystemCall::UnmapMemory => {
|
||||
// let addr = args[0];
|
||||
// let len = args[1];
|
||||
//
|
||||
// if addr == 0 || len == 0 || addr & 0xFFF != 0 || len & 0xFFF != 0 {
|
||||
// return Err(Errno::InvalidArgument);
|
||||
// }
|
||||
//
|
||||
// let proc = Process::current();
|
||||
// proc.manipulate_space(move |space| space.free(addr, len / 4096))?;
|
||||
// Ok(0)
|
||||
// }
|
||||
//
|
||||
// // Process
|
||||
// SystemCall::Clone => {
|
||||
// let entry = args[0];
|
||||
// let stack = args[1];
|
||||
// let arg = args[2];
|
||||
//
|
||||
// Process::current()
|
||||
// .new_user_thread(entry, stack, arg)
|
||||
// .map(|e| u32::from(e) as usize)
|
||||
// }
|
||||
// SystemCall::Exec => {
|
||||
// let filename = arg::str_ref(args[0], args[1])?;
|
||||
// let argv = arg::struct_buf_ref::<&str>(args[2], args[3])?;
|
||||
// // Validate each argument as well
|
||||
// for item in argv.iter() {
|
||||
// arg::validate_ptr(item.as_ptr() as usize, item.len(), false)?;
|
||||
// }
|
||||
// let node = {
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
// // TODO argv, envp array passing ABI?
|
||||
// let node = io.ioctx().find(None, filename, true)?;
|
||||
// drop(io);
|
||||
// node
|
||||
// };
|
||||
// let file = node.open(OpenFlags::O_RDONLY)?;
|
||||
// Process::execve(move |space| elf::load_elf(space, file), argv).unwrap();
|
||||
// panic!();
|
||||
// }
|
||||
// SystemCall::Exit => {
|
||||
// let status = ExitCode::from(args[0] as i32);
|
||||
// let flags = args[1];
|
||||
//
|
||||
// if flags & (1 << 0) != 0 {
|
||||
// Process::exit_thread(Thread::current(), status);
|
||||
// } else {
|
||||
// Process::current().exit(status);
|
||||
// }
|
||||
//
|
||||
// unreachable!();
|
||||
// }
|
||||
// SystemCall::WaitPid => {
|
||||
// // TODO special "pid" values
|
||||
// let pid = Pid::try_from(args[0] as u32)?;
|
||||
// let status = arg::struct_mut::<i32>(args[1])?;
|
||||
//
|
||||
// match Process::waitpid(pid) {
|
||||
// Ok(exit) => {
|
||||
// *status = i32::from(exit);
|
||||
// Ok(0)
|
||||
// }
|
||||
// e => e.map(|e| i32::from(e) as usize),
|
||||
// }
|
||||
// }
|
||||
// SystemCall::WaitTid => {
|
||||
// let tid = Tid::from(args[0] as u32);
|
||||
//
|
||||
// match Thread::waittid(tid) {
|
||||
// Ok(_) => Ok(0),
|
||||
// _ => todo!(),
|
||||
// }
|
||||
// }
|
||||
// SystemCall::GetPid => Ok(u32::from(Process::current().id()) as usize),
|
||||
// SystemCall::GetTid => Ok(u32::from(Thread::current().id()) as usize),
|
||||
// SystemCall::Sleep => {
|
||||
// let rem_buf = arg::option_buf_ref(args[1], size_of::<u64>() * 2)?;
|
||||
// let mut rem = Duration::new(0, 0);
|
||||
// let res = wait::sleep(Duration::from_nanos(args[0] as u64), &mut rem);
|
||||
// if res == Err(Errno::Interrupt) {
|
||||
// warnln!("Sleep interrupted, {:?} remaining", rem);
|
||||
// if rem_buf.is_some() {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
// res.map(|_| 0)
|
||||
// }
|
||||
// SystemCall::SetSignalEntry => {
|
||||
// Thread::current().set_signal_entry(args[0], args[1]);
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::SignalReturn => {
|
||||
// Thread::current().return_from_signal();
|
||||
// unreachable!();
|
||||
// }
|
||||
// SystemCall::SendSignal => {
|
||||
// let target = SignalDestination::from(args[0] as isize);
|
||||
// let signal = Signal::try_from(args[1] as u32)?;
|
||||
//
|
||||
// match target {
|
||||
// SignalDestination::This => Process::current().set_signal(signal),
|
||||
// SignalDestination::Process(pid) => Process::get(pid)
|
||||
// .ok_or(Errno::DoesNotExist)?
|
||||
// .set_signal(signal),
|
||||
// _ => todo!(),
|
||||
// };
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::Yield => {
|
||||
// proc::switch();
|
||||
// Ok(0)
|
||||
// }
|
||||
// SystemCall::GetSid => {
|
||||
// // TODO handle kernel processes here?
|
||||
// let pid = Pid::to_option(args[0] as u32);
|
||||
// let current = Process::current();
|
||||
// let proc = if let Some(pid) = pid {
|
||||
// let proc = Process::get(pid).ok_or(Errno::DoesNotExist)?;
|
||||
// if proc.sid() != current.sid() {
|
||||
// return Err(Errno::PermissionDenied);
|
||||
// }
|
||||
// proc
|
||||
// } else {
|
||||
// current
|
||||
// };
|
||||
//
|
||||
// Ok(u32::from(proc.sid()) as usize)
|
||||
// }
|
||||
// SystemCall::GetPgid => {
|
||||
// // TODO handle kernel processes here?
|
||||
// let pid = Pid::to_option(args[0] as u32);
|
||||
// let current = Process::current();
|
||||
// let proc = if let Some(pid) = pid {
|
||||
// Process::get(pid).ok_or(Errno::DoesNotExist)?
|
||||
// } else {
|
||||
// current
|
||||
// };
|
||||
//
|
||||
// Ok(u32::from(proc.pgid()) as usize)
|
||||
// }
|
||||
// SystemCall::GetPpid => Ok(u32::from(Process::current().ppid().unwrap()) as usize),
|
||||
// SystemCall::SetSid => {
|
||||
// let proc = Process::current();
|
||||
// let mut io = proc.io.lock();
|
||||
//
|
||||
// if let Some(_ctty) = io.ctty() {
|
||||
// todo!();
|
||||
// }
|
||||
//
|
||||
// let id = proc.id();
|
||||
// proc.set_sid(id);
|
||||
// Ok(u32::from(id) as usize)
|
||||
// }
|
||||
// SystemCall::SetPgid => {
|
||||
// let pid = Pid::to_option(args[0] as u32);
|
||||
// let pgid = Pid::to_option(args[1] as u32);
|
||||
//
|
||||
// let current = Process::current();
|
||||
// let proc = if let Some(_pid) = pid {
|
||||
// todo!()
|
||||
// } else {
|
||||
// current
|
||||
// };
|
||||
//
|
||||
// if let Some(_pgid) = pgid {
|
||||
// todo!();
|
||||
// } else {
|
||||
// proc.set_pgid(proc.id());
|
||||
// }
|
||||
//
|
||||
// Ok(u32::from(proc.pgid()) as usize)
|
||||
// }
|
||||
//
|
||||
// // System
|
||||
// SystemCall::GetCpuTime => {
|
||||
// let time = machine::local_timer().timestamp()?;
|
||||
// Ok(time.as_nanos() as usize)
|
||||
// }
|
||||
SystemCall::Mount => {
|
||||
let target = arg::str_ref(args[0], args[1])?;
|
||||
let options = arg::struct_ref::<MountOptions>(args[2])?;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
debugln!("mount(target={:?}, options={:#x?})", target, options);
|
||||
|
||||
let target_node = io.ioctx().find(None, target, true)?;
|
||||
let root = create_filesystem(options)?;
|
||||
|
||||
target_node.mount(root)?;
|
||||
|
||||
Ok(0)
|
||||
},
|
||||
|
||||
// Debugging
|
||||
SystemCall::DebugTrace => {
|
||||
let level = TraceLevel::from_repr(args[0])
|
||||
.map(Level::from)
|
||||
.ok_or(Errno::InvalidArgument)?;
|
||||
let buf = arg::str_ref(args[1], args[2])?;
|
||||
let thread = Thread::current();
|
||||
let proc = thread.owner().unwrap();
|
||||
println!(level, "[trace {:?}:{:?}] {}", proc.id(), thread.id(), buf);
|
||||
Ok(args[1])
|
||||
}
|
||||
|
||||
// // Handled elsewhere
|
||||
// SystemCall::Fork => unreachable!(),
|
||||
_ => panic!("Unimplemented: {:?}", num),
|
||||
}
|
||||
}
|
||||
|
||||
/// Main system call dispatcher function
|
||||
pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
// let thread = Thread::current();
|
||||
// let process = thread.owner().unwrap();
|
||||
// let result = _syscall(num, args);
|
||||
// if !thread.is_handling_signal() {
|
||||
// process.handle_pending_signals();
|
||||
// }
|
||||
// result
|
||||
let thread = Thread::current();
|
||||
let process = thread.owner().unwrap();
|
||||
let result = _syscall(num, args);
|
||||
if !thread.is_handling_signal() {
|
||||
// process.handle_pending_signals();
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
+38
-36
@@ -15,57 +15,59 @@ use core::arch::asm;
|
||||
|
||||
// TODO document the syscall ABI
|
||||
|
||||
// rax
|
||||
//
|
||||
// rdi
|
||||
// rsi
|
||||
// rdx
|
||||
// r10
|
||||
// r8
|
||||
// r9
|
||||
|
||||
// TODO move this to libusr
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
macro_rules! syscall {
|
||||
($num:expr) => {{
|
||||
// let mut res: usize;
|
||||
// asm!("svc #0", out("x0") res, in("x8") $num.repr(), options(nostack));
|
||||
// res
|
||||
loop {}
|
||||
0
|
||||
let mut res: usize = $num.repr();
|
||||
asm!("syscall",
|
||||
inout("rax") res,
|
||||
options(nostack));
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr) => {{
|
||||
// let mut res: usize = $a0;
|
||||
// asm!("svc #0",
|
||||
// inout("x0") res,
|
||||
// in("x8") $num.repr(), options(nostack));
|
||||
// res
|
||||
loop {}
|
||||
0
|
||||
let mut res: usize = $num.repr();
|
||||
asm!("syscall",
|
||||
inout("rax") res, in("rdi") $a0,
|
||||
options(nostack));
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr, $a1:expr) => {{
|
||||
// let mut res: usize = $a0;
|
||||
// asm!("svc #0",
|
||||
// inout("x0") res, in("x1") $a1,
|
||||
// in("x8") $num.repr(), options(nostack));
|
||||
// res
|
||||
loop {}
|
||||
0
|
||||
let mut res: usize = $num.repr();
|
||||
asm!("syscall",
|
||||
inout("rax") res, in("rdi") $a0, in("rsi") $a1,
|
||||
options(nostack));
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr, $a1:expr, $a2:expr) => {{
|
||||
let mut res: usize = $a0;
|
||||
let mut res: usize = $num.repr();
|
||||
asm!("syscall",
|
||||
inout("rax") res, in("rdi") $a1, in("rsi") $a2,
|
||||
in("rdx") $num.repr(), options(nostack));
|
||||
inout("rax") res, in("rdi") $a0, in("rsi") $a1,
|
||||
in("rdx") $a2, options(nostack));
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {{
|
||||
// let mut res: usize = $a0;
|
||||
// asm!("svc #0",
|
||||
// inout("x0") res, in("x1") $a1, in("x2") $a2,
|
||||
// in("x3") $a3, in("x8") $num.repr(), options(nostack));
|
||||
// res
|
||||
loop {}
|
||||
0
|
||||
let mut res: usize = $num.repr();
|
||||
asm!("syscall",
|
||||
inout("rax") res, in("rdi") $a0, in("rsi") $a1,
|
||||
in("rdx") $a2, in("r10") $a3, options(nostack));
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {{
|
||||
// let mut res: usize = $a0;
|
||||
// asm!("svc #0",
|
||||
// inout("x0") res, in("x1") $a1, in("x2") $a2,
|
||||
// in("x3") $a3, in("x4") $a4, in("x8") $num.repr(), options(nostack));
|
||||
// res
|
||||
loop {}
|
||||
0
|
||||
let mut res: usize = $num.repr();
|
||||
asm!("syscall",
|
||||
inout("rax") res, in("rdi") $a0, in("rsi") $a1,
|
||||
in("rdx") $a2, in("r10") $a3, in("r8") $a4, options(nostack));
|
||||
res
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
+9
-11
@@ -26,14 +26,11 @@ extern "C" fn _start(arg: &'static ProgramArgs) -> ! {
|
||||
fn main() -> i32;
|
||||
}
|
||||
|
||||
trace!(TraceLevel::Debug, "Test!");
|
||||
loop {}
|
||||
|
||||
// unsafe {
|
||||
// allocator::init();
|
||||
// thread::init_main();
|
||||
// env::setup_env(arg);
|
||||
// }
|
||||
unsafe {
|
||||
allocator::init();
|
||||
thread::init_main();
|
||||
env::setup_env(arg);
|
||||
}
|
||||
|
||||
let res = unsafe { main() };
|
||||
sys::sys_exit(ExitCode::from(res));
|
||||
@@ -43,7 +40,8 @@ extern "C" fn _start(arg: &'static ProgramArgs) -> ! {
|
||||
fn panic_handler(pi: &PanicInfo) -> ! {
|
||||
// TODO unwind to send panic argument back to parent thread
|
||||
// TODO print to stdout/stderr (if available)
|
||||
let thread = thread::current();
|
||||
trace!(TraceLevel::Error, "{:?} panicked: {:?}", thread, pi);
|
||||
sys::sys_exit(ExitCode::from(-1));
|
||||
// let thread = thread::current();
|
||||
// trace!(TraceLevel::Error, "{:?} panicked: {:?}", thread, pi);
|
||||
loop {}
|
||||
// sys::sys_exit(ExitCode::from(-1));
|
||||
}
|
||||
|
||||
+20
-11
@@ -9,7 +9,8 @@ use libusr::sys::{stat::MountOptions, sys_execve, sys_fork, sys_mount, sys_waitp
|
||||
|
||||
#[no_mangle]
|
||||
fn main() -> i32 {
|
||||
loop {}
|
||||
println!("Test");
|
||||
trace_debug!("test!");
|
||||
|
||||
sys_mount(
|
||||
"/dev",
|
||||
@@ -28,15 +29,23 @@ fn main() -> i32 {
|
||||
)
|
||||
.expect("Failed to mount sysfs");
|
||||
|
||||
if let Some(pid) = unsafe { sys_fork().unwrap() } {
|
||||
let mut status = 0;
|
||||
sys_waitpid(pid, &mut status).unwrap();
|
||||
println!("Process {:?} exited with status {}", pid, status);
|
||||
let pid = unsafe { sys_fork().unwrap() };
|
||||
|
||||
loop {
|
||||
}
|
||||
} else {
|
||||
sys_execve("/sbin/login", &["/sbin/login", "/dev/ttyS0"]).unwrap();
|
||||
unreachable!();
|
||||
}
|
||||
trace_debug!("fork returned {:?}", pid);
|
||||
|
||||
loop {}
|
||||
|
||||
// loop {}
|
||||
|
||||
// if let Some(pid) = unsafe { sys_fork().unwrap() } {
|
||||
// let mut status = 0;
|
||||
// sys_waitpid(pid, &mut status).unwrap();
|
||||
// println!("Process {:?} exited with status {}", pid, status);
|
||||
|
||||
// loop {
|
||||
// }
|
||||
// } else {
|
||||
// sys_execve("/sbin/login", &["/sbin/login", "/dev/ttyS0"]).unwrap();
|
||||
// unreachable!();
|
||||
// }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user