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}