rust_kernel_rt/
syscall.rs1use core::{hint::unreachable_unchecked, mem::MaybeUninit};
2
3use arrayvec::ArrayString;
4use rust_kernel_shared_consts::{DirChild, Fd, PATH_MAX, SYSCALL_CLOSE, SYSCALL_EXEC, SYSCALL_EXIT, SYSCALL_GET_CHAR, SYSCALL_GET_CWD, SYSCALL_GET_DIR_CHILDREN, SYSCALL_OPEN, SYSCALL_PRINT, SYSCALL_SBRK, SYSCALL_SHUTDOWN, SYSCALL_STAT, SYSCALL_WAIT_PID, Stat};
5
6pub unsafe fn syscall0(syscall_nb : u64) -> u64 {
7 let ret : u64;
8 unsafe {
9 core::arch::asm!(
10 "int 0x80",
11 inlateout("rax") syscall_nb => ret,
12 options(nostack)
13 );
14 }
15 ret
16}
17
18pub unsafe fn syscall1(syscall_nb : u64, arg1 : u64) -> u64 {
19 let ret : u64;
20 unsafe {
21 core::arch::asm!(
22 "int 0x80",
23 inlateout("rax") syscall_nb => ret,
24 in("rdi") arg1,
25 options(nostack)
26 );
27 }
28 ret
29}
30
31pub unsafe fn syscall2(syscall_nb : u64, arg1 : u64, arg2 : u64) -> u64 {
32 let ret : u64;
33 unsafe {
34 core::arch::asm!(
35 "int 0x80",
36 inlateout("rax") syscall_nb => ret,
37 in("rdi") arg1,
38 in("rsi") arg2,
39 options(nostack)
40 );
41 }
42 ret
43}
44
45pub unsafe fn syscall3(syscall_nb : u64, arg1 : u64, arg2 : u64, arg3 : u64) -> u64 {
46 let ret : u64;
47 unsafe {
48 core::arch::asm!(
49 "int 0x80",
50 inlateout("rax") syscall_nb => ret,
51 in("rdi") arg1,
52 in("rsi") arg2,
53 in("rdx") arg3,
54 options(nostack)
55 );
56 }
57 ret
58}
59
60pub fn syscall_exit(status : i32) -> ! {
61 unsafe {
62 syscall1(SYSCALL_EXIT, status as u64);
63 unreachable_unchecked()
64 }
65}
66
67fn str_to_ptr_and_len(s : &str) -> (u64, u64) {
68 (s.as_ptr() as u64, s.len() as u64)
69}
70
71pub fn syscall_print(message : &str) -> Option<()> {
72 let (message_ptr, message_len) = str_to_ptr_and_len(message);
73 unsafe {
74 let res = syscall2(SYSCALL_PRINT, message_ptr, message_len);
75 if res == u64::MAX {
76 return None;
77 }
78 Some(())
79 }
80}
81
82pub fn syscall_exec(path : &str) -> u64 {
83 let (path_ptr, path_len) = str_to_ptr_and_len(path);
84 unsafe {
85 syscall2(SYSCALL_EXEC, path_ptr, path_len)
86 }
87}
88
89pub fn syscall_get_char() -> char {
90 unsafe {
91 let c_u32 = syscall0(SYSCALL_GET_CHAR).try_into().unwrap();
92 char::from_u32_unchecked(c_u32)
93 }
94}
95
96pub fn syscall_wait_pid(pid : u64){
97 unsafe {
98 syscall1(SYSCALL_WAIT_PID, pid);
99 }
100}
101
102pub fn syscall_stat(path : &str) -> Option<Stat> {
103 let (path_ptr, path_len) = str_to_ptr_and_len(path);
104 let mut stat = MaybeUninit::uninit();
105 let ret = unsafe {
106 syscall3(SYSCALL_STAT, path_ptr, path_len, stat.as_mut_ptr() as u64)
107 };
108 match ret {
109 u64::MAX => None,
110 _ => unsafe { Some(stat.assume_init()) }
111 }
112}
113
114pub fn syscall_open(path : &str, mode : u64) -> Option<Fd> {
115 let (path_ptr, path_len) = str_to_ptr_and_len(path);
116 let ret = unsafe {
117 syscall3(SYSCALL_OPEN, path_ptr, path_len, mode)
118 };
119 match ret {
120 u64::MAX => None,
121 _ => Some(Fd(ret as usize))
122 }
123}
124
125pub fn syscall_close(fd : Fd) -> Option<()> {
126 let fd = fd.0 as u64;
127 let ret = unsafe {
128 syscall1(SYSCALL_CLOSE, fd)
129 };
130
131 match ret {
132 u64::MAX => None,
133 _ => Some(()),
134 }
135}
136
137pub fn syscall_get_cwd() -> Option<ArrayString<PATH_MAX>> {
138 let mut ret = ArrayString::new();
139 let ret_ptr = ret.as_ptr() as u64;
140 let ret_len = ret.capacity() as u64;
141 let ret_syscall = unsafe {
142 syscall2(SYSCALL_GET_CWD, ret_ptr, ret_len)
143 };
144 match ret_syscall {
145 u64::MAX => None,
146 len => {
147 unsafe {
148 ret.set_len(len as usize);
149 }
150 Some(ret)
151 },
152 }
153}
154
155pub fn syscall_get_dir_children(fd : Fd, children : &mut [DirChild]) -> Option<usize> {
156 let fd = fd.0 as u64;
157 let children_ptr = children.as_mut_ptr() as u64;
158 let children_len = children.len() as u64;
159
160 let ret = unsafe {
161 syscall3(SYSCALL_GET_DIR_CHILDREN, fd, children_ptr, children_len)
162 };
163
164 match ret {
165 u64::MAX => None,
166 ret => {
167 Some(ret as usize)
168 }
169 }
170}
171
172pub fn syscall_sbrk(increment : u64) -> Option<u64> {
173 let ret = unsafe {
174 syscall1(SYSCALL_SBRK, increment)
175 };
176 match ret {
177 u64::MAX => None,
178 ret => Some(ret),
179 }
180}
181
182pub fn syscall_shutdown(flags : u64) -> ! {
183 unsafe {
184 syscall1(SYSCALL_SHUTDOWN, flags);
185 }
186 panic!("shutdown syscall failed")
187}