refactor: better syscall result handling
This commit is contained in:
parent
a695232926
commit
1f204e1d4c
@ -6,8 +6,8 @@ use crate::dev::irq::{IntController, IrqContext};
|
||||
use crate::mem;
|
||||
use crate::proc::{sched, Process};
|
||||
use crate::syscall;
|
||||
use libsys::{abi, signal::Signal};
|
||||
use cortex_a::registers::{ESR_EL1, FAR_EL1};
|
||||
use libsys::{abi, signal::Signal};
|
||||
use tock_registers::interfaces::Readable;
|
||||
|
||||
/// Trapped SIMD/FP functionality
|
||||
@ -92,7 +92,10 @@ extern "C" fn __aa64_exc_sync_handler(exc: &mut ExceptionFrame) {
|
||||
if far < mem::KERNEL_OFFSET && sched::is_ready() {
|
||||
let proc = Process::current();
|
||||
|
||||
if proc.manipulate_space(|space| space.try_cow_copy(far)).is_err() {
|
||||
if proc
|
||||
.manipulate_space(|space| space.try_cow_copy(far))
|
||||
.is_err()
|
||||
{
|
||||
// Kill program
|
||||
dump_data_abort(Level::Error, esr, far as u64);
|
||||
proc.enter_signal(Signal::SegmentationFault);
|
||||
@ -117,8 +120,7 @@ extern "C" fn __aa64_exc_sync_handler(exc: &mut ExceptionFrame) {
|
||||
match syscall::sys_fork(exc) {
|
||||
Ok(pid) => exc.x[0] = pid.value() as usize,
|
||||
Err(err) => {
|
||||
warnln!("fork() syscall failed: {:?}", err);
|
||||
exc.x[0] = usize::MAX;
|
||||
exc.x[0] = err.to_negative_isize() as usize;
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -127,8 +129,7 @@ extern "C" fn __aa64_exc_sync_handler(exc: &mut ExceptionFrame) {
|
||||
match syscall::syscall(exc.x[8], &exc.x[..6]) {
|
||||
Ok(val) => exc.x[0] = val,
|
||||
Err(err) => {
|
||||
warnln!("syscall {} failed: {:?}", exc.x[8], err);
|
||||
exc.x[0] = usize::MAX
|
||||
exc.x[0] = err.to_negative_isize() as usize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,8 @@ unsafe impl Manager for SimpleManager {
|
||||
|
||||
usage
|
||||
};
|
||||
self.update_stats_free(usage, 1);
|
||||
// FIXME
|
||||
// self.update_stats_free(usage, 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::abi;
|
||||
use crate::{
|
||||
error::Errno,
|
||||
ioctl::IoctlCmd,
|
||||
proc::{ExitCode, Pid},
|
||||
signal::{Signal, SignalDestination},
|
||||
stat::{FdSet, FileDescriptor, FileMode, OpenFlags, Stat},
|
||||
};
|
||||
@ -71,8 +73,10 @@ macro_rules! argp {
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_exit(status: i32) -> ! {
|
||||
syscall!(abi::SYS_EXIT, argn!(status));
|
||||
pub fn sys_exit(code: ExitCode) -> ! {
|
||||
unsafe {
|
||||
syscall!(abi::SYS_EXIT, argn!(i32::from(code)));
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
@ -80,172 +84,209 @@ pub unsafe fn sys_exit(status: i32) -> ! {
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_close(fd: FileDescriptor) -> i32 {
|
||||
syscall!(abi::SYS_CLOSE, argn!(u32::from(fd))) as i32
|
||||
pub fn sys_close(fd: FileDescriptor) -> Result<(), Errno> {
|
||||
Errno::from_syscall_unit(unsafe { syscall!(abi::SYS_CLOSE, argn!(u32::from(fd))) })
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_ex_nanosleep(ns: u64, rem: &mut [u64; 2]) -> i32 {
|
||||
syscall!(abi::SYS_EX_NANOSLEEP, argn!(ns), argp!(rem.as_mut_ptr())) as i32
|
||||
pub fn sys_ex_nanosleep(ns: u64, rem: &mut [u64; 2]) -> Result<(), Errno> {
|
||||
Errno::from_syscall_unit(unsafe {
|
||||
syscall!(abi::SYS_EX_NANOSLEEP, argn!(ns), argp!(rem.as_mut_ptr()))
|
||||
})
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_ex_debug_trace(msg: &[u8]) -> usize {
|
||||
syscall!(
|
||||
abi::SYS_EX_DEBUG_TRACE,
|
||||
argp!(msg.as_ptr()),
|
||||
argn!(msg.len())
|
||||
)
|
||||
pub fn sys_ex_debug_trace(msg: &[u8]) -> Result<(), Errno> {
|
||||
Errno::from_syscall_unit(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_EX_DEBUG_TRACE,
|
||||
argp!(msg.as_ptr()),
|
||||
argn!(msg.len())
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_openat(
|
||||
pub fn sys_openat(
|
||||
at: Option<FileDescriptor>,
|
||||
pathname: &str,
|
||||
mode: FileMode,
|
||||
flags: OpenFlags,
|
||||
) -> i32 {
|
||||
syscall!(
|
||||
abi::SYS_OPENAT,
|
||||
argn!(FileDescriptor::into_i32(at)),
|
||||
argp!(pathname.as_ptr()),
|
||||
argn!(pathname.len()),
|
||||
argn!(mode.bits()),
|
||||
argn!(flags.bits())
|
||||
) as i32
|
||||
) -> Result<FileDescriptor, Errno> {
|
||||
Errno::from_syscall(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_OPENAT,
|
||||
argn!(FileDescriptor::into_i32(at)),
|
||||
argp!(pathname.as_ptr()),
|
||||
argn!(pathname.len()),
|
||||
argn!(mode.bits()),
|
||||
argn!(flags.bits())
|
||||
)
|
||||
})
|
||||
.map(|e| FileDescriptor::from(e as u32))
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_read(fd: FileDescriptor, data: &mut [u8]) -> isize {
|
||||
syscall!(
|
||||
abi::SYS_READ,
|
||||
argn!(u32::from(fd)),
|
||||
argp!(data.as_mut_ptr()),
|
||||
argn!(data.len())
|
||||
) as isize
|
||||
pub fn sys_read(fd: FileDescriptor, data: &mut [u8]) -> Result<usize, Errno> {
|
||||
Errno::from_syscall(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_READ,
|
||||
argn!(u32::from(fd)),
|
||||
argp!(data.as_mut_ptr()),
|
||||
argn!(data.len())
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sys_write(fd: FileDescriptor, data: &[u8]) -> Result<usize, Errno> {
|
||||
Errno::from_syscall(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_WRITE,
|
||||
argn!(u32::from(fd)),
|
||||
argp!(data.as_ptr()),
|
||||
argn!(data.len())
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_write(fd: FileDescriptor, data: &[u8]) -> isize {
|
||||
syscall!(
|
||||
abi::SYS_WRITE,
|
||||
argn!(u32::from(fd)),
|
||||
argp!(data.as_ptr()),
|
||||
argn!(data.len())
|
||||
) as isize
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_fstatat(
|
||||
pub fn sys_fstatat(
|
||||
at: Option<FileDescriptor>,
|
||||
pathname: &str,
|
||||
statbuf: &mut Stat,
|
||||
flags: u32,
|
||||
) -> i32 {
|
||||
syscall!(
|
||||
abi::SYS_FSTATAT,
|
||||
argn!(FileDescriptor::into_i32(at)),
|
||||
argp!(pathname.as_ptr()),
|
||||
argn!(pathname.len()),
|
||||
argp!(statbuf as *mut Stat),
|
||||
argn!(flags)
|
||||
) as i32
|
||||
) -> Result<(), Errno> {
|
||||
Errno::from_syscall_unit(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_FSTATAT,
|
||||
argn!(FileDescriptor::into_i32(at)),
|
||||
argp!(pathname.as_ptr()),
|
||||
argn!(pathname.len()),
|
||||
argp!(statbuf as *mut Stat),
|
||||
argn!(flags)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_fork() -> i32 {
|
||||
syscall!(abi::SYS_FORK) as i32
|
||||
pub fn sys_fork() -> Result<Option<Pid>, Errno> {
|
||||
Errno::from_syscall(unsafe { syscall!(abi::SYS_FORK) }).map(|res| {
|
||||
if res != 0 {
|
||||
Some(unsafe { Pid::from_raw(res as u32) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_execve(pathname: &str) -> i32 {
|
||||
syscall!(
|
||||
abi::SYS_EXECVE,
|
||||
argp!(pathname.as_ptr()),
|
||||
argn!(pathname.len())
|
||||
) as i32
|
||||
pub fn sys_execve(pathname: &str) -> Result<(), Errno> {
|
||||
Errno::from_syscall_unit(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_EXECVE,
|
||||
argp!(pathname.as_ptr()),
|
||||
argn!(pathname.len())
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_waitpid(pid: u32, status: &mut i32) -> i32 {
|
||||
syscall!(abi::SYS_WAITPID, argn!(pid), argp!(status as *mut i32)) as i32
|
||||
pub fn sys_waitpid(pid: Pid, status: &mut i32) -> Result<(), Errno> {
|
||||
Errno::from_syscall_unit(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_WAITPID,
|
||||
argn!(pid.value()),
|
||||
argp!(status as *mut i32)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_ioctl(fd: FileDescriptor, cmd: IoctlCmd, ptr: usize, len: usize) -> isize {
|
||||
syscall!(
|
||||
abi::SYS_IOCTL,
|
||||
argn!(u32::from(fd)),
|
||||
argn!(cmd),
|
||||
argn!(ptr),
|
||||
argn!(len)
|
||||
) as isize
|
||||
pub fn sys_ioctl(
|
||||
fd: FileDescriptor,
|
||||
cmd: IoctlCmd,
|
||||
ptr: usize,
|
||||
len: usize,
|
||||
) -> Result<usize, Errno> {
|
||||
Errno::from_syscall(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_IOCTL,
|
||||
argn!(u32::from(fd)),
|
||||
argn!(cmd),
|
||||
argn!(ptr),
|
||||
argn!(len)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_ex_signal(entry: usize, stack: usize) {
|
||||
syscall!(abi::SYS_EX_SIGNAL, argn!(entry), argn!(stack));
|
||||
pub fn sys_ex_signal(entry: usize, stack: usize) -> Result<(), Errno> {
|
||||
Errno::from_syscall_unit(unsafe { syscall!(abi::SYS_EX_SIGNAL, argn!(entry), argn!(stack)) })
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_ex_sigreturn() -> ! {
|
||||
syscall!(abi::SYS_EX_SIGRETURN);
|
||||
pub fn sys_ex_sigreturn() -> ! {
|
||||
unsafe {
|
||||
syscall!(abi::SYS_EX_SIGRETURN);
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_ex_kill(pid: SignalDestination, signum: Signal) -> i32 {
|
||||
syscall!(
|
||||
abi::SYS_EX_KILL,
|
||||
argn!(isize::from(pid)),
|
||||
argn!(signum as u32)
|
||||
) as i32
|
||||
pub fn sys_ex_kill(pid: SignalDestination, signum: Signal) -> Result<(), Errno> {
|
||||
Errno::from_syscall_unit(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_EX_KILL,
|
||||
argn!(isize::from(pid)),
|
||||
argn!(signum as u32)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_select(
|
||||
pub fn sys_select(
|
||||
read_fds: Option<&mut FdSet>,
|
||||
write_fds: Option<&mut FdSet>,
|
||||
timeout: u64,
|
||||
) -> i32 {
|
||||
syscall!(
|
||||
abi::SYS_SELECT,
|
||||
argp!(read_fds
|
||||
.map(|e| e as *mut _)
|
||||
.unwrap_or(core::ptr::null_mut())),
|
||||
argp!(write_fds
|
||||
.map(|e| e as *mut _)
|
||||
.unwrap_or(core::ptr::null_mut())),
|
||||
argn!(timeout)
|
||||
) as i32
|
||||
) -> Result<usize, Errno> {
|
||||
Errno::from_syscall(unsafe {
|
||||
syscall!(
|
||||
abi::SYS_SELECT,
|
||||
argp!(read_fds
|
||||
.map(|e| e as *mut _)
|
||||
.unwrap_or(core::ptr::null_mut())),
|
||||
argp!(write_fds
|
||||
.map(|e| e as *mut _)
|
||||
.unwrap_or(core::ptr::null_mut())),
|
||||
argn!(timeout)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
#[repr(u32)]
|
||||
pub enum Errno {
|
||||
AlreadyExists,
|
||||
BadExecutable,
|
||||
@ -19,3 +20,33 @@ pub enum Errno {
|
||||
TooManyDescriptors,
|
||||
WouldBlock,
|
||||
}
|
||||
|
||||
impl Errno {
|
||||
pub const fn to_negative_isize(self) -> isize {
|
||||
-(self as isize)
|
||||
}
|
||||
|
||||
pub fn from_syscall(u: usize) -> Result<usize, Self> {
|
||||
let i = u as isize;
|
||||
if i < 0 {
|
||||
Err(Self::from((-i) as usize))
|
||||
} else {
|
||||
Ok(u)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_syscall_unit(u: usize) -> Result<(), Self> {
|
||||
let i = u as isize;
|
||||
if i < 0 {
|
||||
Err(Self::from((-i) as usize))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Errno {
|
||||
fn from(u: usize) -> Errno {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
12
libusr/src/file.rs
Normal file
12
libusr/src/file.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use libsys::stat::FileDescriptor;
|
||||
use crate::io;
|
||||
|
||||
pub struct File {
|
||||
fd: FileDescriptor
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn open(path: &str) -> Result<File, io::Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
@ -9,10 +9,8 @@ pub struct Error;
|
||||
|
||||
pub fn stat(pathname: &str) -> Result<Stat, Error> {
|
||||
let mut buf = Stat::default();
|
||||
let res = unsafe { sys_fstatat(None, pathname, &mut buf, 0) };
|
||||
if res != 0 {
|
||||
todo!();
|
||||
}
|
||||
// TODO error handling
|
||||
let res = unsafe { sys_fstatat(None, pathname, &mut buf, 0).unwrap() };
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,11 @@
|
||||
#![no_std]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
use libsys::proc::ExitCode;
|
||||
|
||||
pub mod io;
|
||||
pub mod os;
|
||||
pub mod file;
|
||||
|
||||
pub mod sys {
|
||||
pub use libsys::signal::{Signal, SignalDestination};
|
||||
@ -33,7 +35,7 @@ extern "C" fn _start(_arg: usize) -> ! {
|
||||
SIGNAL_STACK[0] = 1;
|
||||
sys::sys_ex_signal(_signal_handler as usize, SIGNAL_STACK.as_ptr() as usize + 4096);
|
||||
|
||||
sys::sys_exit(main());
|
||||
sys::sys_exit(ExitCode::from(main()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +43,5 @@ extern "C" fn _start(_arg: usize) -> ! {
|
||||
fn panic_handler(pi: &PanicInfo) -> ! {
|
||||
// TODO formatted messages
|
||||
trace!("Panic ocurred: {}", pi);
|
||||
unsafe {
|
||||
sys::sys_exit(-1);
|
||||
}
|
||||
sys::sys_exit(ExitCode::from(-1));
|
||||
}
|
||||
|
@ -5,30 +5,28 @@ use libsys::{ioctl::IoctlCmd, stat::FileDescriptor, termios::Termios};
|
||||
|
||||
pub fn get_tty_attrs(fd: FileDescriptor) -> Result<Termios, &'static str> {
|
||||
let mut termios = MaybeUninit::<Termios>::uninit();
|
||||
let res = unsafe {
|
||||
sys::sys_ioctl(
|
||||
fd,
|
||||
IoctlCmd::TtyGetAttributes,
|
||||
termios.as_mut_ptr() as usize,
|
||||
size_of::<Termios>(),
|
||||
)
|
||||
};
|
||||
if res != size_of::<Termios>() as isize {
|
||||
let res = sys::sys_ioctl(
|
||||
fd,
|
||||
IoctlCmd::TtyGetAttributes,
|
||||
termios.as_mut_ptr() as usize,
|
||||
size_of::<Termios>(),
|
||||
)
|
||||
.unwrap();
|
||||
if res != size_of::<Termios>() {
|
||||
return Err("Failed");
|
||||
}
|
||||
Ok(unsafe { termios.assume_init() })
|
||||
}
|
||||
|
||||
pub fn set_tty_attrs(fd: FileDescriptor, attrs: &Termios) -> Result<(), &'static str> {
|
||||
let res = unsafe {
|
||||
sys::sys_ioctl(
|
||||
fd,
|
||||
IoctlCmd::TtySetAttributes,
|
||||
attrs as *const _ as usize,
|
||||
size_of::<Termios>(),
|
||||
)
|
||||
};
|
||||
if res != size_of::<Termios>() as isize {
|
||||
let res = sys::sys_ioctl(
|
||||
fd,
|
||||
IoctlCmd::TtySetAttributes,
|
||||
attrs as *const _ as usize,
|
||||
size_of::<Termios>(),
|
||||
)
|
||||
.unwrap();
|
||||
if res != size_of::<Termios>() {
|
||||
return Err("Failed");
|
||||
}
|
||||
Ok(())
|
||||
|
@ -5,31 +5,22 @@
|
||||
#[macro_use]
|
||||
extern crate libusr;
|
||||
|
||||
use core::cmp::Ordering;
|
||||
|
||||
#[no_mangle]
|
||||
fn main() -> i32 {
|
||||
let pid = unsafe { libusr::sys::sys_fork() };
|
||||
match pid.cmp(&0) {
|
||||
Ordering::Less => {
|
||||
eprintln!("fork() failed");
|
||||
-1
|
||||
}
|
||||
Ordering::Equal => unsafe { libusr::sys::sys_execve("/bin/shell") },
|
||||
Ordering::Greater => {
|
||||
let mut status = 0;
|
||||
let res = unsafe { libusr::sys::sys_waitpid(pid as u32, &mut status) };
|
||||
if res == 0 {
|
||||
println!("Process {} exited with status {}", pid, status);
|
||||
} else {
|
||||
eprintln!("waitpid() failed");
|
||||
}
|
||||
let pid = libusr::sys::sys_fork().unwrap();
|
||||
|
||||
loop {
|
||||
unsafe {
|
||||
asm!("nop");
|
||||
}
|
||||
if let Some(pid) = pid {
|
||||
let mut status = 0;
|
||||
libusr::sys::sys_waitpid(pid, &mut status).unwrap();
|
||||
println!("Process {:?} exited with status {}", pid, status);
|
||||
|
||||
loop {
|
||||
unsafe {
|
||||
asm!("nop");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
libusr::sys::sys_execve("/bin/shell").unwrap();
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
@ -13,11 +13,8 @@ fn readline(fd: FileDescriptor, buf: &mut [u8]) -> Result<&str, ()> {
|
||||
let mut rfds = FdSet::empty();
|
||||
rfds.set(fd);
|
||||
let res = unsafe {
|
||||
libusr::sys::sys_select(Some(&mut rfds), None, 1_000_000_000)
|
||||
libusr::sys::sys_select(Some(&mut rfds), None, 1_000_000_000).unwrap()
|
||||
};
|
||||
if res < 0 {
|
||||
return Err(());
|
||||
}
|
||||
if res == 0 {
|
||||
continue;
|
||||
}
|
||||
@ -25,12 +22,8 @@ fn readline(fd: FileDescriptor, buf: &mut [u8]) -> Result<&str, ()> {
|
||||
panic!();
|
||||
}
|
||||
|
||||
let count = unsafe { libusr::sys::sys_read(fd, buf) };
|
||||
if count >= 0 {
|
||||
return core::str::from_utf8(&buf[..count as usize]).map_err(|_| ());
|
||||
} else {
|
||||
return Err(());
|
||||
}
|
||||
let count = unsafe { libusr::sys::sys_read(fd, buf).unwrap() };
|
||||
return core::str::from_utf8(&buf[..count as usize]).map_err(|_| ());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user