syscall/arch/
x86.rs

1use core::{
2    arch::asm,
3    mem,
4    ops::{Deref, DerefMut},
5    slice,
6};
7
8use super::error::{Error, Result};
9
10pub const PAGE_SIZE: usize = 4096;
11
12#[cfg(feature = "userspace")]
13macro_rules! syscall {
14    ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
15        $(
16            pub unsafe fn $name(mut $a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result<usize> {
17                asm!(
18                    "int 0x80",
19                    inout("eax") $a,
20                    $(
21                        in("ebx") $b,
22                        $(
23                            in("ecx") $c,
24                            $(
25                                in("edx") $d,
26                                $(
27                                    in("esi") $e,
28                                    $(
29                                        in("edi") $f,
30                                    )?
31                                )?
32                            )?
33                        )?
34                    )?
35                    options(nostack),
36                );
37
38                Error::demux($a)
39            }
40        )+
41    };
42}
43
44#[cfg(feature = "userspace")]
45syscall! {
46    syscall0(a,);
47    syscall1(a, b,);
48    syscall2(a, b, c,);
49    syscall3(a, b, c, d,);
50    // Must be done custom because LLVM reserves ESI
51    //syscall4(a, b, c, d, e,);
52    //syscall5(a, b, c, d, e, f,);
53}
54
55#[cfg(feature = "userspace")]
56pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
57    asm!(
58        "xchg esi, {e}
59        int 0x80
60        xchg esi, {e}",
61        e = in(reg) e,
62        inout("eax") a,
63        in("ebx") b,
64        in("ecx") c,
65        in("edx") d,
66        options(nostack),
67    );
68
69    Error::demux(a)
70}
71
72#[cfg(feature = "userspace")]
73pub unsafe fn syscall5(
74    mut a: usize,
75    b: usize,
76    c: usize,
77    d: usize,
78    e: usize,
79    f: usize,
80) -> Result<usize> {
81    asm!(
82        "xchg esi, {e}
83        int 0x80
84        xchg esi, {e}",
85        e = in(reg) e,
86        inout("eax") a,
87        in("ebx") b,
88        in("ecx") c,
89        in("edx") d,
90        in("edi") f,
91        options(nostack),
92    );
93
94    Error::demux(a)
95}
96
97#[derive(Copy, Clone, Debug, Default)]
98#[repr(C)]
99pub struct IntRegisters {
100    // TODO: Some of these don't get set by Redox yet. Should they?
101    pub ebp: usize,
102    pub esi: usize,
103    pub edi: usize,
104    pub ebx: usize,
105    pub eax: usize,
106    pub ecx: usize,
107    pub edx: usize,
108    // pub orig_rax: usize,
109    pub eip: usize,
110    pub cs: usize,
111    pub eflags: usize,
112    pub esp: usize,
113    pub ss: usize,
114    // pub fs_base: usize,
115    // pub gs_base: usize,
116    // pub ds: usize,
117    // pub es: usize,
118    pub fs: usize,
119    // pub gs: usize
120}
121
122impl Deref for IntRegisters {
123    type Target = [u8];
124    fn deref(&self) -> &[u8] {
125        unsafe {
126            slice::from_raw_parts(
127                self as *const IntRegisters as *const u8,
128                mem::size_of::<IntRegisters>(),
129            )
130        }
131    }
132}
133
134impl DerefMut for IntRegisters {
135    fn deref_mut(&mut self) -> &mut [u8] {
136        unsafe {
137            slice::from_raw_parts_mut(
138                self as *mut IntRegisters as *mut u8,
139                mem::size_of::<IntRegisters>(),
140            )
141        }
142    }
143}
144
145#[derive(Clone, Copy, Debug, Default)]
146#[repr(C, packed)]
147pub struct FloatRegisters {
148    pub fcw: u16,
149    pub fsw: u16,
150    pub ftw: u8,
151    pub _reserved: u8,
152    pub fop: u16,
153    pub fip: u64,
154    pub fdp: u64,
155    pub mxcsr: u32,
156    pub mxcsr_mask: u32,
157    pub st_space: [u128; 8],
158    pub xmm_space: [u128; 16],
159    // TODO: YMM/ZMM
160}
161
162impl Deref for FloatRegisters {
163    type Target = [u8];
164    fn deref(&self) -> &[u8] {
165        unsafe {
166            slice::from_raw_parts(
167                self as *const FloatRegisters as *const u8,
168                mem::size_of::<FloatRegisters>(),
169            )
170        }
171    }
172}
173
174impl DerefMut for FloatRegisters {
175    fn deref_mut(&mut self) -> &mut [u8] {
176        unsafe {
177            slice::from_raw_parts_mut(
178                self as *mut FloatRegisters as *mut u8,
179                mem::size_of::<FloatRegisters>(),
180            )
181        }
182    }
183}
184
185#[derive(Clone, Copy, Debug, Default)]
186#[repr(C, packed)]
187pub struct EnvRegisters {
188    pub fsbase: u32,
189    pub gsbase: u32,
190}
191
192impl Deref for EnvRegisters {
193    type Target = [u8];
194    fn deref(&self) -> &[u8] {
195        unsafe {
196            slice::from_raw_parts(
197                self as *const EnvRegisters as *const u8,
198                mem::size_of::<EnvRegisters>(),
199            )
200        }
201    }
202}
203
204impl DerefMut for EnvRegisters {
205    fn deref_mut(&mut self) -> &mut [u8] {
206        unsafe {
207            slice::from_raw_parts_mut(
208                self as *mut EnvRegisters as *mut u8,
209                mem::size_of::<EnvRegisters>(),
210            )
211        }
212    }
213}