1pub const SYS_CTL: u8 = 1;
10pub const SYS_MEM: u8 = 2;
11pub const SYS_CPU: u8 = 3;
12
13use crate::ErrorCode;
14
15#[derive(Debug)]
18pub struct SyscallResult {
19 pub result: u64, pub data: [u64; 6], }
22
23impl SyscallResult {
24 pub const F_TIMED_OUT: u64 = 0x01_00_00;
26 pub const F_HANDLE_ARRAY: u64 = 0x_02_00_00;
27
28 pub fn is_ok(&self) -> bool {
29 ((self.result & 0xFF_FF) as u16) == ErrorCode::Ok as u16
30 }
31
32 pub fn timed_out(&self) -> bool {
33 (self.result & Self::F_TIMED_OUT) != 0
34 }
35
36 pub fn error_code(&self) -> ErrorCode {
37 ErrorCode::from_u16((self.result & 0xFF_FF) as u16)
38 }
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
43#[repr(C, align(8))]
44pub struct SysHandle(u64);
45
46const _: () = assert!(core::mem::size_of::<SysHandle>() == 8);
47
48impl SysHandle {
49 pub const NONE: SysHandle = SysHandle(0);
51 pub const KERNEL: SysHandle = SysHandle(1);
52 pub const SELF: SysHandle = SysHandle(2); pub const CURR: SysHandle = SysHandle(3); pub const PARENT: SysHandle = SysHandle(4); pub const IO_MAN: SysHandle = SysHandle(5); pub const fn from_u64(val: u64) -> Self {
58 SysHandle(val)
59 }
60 pub const fn as_u64(&self) -> u64 {
61 self.0
62 }
63 pub const fn is_none(&self) -> bool {
64 self.as_u64() == Self::NONE.as_u64()
65 }
66}
67
68#[cfg(feature = "userspace")]
70pub struct RaiiHandle(u64);
71
72#[cfg(feature = "userspace")]
73impl Drop for RaiiHandle {
74 fn drop(&mut self) {
75 if self.0 != 0 {
76 SysCtl::put(self.syshandle()).unwrap()
77 }
78 }
79}
80
81#[cfg(feature = "userspace")]
82impl RaiiHandle {
83 pub const fn syshandle(&self) -> SysHandle {
84 SysHandle(self.0)
85 }
86
87 pub const fn from(handle: SysHandle) -> Self {
88 Self(handle.0)
89 }
90
91 pub fn take(mut self) -> SysHandle {
92 let result = SysHandle(self.0);
93 self.0 = 0;
94 result
95 }
96}
97
98pub struct SysCtl;
99
100#[cfg(feature = "userspace")]
101fn pack_nr_ver(syscall_number: u8, operation: u8, flags: u32, version: u16) -> u64 {
102 ((syscall_number as u64) << 56)
103 | ((operation as u64) << 48)
104 | ((flags as u64) << 16)
105 | (version as u64)
106}
107
108impl SysCtl {
109 pub const OP_GET: u8 = 1;
110 pub const OP_PUT: u8 = 2;
111 pub const OP_CREATE: u8 = 3;
112 pub const OP_QUERY_PROCESS: u8 = 4;
113 pub const OP_SET_LOG_LEVEL: u8 = 5;
114
115 pub const F_QUERY_STATUS: u32 = 1;
116 pub const F_QUERY_LIST: u32 = 2;
117 pub const F_QUERY_LIST_CHILDREN: u32 = 3;
118
119 pub const F_WAKE_PEER: u32 = 1;
121
122 #[cfg(feature = "userspace")]
138 pub fn create(parent: SysHandle, flags: u32, url: &str) -> Result<SysHandle, ErrorCode> {
139 let bytes = url.as_bytes();
140
141 let result = do_syscall(
142 pack_nr_ver(SYS_CTL, Self::OP_CREATE, flags, 0),
143 parent.as_u64(),
144 bytes.as_ptr() as usize as u64,
145 bytes.len() as u64,
146 0,
147 0,
148 0,
149 );
150 if result.is_ok() {
151 Ok(SysHandle(result.data[0]))
152 } else {
153 Err(result.error_code())
154 }
155 }
156
157 #[cfg(feature = "userspace")]
165 pub fn create_ipc_pair(
166 process1: SysHandle,
167 process2: SysHandle,
168 flags: u32,
169 ) -> Result<(SysHandle, SysHandle), ErrorCode> {
170 let bytes = "ipc_pair".as_bytes();
171 let result = do_syscall(
172 pack_nr_ver(SYS_CTL, Self::OP_CREATE, flags, 0),
173 process1.as_u64(),
174 bytes.as_ptr() as usize as u64,
175 bytes.len() as u64,
176 process2.as_u64(),
177 0,
178 0,
179 );
180 if result.is_ok() {
181 Ok((SysHandle(result.data[0]), SysHandle(result.data[1])))
182 } else {
183 Err(result.error_code())
184 }
185 }
186
187 #[cfg(feature = "userspace")]
188 pub fn get(parent: SysHandle, flags: u32, url: &str) -> Result<SysHandle, ErrorCode> {
189 let res = Self::get_res1(parent, flags, url)?;
190 Ok(res.0)
191 }
192
193 #[cfg(feature = "userspace")]
194 pub fn get_res1(
195 parent: SysHandle,
196 flags: u32,
197 url: &str,
198 ) -> Result<(SysHandle, u64), ErrorCode> {
199 let bytes = url.as_bytes();
200
201 let result = do_syscall(
202 pack_nr_ver(SYS_CTL, Self::OP_GET, flags, 0),
203 parent.as_u64(),
204 bytes.as_ptr() as usize as u64,
205 bytes.len() as u64,
206 0,
207 0,
208 0,
209 );
210 if result.is_ok() {
211 Ok((SysHandle(result.data[0]), result.data[1]))
212 } else {
213 Err(result.error_code())
214 }
215 }
216
217 #[cfg(feature = "userspace")]
218 pub fn put(handle: SysHandle) -> Result<(), ErrorCode> {
219 Self::put_1(handle, 0)
220 }
221
222 #[cfg(feature = "userspace")]
223 pub fn put_1(handle: SysHandle, arg: u64) -> Result<(), ErrorCode> {
224 Self::put_remote_1(SysHandle::SELF, handle, arg)
225 }
226
227 #[cfg(feature = "userspace")]
228 pub fn put_remote(owner_process: SysHandle, handle: SysHandle) -> Result<(), ErrorCode> {
229 Self::put_remote_1(owner_process, handle, 0)
230 }
231
232 #[cfg(feature = "userspace")]
233 pub fn put_remote_1(
234 owner_process: SysHandle,
235 handle: SysHandle,
236 arg: u64,
237 ) -> Result<(), ErrorCode> {
238 let result = do_syscall(
239 pack_nr_ver(SYS_CTL, Self::OP_PUT, 0, 0),
240 owner_process.as_u64(),
241 handle.as_u64(),
242 arg,
243 0,
244 0,
245 0,
246 );
247 if result.is_ok() {
248 Ok(())
249 } else {
250 Err(result.error_code())
251 }
252 }
253
254 #[cfg(feature = "userspace")]
256 pub fn set_log_level(level: u8) -> Result<u8, ErrorCode> {
257 let result = do_syscall(
258 pack_nr_ver(SYS_CTL, Self::OP_SET_LOG_LEVEL, 0, 0),
259 level as u64,
260 0,
261 0,
262 0,
263 0,
264 0,
265 );
266 if result.is_ok() {
267 Ok(result.data[0] as u8)
268 } else {
269 Err(result.error_code())
270 }
271 }
272
273 #[cfg(feature = "userspace")]
274 pub fn process_status(handle: SysHandle) -> Result<Option<u64>, ErrorCode> {
275 let result = do_syscall(
276 pack_nr_ver(SYS_CTL, Self::OP_QUERY_PROCESS, Self::F_QUERY_STATUS, 0),
277 handle.as_u64(),
278 0,
279 0,
280 0,
281 0,
282 0,
283 );
284
285 if result.is_ok() {
286 Ok(Some(result.data[0]))
287 } else {
288 if result.error_code() == ErrorCode::AlreadyInUse {
289 Ok(None)
290 } else {
291 Err(ErrorCode::NotFound)
292 }
293 }
294 }
295
296 #[cfg(feature = "userspace")]
297 pub fn list_processes_v1(
298 pid: u64,
299 flat_list: bool,
300 buf: &mut [super::stats::ProcessStatsV1],
301 ) -> Result<usize, ErrorCode> {
302 if buf.len() < 1 {
303 return Err(ErrorCode::InvalidArgument);
304 }
305
306 let flags = if flat_list {
307 Self::F_QUERY_LIST
308 } else {
309 Self::F_QUERY_LIST_CHILDREN
310 };
311 let result = do_syscall(
312 pack_nr_ver(SYS_CTL, Self::OP_QUERY_PROCESS, flags, 1),
313 pid,
314 buf.as_mut_ptr() as usize as u64,
315 buf.len() as u64,
316 0,
317 0,
318 0,
319 );
320
321 if result.is_ok() {
322 Ok(result.data[0] as usize)
323 } else {
324 Err(result.error_code())
325 }
326 }
327}
328
329#[cfg(feature = "userspace")]
332pub fn do_syscall(
333 nr_ver: u64,
334 arg0: u64,
335 arg1: u64,
336 arg2: u64,
337 arg3: u64,
338 arg4: u64,
339 arg5: u64,
340) -> SyscallResult {
341 use core::arch::asm;
342
343 let mut val0 = arg0;
344 let mut val1 = arg1;
345 let mut val2 = arg2;
346 let mut val3 = arg3;
347 let mut val4 = arg4;
348 let mut val5 = arg5;
349 let mut rax = nr_ver;
350
351 unsafe {
352 asm!(
353 "syscall",
354 inout("rax") rax,
355 inout("rdi") val0,
356 inout("rsi") val1,
357 inout("rdx") val2,
358 inout("r10") val3,
359 inout("r8" ) val4,
360 inout("r9" ) val5,
361 lateout("rcx") _,
362 lateout("r11") _,
363 )
364 };
365
366 let mut data: [u64; 6] = [0; 6];
367 data[0] = val0;
368 data[1] = val1;
369 data[2] = val2;
370 data[3] = val3;
371 data[4] = val4;
372 data[5] = val5;
373
374 SyscallResult { result: rax, data }
375}
376
377pub struct SysMem;
378
379impl SysMem {
380 pub const OP_CREATE: u8 = 1;
382 pub const OP_GET: u8 = 2;
383 pub const OP_PUT: u8 = 3;
384 pub const OP_MAP: u8 = 4;
385 pub const OP_UNMAP: u8 = 5;
386 pub const OP_REMAP: u8 = 6;
387 pub const OP_QUERY: u8 = 7;
388 pub const OP_DEBUG: u8 = 8;
389 pub const OP_RECLAIM: u8 = 9;
390
391 pub const F_READABLE: u32 = 1;
393 pub const F_WRITABLE: u32 = 2;
394 pub const F_MMIO: u32 = 4;
395 pub const F_CONTIGUOUS: u32 = 8;
396 pub const F_SHARE_SELF: u32 = 0x10;
397
398 pub const F_LAZY: u32 = 0x20;
402
403 pub const F_LOG_UTF8: u32 = 1; pub const F_QUERY_STATS: u32 = 1;
407
408 pub const PAGE_SIZE_SMALL: u64 = 4096;
410 pub const PAGE_SIZE_MID: u64 = 4096 * 512;
411 pub const PAGE_SIZE_LARGE: u64 = 4096 * 512 * 512;
412
413 pub const PAGE_SIZE_SMALL_LOG2: u64 = 12;
414 pub const PAGE_SIZE_MID_LOG2: u64 = 21;
415 pub const PAGE_SIZE_LARGE_LOG2: u64 = 30;
416
417 pub const PAGE_TYPE_SMALL: u64 = 1;
418 pub const PAGE_TYPE_MID: u64 = 2;
419 pub const PAGE_TYPE_LARGE: u64 = 3;
420
421 pub const MAX_ADDRESS_SPACE_SIZE_LOG2: u64 = 46;
422
423 #[cfg(feature = "userspace")]
424 pub fn map(
425 address_space: SysHandle,
426 flags: u32,
427 phys_addr: u64,
428 virt_addr: u64,
429 page_size: u64,
430 num_pages: u64,
431 ) -> Result<u64, ErrorCode> {
432 debug_assert_ne!(num_pages, 0);
433 let result = do_syscall(
434 pack_nr_ver(SYS_MEM, Self::OP_MAP, flags, 0),
435 address_space.as_u64(),
436 phys_addr,
437 virt_addr,
438 page_size,
439 num_pages,
440 0,
441 );
442 if result.is_ok() {
443 Ok(result.data[0])
444 } else {
445 Err(result.error_code())
446 }
447 }
448
449 #[cfg(feature = "userspace")]
450 pub fn map2(
451 address_space: SysHandle,
452 flags: u32,
453 phys_addr: u64,
454 virt_addr: u64,
455 page_size: u64,
456 num_pages: u64,
457 ) -> Result<(u64, u64), ErrorCode> {
458 debug_assert_ne!(num_pages, 0);
459 let result = do_syscall(
460 pack_nr_ver(SYS_MEM, Self::OP_MAP, flags, 0),
461 address_space.as_u64(),
462 phys_addr,
463 virt_addr,
464 page_size,
465 num_pages,
466 0,
467 );
468 if result.is_ok() {
469 Ok((result.data[0], result.data[1]))
470 } else {
471 Err(result.error_code())
472 }
473 }
474 #[cfg(feature = "userspace")]
475 pub fn unmap(
476 address_space: SysHandle,
477 flags: u32,
478 phys_addr: u64,
479 virt_addr: u64,
480 ) -> Result<(), ErrorCode> {
481 let result = do_syscall(
482 pack_nr_ver(SYS_MEM, Self::OP_UNMAP, flags, 0),
483 address_space.as_u64(),
484 phys_addr,
485 virt_addr,
486 0,
487 0,
488 0,
489 );
490
491 if result.is_ok() {
492 Ok(())
493 } else {
494 Err(result.error_code())
495 }
496 }
497
498 #[cfg(feature = "userspace")]
499 pub fn virt_to_phys(virt_addr: u64) -> Result<u64, ErrorCode> {
500 let result = do_syscall(
501 pack_nr_ver(SYS_MEM, Self::OP_QUERY, 0, 0),
502 SysHandle::SELF.as_u64(),
503 u64::MAX,
504 virt_addr,
505 0,
506 0,
507 0,
508 );
509
510 if result.is_ok() {
511 Ok(result.data[0])
512 } else {
513 Err(result.error_code())
514 }
515 }
516
517 #[cfg(feature = "userspace")]
518 pub fn alloc(page_size: u64, num_pages: u64) -> Result<u64, ErrorCode> {
519 assert!(
520 page_size == Self::PAGE_SIZE_SMALL
521 || page_size == Self::PAGE_SIZE_MID
522 || page_size == Self::PAGE_SIZE_LARGE
523 );
524 assert_ne!(num_pages, 0);
525 Self::map(
526 SysHandle::SELF,
527 Self::F_READABLE | Self::F_WRITABLE,
528 u64::MAX,
529 u64::MAX,
530 page_size,
531 num_pages,
532 )
533 }
534
535 #[cfg(feature = "userspace")]
537 pub fn alloc_contiguous_pages(size: u64) -> Result<u64, ErrorCode> {
538 assert_ne!(size, 0);
539 if size > 20 * Self::PAGE_SIZE_MID {
540 return Err(ErrorCode::InvalidArgument);
541 }
542 let (page_size, page_size_log_2) = if size > (Self::PAGE_SIZE_MID >> 1) {
543 (Self::PAGE_SIZE_MID, Self::PAGE_SIZE_MID_LOG2)
544 } else {
545 (Self::PAGE_SIZE_SMALL, Self::PAGE_SIZE_SMALL_LOG2)
546 };
547
548 let size = super::align_up(size, page_size);
549 Self::map(
550 SysHandle::SELF,
551 Self::F_READABLE | Self::F_WRITABLE | Self::F_CONTIGUOUS,
552 u64::MAX,
553 u64::MAX,
554 page_size,
555 size >> page_size_log_2,
556 )
557 }
558
559 #[cfg(feature = "userspace")]
560 pub fn free(virt_addr: u64) -> Result<(), ErrorCode> {
561 Self::unmap(SysHandle::SELF, 0, u64::MAX, virt_addr)
562 }
563
564 #[cfg(feature = "userspace")]
565 pub fn mmio_map(phys_addr: u64, size: u64) -> Result<u64, ErrorCode> {
566 assert_eq!(0, size & (Self::PAGE_SIZE_SMALL - 1));
567 Self::map(
568 SysHandle::SELF,
569 Self::F_READABLE | Self::F_WRITABLE | Self::F_MMIO,
570 phys_addr,
571 u64::MAX,
572 Self::PAGE_SIZE_SMALL,
573 size >> Self::PAGE_SIZE_SMALL_LOG2,
574 )
575 }
576
577 #[cfg(feature = "userspace")]
578 pub fn log(msg: &str) -> Result<(), ErrorCode> {
579 let bytes = msg.as_bytes();
580 if bytes.len() == 0 {
581 return Err(ErrorCode::InvalidArgument);
582 }
583
584 let res = do_syscall(
585 pack_nr_ver(SYS_MEM, Self::OP_DEBUG, Self::F_LOG_UTF8, 0),
586 SysHandle::SELF.as_u64(),
587 0,
588 msg.as_bytes().as_ptr() as usize as u64,
589 0,
590 0,
591 bytes.len() as u64,
592 );
593
594 if res.is_ok() {
595 Ok(())
596 } else {
597 Err(res.error_code())
598 }
599 }
600
601 #[cfg(feature = "userspace")]
602 pub fn query_stats() -> Result<super::stats::MemoryStats, ErrorCode> {
603 use crate::stats::MemoryStats;
604
605 let mut stats = MemoryStats::default();
606
607 let res = do_syscall(
608 pack_nr_ver(SYS_MEM, Self::OP_QUERY, Self::F_QUERY_STATS, 0),
609 SysHandle::NONE.as_u64(),
610 &mut stats as *mut _ as usize as u64,
611 0,
612 0,
613 0,
614 0,
615 );
616
617 if res.is_ok() {
618 Ok(stats)
619 } else {
620 Err(res.error_code())
621 }
622 }
623
624 #[cfg(feature = "userspace")]
625 pub fn reclaim(handle: SysHandle) -> Result<(), ErrorCode> {
626 let res = do_syscall(
627 pack_nr_ver(SYS_MEM, Self::OP_RECLAIM, 0, 0),
628 handle.as_u64(),
629 0,
630 0,
631 0,
632 0,
633 0,
634 );
635
636 if res.is_ok() {
637 Ok(())
638 } else {
639 Err(res.error_code())
640 }
641 }
642}
643
644pub struct SysCpu;
645
646impl SysCpu {
647 pub const OP_EXIT: u8 = 1;
648 pub const OP_WAIT: u8 = 2;
649 pub const OP_WAKE: u8 = 3;
650 pub const OP_KILL: u8 = 4;
651 pub const OP_SPAWN: u8 = 5;
652 pub const OP_USAGE: u8 = 6;
653 pub const OP_AFFINE_CPU: u8 = 7;
654
655 pub const F_HANDLE_ARRAY: u32 = 1;
657 pub const F_TIMEOUT: u32 = 2; pub const F_DONTBLOCK: u32 = 4;
661
662 pub const F_SWAP_TARGET: u32 = 8;
664
665 pub const F_WAKE_TARGET: u32 = 16;
667
668 #[cfg(feature = "userspace")]
669 pub fn exit(code: u64) -> ! {
670 do_syscall(
671 pack_nr_ver(SYS_CPU, Self::OP_EXIT, 0, 0),
672 code,
673 0,
674 0,
675 0,
676 0,
677 0,
678 );
679 unreachable!();
680 }
681
682 #[cfg(feature = "userspace")]
683 pub fn kill(target: SysHandle) -> Result<(), ErrorCode> {
684 let result = do_syscall(
685 pack_nr_ver(SYS_CPU, Self::OP_KILL, 0, 0),
686 target.as_u64(),
687 0,
688 0,
689 0,
690 0,
691 0,
692 );
693
694 if result.is_ok() {
695 Ok(())
696 } else {
697 Err(result.error_code())
698 }
699 }
700
701 #[cfg(feature = "userspace")]
702 pub fn wake(target: SysHandle) -> Result<(), ErrorCode> {
703 let result = do_syscall(
704 pack_nr_ver(SYS_CPU, Self::OP_WAKE, 0, 0),
705 target.as_u64(),
706 0,
707 0,
708 0,
709 0,
710 0,
711 );
712
713 if result.is_ok() {
714 Ok(())
715 } else {
716 Err(result.error_code())
717 }
718 }
719
720 #[cfg(feature = "userspace")]
729 pub fn wait(
730 wait_handles: &mut [SysHandle],
731 swap_target: SysHandle,
732 wake_target: SysHandle,
733 timeout: Option<crate::time::Instant>,
734 ) -> Result<(), ErrorCode> {
735 let mut flags: u32 = 0;
741 let mut next_arg: usize = 0;
742 let mut args = [0_u64; 6];
743
744 if let Some(timeout) = timeout {
745 if timeout.is_nan() {
746 flags |= Self::F_DONTBLOCK;
747 } else {
748 flags |= Self::F_TIMEOUT;
749 args[next_arg] = timeout.as_u64();
750 next_arg += 1;
751 }
752 }
753
754 if swap_target != SysHandle::NONE {
755 if wake_target != SysHandle::NONE {
756 return Err(ErrorCode::InvalidArgument);
757 }
758 flags |= Self::F_SWAP_TARGET;
759 args[next_arg] = swap_target.as_u64();
760 next_arg += 1;
761 } else if wake_target != SysHandle::NONE {
762 flags |= Self::F_WAKE_TARGET;
763 args[next_arg] = wake_target.as_u64();
764 next_arg += 1;
765 }
766
767 if wait_handles.len() > (args.len() - next_arg) {
768 flags |= Self::F_HANDLE_ARRAY;
769 args[next_arg] = wait_handles.as_ptr() as usize as u64;
770 args[next_arg + 1] = wait_handles.len() as u64;
771 } else {
772 for idx in 0..wait_handles.len() {
773 args[next_arg] = wait_handles[idx].as_u64();
774 next_arg += 1;
775 }
776 }
777
778 let result = do_syscall(
779 pack_nr_ver(SYS_CPU, Self::OP_WAIT, flags, 1),
780 args[0],
781 args[1],
782 args[2],
783 args[3],
784 args[4],
785 args[5],
786 );
787
788 Self::process_result(&result, wait_handles)
789 }
790
791 #[cfg(feature = "userspace")]
792 fn process_result(result: &SyscallResult, handles: &mut [SysHandle]) -> Result<(), ErrorCode> {
793 if result.result & SyscallResult::F_HANDLE_ARRAY == 0 {
795 for idx in 0..handles.len() {
796 if idx < 6 {
797 handles[idx] = SysHandle::from_u64(result.data[idx]);
798 } else {
799 handles[idx] = SysHandle::NONE;
800 }
801 }
802 }
803
804 if result.is_ok() {
805 Ok(())
806 } else {
807 Err(result.error_code())
808 }
809 }
810
811 #[cfg(feature = "userspace")]
812 pub fn spawn(
813 process: SysHandle,
814 stack_start: u64,
815 thread_fn: u64,
816 thread_arg: u64,
817 ) -> Result<SysHandle, ErrorCode> {
818 let result = do_syscall(
819 pack_nr_ver(SYS_CPU, Self::OP_SPAWN, 0, 0),
820 process.as_u64(),
821 stack_start,
822 thread_fn,
823 thread_arg,
824 0,
825 0,
826 );
827
828 if result.is_ok() {
829 Ok(SysHandle::from_u64(result.data[0]))
830 } else {
831 Err(result.error_code())
832 }
833 }
834
835 #[cfg(feature = "userspace")]
836 pub fn sched_yield() {
837 Self::wait(
839 &mut [],
840 SysHandle::NONE,
841 SysHandle::NONE,
842 Some(crate::time::Instant::nan()),
843 )
844 .unwrap();
845 }
846
847 #[cfg(feature = "userspace")]
848 pub fn query_stats(buf: &mut [f32]) -> Result<(), ErrorCode> {
849 let result = do_syscall(
850 pack_nr_ver(SYS_CPU, Self::OP_USAGE, 0, 0),
851 buf.as_ptr() as usize as u64,
852 buf.len() as u64,
853 0,
854 0,
855 0,
856 0,
857 );
858
859 if result.is_ok() {
860 Ok(())
861 } else {
862 Err(result.error_code())
863 }
864 }
865
866 #[cfg(feature = "userspace")]
869 pub fn affine_to_cpu(cpu: Option<u32>) -> Result<(), ErrorCode> {
870 let result = do_syscall(
871 pack_nr_ver(SYS_CPU, Self::OP_AFFINE_CPU, 0, 0),
872 match cpu {
873 Some(cpu) => cpu as u64,
874 None => u64::MAX,
875 },
876 0,
877 0,
878 0,
879 0,
880 0,
881 );
882
883 if result.is_ok() {
884 Ok(())
885 } else {
886 Err(result.error_code())
887 }
888 }
889}