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/// Size of the metadata region used to transfer information from the kernel to the bootstrapper.
12pub const KERNEL_METADATA_SIZE: usize = 4 * PAGE_SIZE;
13
14#[cfg(feature = "userspace")]
15macro_rules! syscall {
16    ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
17        $(
18            pub unsafe fn $name(mut $a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result<usize> {
19                asm!(
20                    "int 0x80",
21                    inout("eax") $a,
22                    $(
23                        in("ebx") $b,
24                        $(
25                            in("ecx") $c,
26                            $(
27                                in("edx") $d,
28                                $(
29                                    in("esi") $e,
30                                    $(
31                                        in("edi") $f,
32                                    )?
33                                )?
34                            )?
35                        )?
36                    )?
37                    options(nostack),
38                );
39
40                Error::demux($a)
41            }
42        )+
43    };
44}
45
46#[cfg(feature = "userspace")]
47syscall! {
48    syscall0(a,);
49    syscall1(a, b,);
50    syscall2(a, b, c,);
51    syscall3(a, b, c, d,);
52    // Must be done custom because LLVM reserves ESI
53    //syscall4(a, b, c, d, e,);
54    //syscall5(a, b, c, d, e, f,);
55    //syscall6(a, b, c, d, e, f, g,);
56}
57
58#[cfg(feature = "userspace")]
59pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
60    asm!(
61        "xchg esi, {e}
62        int 0x80
63        xchg esi, {e}",
64        e = in(reg) e,
65        inout("eax") a,
66        in("ebx") b,
67        in("ecx") c,
68        in("edx") d,
69        options(nostack),
70    );
71
72    Error::demux(a)
73}
74
75#[cfg(feature = "userspace")]
76pub unsafe fn syscall5(
77    mut a: usize,
78    b: usize,
79    c: usize,
80    d: usize,
81    e: usize,
82    f: usize,
83) -> Result<usize> {
84    asm!(
85        "xchg esi, {e}
86        int 0x80
87        xchg esi, {e}",
88        e = in(reg) e,
89        inout("eax") a,
90        in("ebx") b,
91        in("ecx") c,
92        in("edx") d,
93        in("edi") f,
94        options(nostack),
95    );
96
97    Error::demux(a)
98}
99
100#[cfg(feature = "userspace")]
101pub unsafe fn syscall6(
102    mut a: usize,
103    b: usize,
104    c: usize,
105    d: usize,
106    e: usize,
107    f: usize,
108    g: usize,
109) -> Result<usize> {
110    #[repr(C)]
111    struct PackedArgs {
112        arg4: usize,
113        arg6: usize,
114        nr: usize,
115    }
116    let args = PackedArgs {
117        arg4: e,
118        arg6: g,
119        nr: a,
120    };
121    let args_ptr = &args as *const PackedArgs;
122    asm!(
123        "push ebp",
124        "push esi",
125        "mov esi, [eax + 0]", // arg4 -> esi
126        "mov ebp, [eax + 4]", // arg6 -> ebp
127        "mov eax, [eax + 8]", // nr -> eax
128        "int 0x80",
129        "pop esi",
130        "pop ebp",
131        inout("eax") args_ptr => a,
132        in("ebx") b,
133        in("ecx") c,
134        in("edx") d,
135        in("edi") f,
136        options(nostack),
137    );
138
139    Error::demux(a)
140}
141
142#[derive(Copy, Clone, Debug, Default)]
143#[repr(C)]
144pub struct IntRegisters {
145    // TODO: Some of these don't get set by Redox yet. Should they?
146    pub ebp: usize,
147    pub esi: usize,
148    pub edi: usize,
149    pub ebx: usize,
150    pub eax: usize,
151    pub ecx: usize,
152    pub edx: usize,
153    // pub orig_rax: usize,
154    pub eip: usize,
155    pub cs: usize,
156    pub eflags: usize,
157    pub esp: usize,
158    pub ss: usize,
159    // pub fs_base: usize,
160    // pub gs_base: usize,
161    // pub ds: usize,
162    // pub es: usize,
163    pub fs: usize,
164    // pub gs: usize
165}
166
167impl Deref for IntRegisters {
168    type Target = [u8];
169    fn deref(&self) -> &[u8] {
170        unsafe {
171            slice::from_raw_parts(
172                self as *const IntRegisters as *const u8,
173                mem::size_of::<IntRegisters>(),
174            )
175        }
176    }
177}
178
179impl DerefMut for IntRegisters {
180    fn deref_mut(&mut self) -> &mut [u8] {
181        unsafe {
182            slice::from_raw_parts_mut(
183                self as *mut IntRegisters as *mut u8,
184                mem::size_of::<IntRegisters>(),
185            )
186        }
187    }
188}
189
190#[derive(Clone, Copy, Debug, Default)]
191#[repr(C, packed)]
192pub struct FloatRegisters {
193    pub fcw: u16,
194    pub fsw: u16,
195    pub ftw: u8,
196    pub _reserved: u8,
197    pub fop: u16,
198    pub fip: u64,
199    pub fdp: u64,
200    pub mxcsr: u32,
201    pub mxcsr_mask: u32,
202    pub st_space: [u128; 8],
203    pub xmm_space: [u128; 16],
204    // TODO: YMM/ZMM
205}
206
207impl Deref for FloatRegisters {
208    type Target = [u8];
209    fn deref(&self) -> &[u8] {
210        unsafe {
211            slice::from_raw_parts(
212                self as *const FloatRegisters as *const u8,
213                mem::size_of::<FloatRegisters>(),
214            )
215        }
216    }
217}
218
219impl DerefMut for FloatRegisters {
220    fn deref_mut(&mut self) -> &mut [u8] {
221        unsafe {
222            slice::from_raw_parts_mut(
223                self as *mut FloatRegisters as *mut u8,
224                mem::size_of::<FloatRegisters>(),
225            )
226        }
227    }
228}
229
230#[derive(Clone, Copy, Debug, Default)]
231#[repr(C, packed)]
232pub struct EnvRegisters {
233    pub fsbase: u32,
234    pub gsbase: u32,
235}
236
237impl Deref for EnvRegisters {
238    type Target = [u8];
239    fn deref(&self) -> &[u8] {
240        unsafe {
241            slice::from_raw_parts(
242                self as *const EnvRegisters as *const u8,
243                mem::size_of::<EnvRegisters>(),
244            )
245        }
246    }
247}
248
249impl DerefMut for EnvRegisters {
250    fn deref_mut(&mut self) -> &mut [u8] {
251        unsafe {
252            slice::from_raw_parts_mut(
253                self as *mut EnvRegisters as *mut u8,
254                mem::size_of::<EnvRegisters>(),
255            )
256        }
257    }
258}
259
260#[derive(Clone, Copy, Debug, Default)]
261#[repr(C, packed)]
262pub struct Exception {
263    pub kind: usize,
264    pub code: usize,
265    pub address: usize,
266}
267impl Deref for Exception {
268    type Target = [u8];
269    fn deref(&self) -> &[u8] {
270        unsafe {
271            slice::from_raw_parts(
272                self as *const Exception as *const u8,
273                mem::size_of::<Exception>(),
274            )
275        }
276    }
277}
278
279impl DerefMut for Exception {
280    fn deref_mut(&mut self) -> &mut [u8] {
281        unsafe {
282            slice::from_raw_parts_mut(
283                self as *mut Exception as *mut u8,
284                mem::size_of::<Exception>(),
285            )
286        }
287    }
288}