From 5113516b28a446abf2179c3002647197a2e7a3f7 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Sun, 23 Jan 2022 20:19:43 +0200 Subject: [PATCH] Almost forking, UB --- etc/x86_64-osdev5.json | 2 +- etc/x86_64-osdev5.ld | 32 ++ kernel/src/arch/x86_64/boot/mod.rs | 3 +- kernel/src/arch/x86_64/mod.rs | 2 + kernel/src/arch/x86_64/syscall.S | 58 +- kernel/src/arch/x86_64/syscall.rs | 36 ++ kernel/src/arch/x86_64/table.rs | 52 ++ kernel/src/arch/x86_64/uart.rs | 20 +- kernel/src/dev/mod.rs | 2 +- kernel/src/dev/tty.rs | 3 +- kernel/src/init.rs | 36 +- kernel/src/mem/virt/table.rs | 29 + kernel/src/proc/process.rs | 71 +-- kernel/src/syscall/arg.rs | 44 +- kernel/src/syscall/mod.rs | 829 +++++++++++++++-------------- libsys/src/calls.rs | 74 +-- libusr/src/lib.rs | 20 +- user/src/init/main.rs | 31 +- 18 files changed, 797 insertions(+), 547 deletions(-) create mode 100644 etc/x86_64-osdev5.ld diff --git a/etc/x86_64-osdev5.json b/etc/x86_64-osdev5.json index 4957a5d..b83686c 100644 --- a/etc/x86_64-osdev5.json +++ b/etc/x86_64-osdev5.json @@ -16,6 +16,6 @@ "os": "none", "pre-link-args": { - "ld.lld": [ "-Tetc/aarch64-osdev5.ld" ] + "ld.lld": [ "-Tetc/x86_64-osdev5.ld" ] } } diff --git a/etc/x86_64-osdev5.ld b/etc/x86_64-osdev5.ld new file mode 100644 index 0000000..b9be323 --- /dev/null +++ b/etc/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 +} diff --git a/kernel/src/arch/x86_64/boot/mod.rs b/kernel/src/arch/x86_64/boot/mod.rs index c61817f..63af7c1 100644 --- a/kernel/src/arch/x86_64/boot/mod.rs +++ b/kernel/src/arch/x86_64/boot/mod.rs @@ -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(); diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 30defc7..8f1278c 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -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 diff --git a/kernel/src/arch/x86_64/syscall.S b/kernel/src/arch/x86_64/syscall.S index 45e868e..d6ae1de 100644 --- a/kernel/src/arch/x86_64/syscall.S +++ b/kernel/src/arch/x86_64/syscall.S @@ -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 diff --git a/kernel/src/arch/x86_64/syscall.rs b/kernel/src/arch/x86_64/syscall.rs index c37fb23..a1658ce 100644 --- a/kernel/src/arch/x86_64/syscall.rs +++ b/kernel/src/arch/x86_64/syscall.rs @@ -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)); diff --git a/kernel/src/arch/x86_64/table.rs b/kernel/src/arch/x86_64/table.rs index 550ee81..ac73638 100644 --- a/kernel/src/arch/x86_64/table.rs +++ b/kernel/src/arch/x86_64/table.rs @@ -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 for Table { diff --git a/kernel/src/arch/x86_64/uart.rs b/kernel/src/arch/x86_64/uart.rs index 26ade15..abeb7c2 100644 --- a/kernel/src/arch/x86_64/uart.rs +++ b/kernel/src/arch/x86_64/uart.rs @@ -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 + dr: PortIo, + 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() } } } diff --git a/kernel/src/dev/mod.rs b/kernel/src/dev/mod.rs index 069a1a0..33a2420 100644 --- a/kernel/src/dev/mod.rs +++ b/kernel/src/dev/mod.rs @@ -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 { diff --git a/kernel/src/dev/tty.rs b/kernel/src/dev/tty.rs index c713c30..1095069 100644 --- a/kernel/src/dev/tty.rs +++ b/kernel/src/dev/tty.rs @@ -126,7 +126,8 @@ pub trait TtyDevice: 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; diff --git a/kernel/src/init.rs b/kernel/src/init.rs index ca7936a..db7789f 100644 --- a/kernel/src/init.rs +++ b/kernel/src/init.rs @@ -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); diff --git a/kernel/src/mem/virt/table.rs b/kernel/src/mem/virt/table.rs index d6f4bbf..de781fd 100644 --- a/kernel/src/mem/virt/table.rs +++ b/kernel/src/mem/virt/table.rs @@ -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; @@ -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 { 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 { + '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) + } } diff --git a/kernel/src/proc/process.rs b/kernel/src/proc/process.rs index 871e9f6..adea760 100644 --- a/kernel/src/proc/process.rs +++ b/kernel/src/proc/process.rs @@ -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 { - // 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 { + 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) { diff --git a/kernel/src/syscall/arg.rs b/kernel/src/syscall/arg.rs index d695cde..4726a81 100644 --- a/kernel/src/syscall/arg.rs +++ b/kernel/src/syscall/arg.rs @@ -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 { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 0c115c1..88d0e8c 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -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 { -// 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 { + Process::current().fork(regs) +} fn find_at_node>( io: &mut T, @@ -57,407 +61,406 @@ fn find_at_node>( } fn _syscall(num: SystemCall, args: &[usize]) -> Result { - 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::(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::(args[0])?; -// let wfds = arg::option_struct_mut::(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::(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::(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::() * 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::(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::(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::(args[0])?; + // let wfds = arg::option_struct_mut::(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::(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::(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::() * 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::(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 { - 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 } diff --git a/libsys/src/calls.rs b/libsys/src/calls.rs index 7e5c281..ac36462 100644 --- a/libsys/src/calls.rs +++ b/libsys/src/calls.rs @@ -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 }}; } diff --git a/libusr/src/lib.rs b/libusr/src/lib.rs index 035843d..b1f5b1e 100644 --- a/libusr/src/lib.rs +++ b/libusr/src/lib.rs @@ -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)); } diff --git a/user/src/init/main.rs b/user/src/init/main.rs index ebabda1..c0711f3 100644 --- a/user/src/init/main.rs +++ b/user/src/init/main.rs @@ -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!(); + // } }