Skip to main content

kernel/
error.rs

1use core::fmt::Display;
2
3use crate::exec::ExecError;
4use crate::fs::FsError;
5use crate::syscall::SysError;
6use crate::virtio_disk::VirtioError;
7use crate::vm::VmError;
8
9/// Kernel error codes.
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum KernelError {
12    Alloc,
13    InvalidArgument,
14    OutOfProc,
15    Vm(VmError),
16    Sys(SysError),
17    Fs(FsError),
18    Exec(ExecError),
19    VirtioError(VirtioError),
20}
21
22impl From<core::alloc::AllocError> for KernelError {
23    fn from(_value: core::alloc::AllocError) -> Self {
24        Self::Alloc
25    }
26}
27
28impl From<VmError> for KernelError {
29    fn from(value: VmError) -> Self {
30        Self::Vm(value)
31    }
32}
33
34impl From<SysError> for KernelError {
35    fn from(value: SysError) -> Self {
36        Self::Sys(value)
37    }
38}
39
40impl From<FsError> for KernelError {
41    fn from(value: FsError) -> Self {
42        Self::Fs(value)
43    }
44}
45
46impl From<ExecError> for KernelError {
47    fn from(value: ExecError) -> Self {
48        Self::Exec(value)
49    }
50}
51
52impl From<VirtioError> for KernelError {
53    fn from(value: VirtioError) -> Self {
54        Self::VirtioError(value)
55    }
56}
57
58impl Display for KernelError {
59    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60        match self {
61            KernelError::Alloc => write!(f, "alloc error"),
62            KernelError::InvalidArgument => write!(f, "invalid argument"),
63            KernelError::OutOfProc => write!(f, "out of proc"),
64            KernelError::Sys(e) => write!(f, "syscall error: {}", e),
65            KernelError::Vm(e) => write!(f, "vm error: {}", e),
66            KernelError::Fs(e) => write!(f, "filesystem error {}", e),
67            KernelError::Exec(e) => write!(f, "exec error {}", e),
68            KernelError::VirtioError(e) => write!(f, "virtio error {}", e),
69        }
70    }
71}
72
73/// Return an error, logging file:line. Use instead of `return Err(...)`.
74#[macro_export]
75macro_rules! err {
76    ($e:expr) => {{
77        #[cfg(debug_assertions)]
78        {
79            let _lock = $crate::proc::lock_current_cpu();
80            #[allow(unused_unsafe)]
81            let cpu_id = unsafe { $crate::proc::current_id() };
82            $crate::println!(
83                "! hart {} errored at {}:{}: {}",
84                cpu_id,
85                file!(),
86                line!(),
87                $e
88            );
89        }
90        return Err($e.into());
91    }};
92}
93
94/// Log error.
95#[macro_export]
96macro_rules! log {
97    ($e:expr) => {
98        match $e {
99            Ok(v) => Ok(v),
100            Err(e) => {
101                #[cfg(debug_assertions)]
102                $crate::println!("  at {}:{}", file!(), line!());
103                Err(e)
104            }
105        }
106    };
107}
108
109/// Propagate error with location logging. Use instead of `?`.
110#[macro_export]
111macro_rules! try_log {
112    ($e:expr) => {
113        match $e {
114            Ok(v) => v,
115            Err(e) => {
116                #[cfg(debug_assertions)]
117                $crate::println!("  at {}:{}", file!(), line!());
118                return Err(e.into());
119            }
120        }
121    };
122}