1use core::fmt::Write;
6
7use crate::registers::bits32::eflags::{EFlags, EFLAGS};
8
9use kernel::process::FunctionCall;
10use kernel::syscall::{ContextSwitchReason, Syscall, SyscallReturn, UserspaceKernelBoundary};
11use kernel::ErrorCode;
12
13use crate::interrupts::{IDT_RESERVED_EXCEPTIONS, SYSCALL_VECTOR};
14use crate::segmentation::{USER_CODE, USER_DATA};
15
16use super::UserContext;
17
18pub struct Boundary;
20
21impl Default for Boundary {
22    fn default() -> Self {
23        Self::new()
24    }
25}
26
27impl Boundary {
28    const MIN_APP_BRK: u32 = 9 * core::mem::size_of::<usize>() as u32;
36
37    pub fn new() -> Self {
39        Self
40    }
41}
42
43impl UserspaceKernelBoundary for Boundary {
44    type StoredState = UserContext;
45
46    fn initial_process_app_brk_size(&self) -> usize {
47        Self::MIN_APP_BRK as usize
48    }
49
50    unsafe fn initialize_process(
51        &self,
52        accessible_memory_start: *const u8,
53        app_brk: *const u8,
54        state: &mut Self::StoredState,
55    ) -> Result<(), ()> {
56        if (app_brk as u32 - accessible_memory_start as u32) < Self::MIN_APP_BRK {
57            return Err(());
58        }
59
60        let esp = (app_brk as u32) - 16;
62
63        let mut eflags = EFlags::new();
64        eflags.0.modify(EFLAGS::FLAGS_IF::SET);
65
66        state.eax = 0;
67        state.ebx = 0;
68        state.ecx = 0;
69        state.edx = 0;
70        state.esi = 0;
71        state.edi = 0;
72        state.ebp = 0;
73        state.esp = esp;
74        state.eip = 0;
75        state.eflags = eflags.0.get();
76        state.cs = USER_CODE.bits() as u32;
77        state.ss = USER_DATA.bits() as u32;
78        state.ds = USER_DATA.bits() as u32;
79        state.es = USER_DATA.bits() as u32;
80        state.fs = USER_DATA.bits() as u32;
81        state.gs = USER_DATA.bits() as u32;
82
83        Ok(())
84    }
85
86    unsafe fn set_syscall_return_value(
87        &self,
88        accessible_memory_start: *const u8,
89        app_brk: *const u8,
90        state: &mut Self::StoredState,
91        return_value: SyscallReturn,
92    ) -> Result<(), ()> {
93        let mut ret0 = 0;
94        let mut ret1 = 0;
95        let mut ret2 = 0;
96        let mut ret3 = 0;
97
98        kernel::utilities::arch_helpers::encode_syscall_return_trd104(
117            &kernel::utilities::arch_helpers::TRD104SyscallReturn::from_syscall_return(
118                return_value,
119            ),
120            &mut ret0,
121            &mut ret1,
122            &mut ret2,
123            &mut ret3,
124        );
125
126        unsafe {
131            state.write_stack(0, ret0, accessible_memory_start, app_brk)?;
132            state.write_stack(1, ret1, accessible_memory_start, app_brk)?;
133            state.write_stack(2, ret2, accessible_memory_start, app_brk)?;
134            state.write_stack(3, ret3, accessible_memory_start, app_brk)?;
135        }
136
137        Ok(())
138    }
139
140    unsafe fn set_process_function(
141        &self,
142        accessible_memory_start: *const u8,
143        app_brk: *const u8,
144        state: &mut Self::StoredState,
145        upcall: FunctionCall,
146    ) -> Result<(), ()> {
147        unsafe {
161            state.write_stack(0, upcall.argument0 as u32, accessible_memory_start, app_brk)?;
162            state.write_stack(1, upcall.argument1 as u32, accessible_memory_start, app_brk)?;
163            state.write_stack(2, upcall.argument2 as u32, accessible_memory_start, app_brk)?;
164            state.write_stack(
165                3,
166                upcall.argument3.as_usize() as u32,
167                accessible_memory_start,
168                app_brk,
169            )?;
170
171            state.push_stack(state.eip, accessible_memory_start, app_brk)?;
172        }
173
174        state.eip = upcall.pc.addr() as u32;
177
178        Ok(())
179    }
180
181    unsafe fn switch_to_process(
182        &self,
183        accessible_memory_start: *const u8,
184        app_brk: *const u8,
185        state: &mut Self::StoredState,
186    ) -> (ContextSwitchReason, Option<*const u8>) {
187        if state.exception != 0 || state.err_code != 0 {
189            let stack_ptr = state.esp as *mut u8;
190            return (ContextSwitchReason::Fault, Some(stack_ptr));
191        }
192
193        let mut err_code = 0;
194        let int_num = unsafe { super::switch_to_user(state, &mut err_code) };
195
196        let reason = match int_num as u8 {
197            0..IDT_RESERVED_EXCEPTIONS => {
198                state.exception = int_num as u8;
199                state.err_code = err_code;
200                ContextSwitchReason::Fault
201            }
202
203            SYSCALL_VECTOR => {
204                let num = state.eax as u8;
205
206                let arg0 =
210                    unsafe { state.read_stack(0, accessible_memory_start, app_brk) }.unwrap_or(0);
211                let arg1 =
212                    unsafe { state.read_stack(1, accessible_memory_start, app_brk) }.unwrap_or(0);
213                let arg2 =
214                    unsafe { state.read_stack(2, accessible_memory_start, app_brk) }.unwrap_or(0);
215                let arg3 =
216                    unsafe { state.read_stack(3, accessible_memory_start, app_brk) }.unwrap_or(0);
217
218                Syscall::from_register_arguments(
219                    num,
220                    arg0 as usize,
221                    (arg1 as usize).into(),
222                    (arg2 as usize).into(),
223                    (arg3 as usize).into(),
224                )
225                .map_or(ContextSwitchReason::Fault, |syscall| {
226                    ContextSwitchReason::SyscallFired { syscall }
227                })
228            }
229            _ => ContextSwitchReason::Interrupted,
230        };
231
232        let stack_ptr = state.esp as *const u8;
233
234        (reason, Some(stack_ptr))
235    }
236
237    unsafe fn print_context(
238        &self,
239        _accessible_memory_start: *const u8,
240        _app_brk: *const u8,
241        state: &Self::StoredState,
242        writer: &mut dyn Write,
243    ) {
244        let _ = writeln!(writer, "{}", state);
245    }
246
247    fn store_context(
248        &self,
249        _state: &Self::StoredState,
250        _out: &mut [u8],
251    ) -> Result<usize, ErrorCode> {
252        unimplemented!()
253    }
254}