use core::{mem, slice}; use core::arch::asm; use core::ops::{Deref, DerefMut}; use super::error::{Error, Result}; pub const PAGE_SIZE: usize = 4096; macro_rules! syscall { ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => { $( pub unsafe fn $name(mut $a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result { asm!( "int 0x80", inout("eax") $a, $( in("ebx") $b, $( in("ecx") $c, $( in("edx") $d, $( in("esi") $e, $( in("edi") $f, )? )? )? )? )? options(nostack), ); Error::demux($a) } )+ }; } syscall! { syscall0(a,); syscall1(a, b,); syscall2(a, b, c,); syscall3(a, b, c, d,); // Must be done custom because LLVM reserves ESI //syscall4(a, b, c, d, e,); //syscall5(a, b, c, d, e, f,); } pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { asm!( "xchg esi, {e} int 0x80 xchg esi, {e}", e = in(reg) e, inout("eax") a, in("ebx") b, in("ecx") c, in("edx") d, options(nostack), ); Error::demux(a) } pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { asm!( "xchg esi, {e} int 0x80 xchg esi, {e}", e = in(reg) e, inout("eax") a, in("ebx") b, in("ecx") c, in("edx") d, in("edi") f, options(nostack), ); Error::demux(a) } #[derive(Copy, Clone, Debug, Default)] #[repr(C)] pub struct IntRegisters { // TODO: Some of these don't get set by Redox yet. Should they? pub ebp: usize, pub esi: usize, pub edi: usize, pub ebx: usize, pub eax: usize, pub ecx: usize, pub edx: usize, // pub orig_rax: usize, pub eip: usize, pub cs: usize, pub eflags: usize, pub esp: usize, pub ss: usize, // pub fs_base: usize, // pub gs_base: usize, // pub ds: usize, // pub es: usize, pub fs: usize, // pub gs: usize } impl Deref for IntRegisters { type Target = [u8]; fn deref(&self) -> &[u8] { unsafe { slice::from_raw_parts(self as *const IntRegisters as *const u8, mem::size_of::()) } } } impl DerefMut for IntRegisters { fn deref_mut(&mut self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self as *mut IntRegisters as *mut u8, mem::size_of::()) } } } #[derive(Clone, Copy, Debug, Default)] #[repr(packed)] pub struct FloatRegisters { pub fcw: u16, pub fsw: u16, pub ftw: u8, pub _reserved: u8, pub fop: u16, pub fip: u64, pub fdp: u64, pub mxcsr: u32, pub mxcsr_mask: u32, pub st_space: [u128; 8], pub xmm_space: [u128; 16], // TODO: YMM/ZMM } impl Deref for FloatRegisters { type Target = [u8]; fn deref(&self) -> &[u8] { unsafe { slice::from_raw_parts(self as *const FloatRegisters as *const u8, mem::size_of::()) } } } impl DerefMut for FloatRegisters { fn deref_mut(&mut self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self as *mut FloatRegisters as *mut u8, mem::size_of::()) } } } #[derive(Clone, Copy, Debug, Default)] #[repr(packed)] pub struct EnvRegisters { pub fsbase: u32, pub gsbase: u32, } impl Deref for EnvRegisters { type Target = [u8]; fn deref(&self) -> &[u8] { unsafe { slice::from_raw_parts(self as *const EnvRegisters as *const u8, mem::size_of::()) } } } impl DerefMut for EnvRegisters { fn deref_mut(&mut self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self as *mut EnvRegisters as *mut u8, mem::size_of::()) } } }