1use alloc::vec::Vec;
16use core::str;
17
18use crate::abi::{AbiRegistry, MAX_ABI_LENGTH};
19use crate::device::manager::DeviceManager;
20use crate::fs::{File, VfsManager, MAX_PATH_LENGTH};
21use crate::task::elf_loader::load_elf_into_task;
22
23use crate::arch::{get_cpu, vm, Registers, Trapframe};
24use crate::print;
25use crate::sched::scheduler::get_scheduler;
26use crate::task::WaitError;
27use crate::vm::{setup_user_stack, setup_trampoline};
28
29use super::mytask;
30
31pub fn sys_brk(trapframe: &mut Trapframe) -> usize {
32 let task = mytask().unwrap();
33 let brk = trapframe.get_arg(0);
34 trapframe.epc += 4;
35 match task.set_brk(brk) {
36 Ok(_) => task.get_brk(),
37 Err(_) => usize::MAX, }
39}
40
41pub fn sys_sbrk(trapframe: &mut Trapframe) -> usize {
42 let task = mytask().unwrap();
43 let increment = trapframe.get_arg(0);
44 let brk = task.get_brk();
45 trapframe.epc += 4;
46 match task.set_brk(unsafe { brk.unchecked_add(increment) }) {
47 Ok(_) => brk,
48 Err(_) => usize::MAX, }
50}
51
52pub fn sys_putchar(trapframe: &mut Trapframe) -> usize {
53 let c = trapframe.get_arg(0) as u32;
54 trapframe.epc += 4;
55 if let Some(ch) = char::from_u32(c) {
56 print!("{}", ch);
57 } else {
58 return usize::MAX; }
60 0
61}
62
63pub fn sys_getchar(trapframe: &mut Trapframe) -> usize {
64 let serial = DeviceManager::get_mut_manager().basic.borrow_mut_serial(0).unwrap();
65 trapframe.epc += 4;
66
67 if let Some(byte) = serial.get() {
68 byte as usize
69 } else {
70 0 }
72}
73
74pub fn sys_exit(trapframe: &mut Trapframe) -> usize {
75 let task = mytask().unwrap();
76 task.vcpu.store(trapframe);
77 let exit_code = trapframe.get_arg(0) as i32;
78 task.exit(exit_code);
79 get_scheduler().schedule(get_cpu());
80 trapframe.get_arg(0) as usize
81}
82
83pub fn sys_clone(trapframe: &mut Trapframe) -> usize {
84 let parent_task = mytask().unwrap();
85
86 trapframe.epc += 4; parent_task.vcpu.store(trapframe);
90
91 match parent_task.clone_task() {
93 Ok(mut child_task) => {
94 let child_id = child_task.get_id();
95 child_task.vcpu.regs.reg[10] = 0; get_scheduler().add_task(child_task, get_cpu().get_cpuid());
97 child_id
99 },
100 Err(_) => {
101 usize::MAX }
103 }
104}
105
106pub fn sys_execve(trapframe: &mut Trapframe) -> usize {
107 let task = mytask().unwrap();
108 let path_ptr = task.vm_manager.translate_vaddr(trapframe.get_arg(0)).unwrap() as *const u8;
110
111 trapframe.epc += 4;
121
122 let task = mytask().unwrap();
124
125 let mut backup_pages = Vec::new();
127 backup_pages.append(&mut task.managed_pages); let backup_vm_mapping = task.vm_manager.remove_all_memory_maps(); let backup_text_size = task.text_size;
132 let backup_data_size = task.data_size;
133
134 let mut path_bytes = Vec::new();
136 let mut i = 0;
137 unsafe {
138 loop {
139 let byte = *path_ptr.add(i);
140 if byte == 0 {
141 break;
142 }
143 path_bytes.push(byte);
144 i += 1;
145
146 if i > MAX_PATH_LENGTH {
148 task.managed_pages = backup_pages; task.vm_manager.restore_memory_maps(backup_vm_mapping).unwrap(); task.text_size = backup_text_size; task.data_size = backup_data_size; return usize::MAX; }
155 }
156 }
157
158 let path_str = match str::from_utf8(&path_bytes) {
160 Ok(s) => match VfsManager::to_absolute_path(&task, s) {
161 Ok(path) => path,
162 Err(_) => {
163 task.managed_pages = backup_pages; task.vm_manager.restore_memory_maps(backup_vm_mapping).unwrap(); task.text_size = backup_text_size; task.data_size = backup_data_size; return usize::MAX; }
170 },
171 Err(_) => {
172 task.managed_pages = backup_pages; task.vm_manager.restore_memory_maps(backup_vm_mapping).unwrap(); task.text_size = backup_text_size; task.data_size = backup_data_size; return usize::MAX },
179 };
180
181 if task.vfs.is_none() {
183 task.managed_pages = backup_pages; task.vm_manager.restore_memory_maps(backup_vm_mapping).unwrap(); task.text_size = backup_text_size; task.data_size = backup_data_size; return usize::MAX; }
190
191 let file = match task.vfs.as_ref() {
193 Some(vfs) => vfs.open(&path_str, 0),
194 None => {
195 task.managed_pages = backup_pages; task.vm_manager.restore_memory_maps(backup_vm_mapping).unwrap(); task.text_size = backup_text_size; task.data_size = backup_data_size; return usize::MAX; }
202 };
203 if file.is_err() {
204 task.managed_pages = backup_pages; task.vm_manager.restore_memory_maps(backup_vm_mapping).unwrap(); task.text_size = backup_text_size; task.data_size = backup_data_size; return usize::MAX; }
211 let mut file = file.unwrap();
212
213 task.text_size = 0;
214 task.data_size = 0;
215 task.stack_size = 0;
216
217 match load_elf_into_task(&mut file, task) {
219 Ok(entry_point) => {
220 task.name = path_str;
222 let idx = vm::get_root_page_table_idx(task.vm_manager.get_asid()).unwrap();
224 let root_page_table = vm::get_page_table(idx).unwrap();
225 root_page_table.unmap_all();
226 setup_trampoline(&mut task.vm_manager);
228 let stack_pointer = setup_user_stack(task);
230
231 task.set_entry_point(entry_point as usize);
233
234 task.vcpu.regs = Registers::new();
236 task.vcpu.set_sp(stack_pointer);
238
239 task.vcpu.switch(trapframe);
241
242 0
244 },
245 Err(_) => {
246 task.managed_pages = backup_pages; task.vm_manager.restore_memory_maps(backup_vm_mapping).unwrap(); task.text_size = backup_text_size; task.data_size = backup_data_size; usize::MAX
254 }
255 }
256}
257
258pub fn sys_execve_abi(trapframe: &mut Trapframe) -> usize {
259 let task = mytask().unwrap();
260 trapframe.epc += 4;
261
262 let abi_str_ptr = task.vm_manager.translate_vaddr(trapframe.get_arg(3)).unwrap() as *const u8;
263 let mut abi_bytes = Vec::new();
264 let mut i = 0;
265 unsafe {
266 loop {
267 let byte = *abi_str_ptr.add(i);
268 if byte == 0 {
269 break;
270 }
271 abi_bytes.push(byte);
272 i += 1;
273
274 if i > MAX_ABI_LENGTH {
276 trapframe.epc += 4;
277 return usize::MAX; }
279 }
280 }
281 let abi_str = match str::from_utf8(&abi_bytes) {
283 Ok(s) => s,
284 Err(_) => return usize::MAX, };
286 let abi = AbiRegistry::instantiate(abi_str);
287 if abi.is_none() {
288 trapframe.epc += 4;
289 return usize::MAX; }
291 let backup_abi = task.abi.take();
292 task.abi = abi;
293
294 let res = sys_execve(trapframe);
295 if res == usize::MAX {
296 task.abi = backup_abi;
298 }
299 res
300}
301
302pub fn sys_waitpid(trapframe: &mut Trapframe) -> usize {
303 let task = mytask().unwrap();
304 let pid = trapframe.get_arg(0) as i32;
305 let status_ptr = trapframe.get_arg(1) as *mut i32;
306 let _options = trapframe.get_arg(2) as i32; if pid == -1 {
309 for pid in task.get_children().clone() {
310 match task.wait(pid) {
311 Ok(status) => {
312 if status_ptr != core::ptr::null_mut() {
314 let status_ptr = task.vm_manager.translate_vaddr(status_ptr as usize).unwrap() as *mut i32;
315 unsafe {
316 *status_ptr = status;
317 }
318 }
319 trapframe.epc += 4;
320 return pid;
321 },
322 Err(error) => {
323 match error {
324 WaitError::ChildNotExited(_) => continue,
325 _ => {
326 trapframe.epc += 4;
327 return usize::MAX;
328 },
329 }
330 }
331 }
332 }
333 trapframe.epc += 4;
335 return usize::MAX;
336 }
337
338 match task.wait(pid as usize) {
339 Ok(status) => {
340 if status_ptr != core::ptr::null_mut() {
342 let status_ptr = task.vm_manager.translate_vaddr(status_ptr as usize).unwrap() as *mut i32;
343 unsafe {
344 *status_ptr = status;
345 }
346 }
347 trapframe.epc += 4;
348 pid as usize
349 }
350 Err(error) => {
351 match error {
352 WaitError::NoSuchChild(_) => {
353 trapframe.epc += 4;
354 usize::MAX
355 },
356 WaitError::ChildTaskNotFound(_) => {
357 trapframe.epc += 4;
358 usize::MAX
359 },
360 WaitError::ChildNotExited(_) => {
361 get_scheduler().schedule(trapframe);
363 trapframe.get_return_value()
364 },
365 }
366 }
367 }
368}
369
370pub fn sys_getpid(trapframe: &mut Trapframe) -> usize {
371 let task = mytask().unwrap();
372 trapframe.epc += 4;
373 task.get_id() as usize
374}
375
376pub fn sys_getppid(trapframe: &mut Trapframe) -> usize {
377 let task = mytask().unwrap();
378 trapframe.epc += 4;
379 task.get_parent_id().unwrap_or(task.get_id()) as usize
380}