refactor: better syscall result handling

This commit is contained in:
Mark Poliakov 2021-11-13 15:44:55 +02:00
parent a695232926
commit 1f204e1d4c
10 changed files with 222 additions and 156 deletions

View File

@ -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;
}
}
}

View File

@ -139,7 +139,8 @@ unsafe impl Manager for SimpleManager {
usage
};
self.update_stats_free(usage, 1);
// FIXME
// self.update_stats_free(usage, 1);
Ok(())
}

View File

@ -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)
)
})
}

View File

@ -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
View 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!()
}
}

View File

@ -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)
}

View File

@ -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));
}

View File

@ -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(())

View File

@ -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 {}
}
}

View File

@ -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(|_| ());
}
}