Skip to main content

ruvix_physmem/
error.rs

1//! Physical memory allocator errors.
2//!
3//! This module defines error types specific to physical memory allocation.
4
5use core::fmt;
6
7use ruvix_types::KernelError;
8
9/// Physical memory allocator errors.
10///
11/// These errors are returned by the buddy allocator when operations fail.
12/// They can be converted to `KernelError` for use in syscall contexts.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub enum PhysMemError {
15    /// No memory available for the requested allocation.
16    OutOfMemory,
17
18    /// The requested allocation size is too large.
19    ///
20    /// The maximum allocation size is 512 pages (2MB).
21    AllocationTooLarge,
22
23    /// The requested allocation size is zero.
24    ZeroAllocation,
25
26    /// The address is not page-aligned.
27    UnalignedAddress,
28
29    /// The address is outside the managed memory range.
30    AddressOutOfRange,
31
32    /// The block at the specified address is not allocated.
33    ///
34    /// This can happen when trying to free memory that was never allocated
35    /// or has already been freed (double-free detection).
36    NotAllocated,
37
38    /// The free operation has an incorrect size.
39    ///
40    /// The size passed to `free_pages` must match the original allocation size.
41    SizeMismatch,
42
43    /// The allocator has not been initialized.
44    NotInitialized,
45
46    /// Invalid order specified (exceeds `MAX_ORDER`).
47    InvalidOrder,
48
49    /// Internal allocator corruption detected.
50    ///
51    /// This indicates a bug in the allocator or memory corruption.
52    InternalCorruption,
53}
54
55impl PhysMemError {
56    /// Returns a human-readable description of the error.
57    #[inline]
58    #[must_use]
59    pub const fn as_str(&self) -> &'static str {
60        match self {
61            Self::OutOfMemory => "Out of physical memory",
62            Self::AllocationTooLarge => "Allocation size exceeds maximum block size",
63            Self::ZeroAllocation => "Cannot allocate zero pages",
64            Self::UnalignedAddress => "Address is not page-aligned",
65            Self::AddressOutOfRange => "Address is outside managed memory range",
66            Self::NotAllocated => "Block is not allocated (possible double-free)",
67            Self::SizeMismatch => "Free size does not match allocation size",
68            Self::NotInitialized => "Allocator has not been initialized",
69            Self::InvalidOrder => "Invalid block order specified",
70            Self::InternalCorruption => "Internal allocator corruption detected",
71        }
72    }
73
74    /// Converts this error to a `KernelError`.
75    ///
76    /// This allows physical memory errors to be propagated through the
77    /// kernel's standard error handling mechanism.
78    #[inline]
79    #[must_use]
80    pub const fn to_kernel_error(self) -> KernelError {
81        match self {
82            Self::OutOfMemory | Self::AllocationTooLarge => KernelError::OutOfMemory,
83            Self::ZeroAllocation | Self::InvalidOrder => KernelError::InvalidArgument,
84            Self::UnalignedAddress | Self::AddressOutOfRange => KernelError::InvalidArgument,
85            Self::NotAllocated | Self::SizeMismatch => KernelError::InvalidArgument,
86            Self::NotInitialized => KernelError::NotPermitted,
87            Self::InternalCorruption => KernelError::InternalError,
88        }
89    }
90}
91
92impl fmt::Display for PhysMemError {
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        write!(f, "{}", self.as_str())
95    }
96}
97
98impl From<PhysMemError> for KernelError {
99    #[inline]
100    fn from(err: PhysMemError) -> Self {
101        err.to_kernel_error()
102    }
103}
104
105#[cfg(feature = "std")]
106impl std::error::Error for PhysMemError {}
107
108#[cfg(test)]
109mod tests {
110    extern crate alloc;
111    use alloc::format;
112    use super::*;
113
114    #[test]
115    fn test_error_as_str() {
116        assert_eq!(PhysMemError::OutOfMemory.as_str(), "Out of physical memory");
117        assert_eq!(
118            PhysMemError::AllocationTooLarge.as_str(),
119            "Allocation size exceeds maximum block size"
120        );
121        assert_eq!(
122            PhysMemError::ZeroAllocation.as_str(),
123            "Cannot allocate zero pages"
124        );
125        assert_eq!(
126            PhysMemError::UnalignedAddress.as_str(),
127            "Address is not page-aligned"
128        );
129    }
130
131    #[test]
132    fn test_to_kernel_error() {
133        assert_eq!(
134            PhysMemError::OutOfMemory.to_kernel_error(),
135            KernelError::OutOfMemory
136        );
137        assert_eq!(
138            PhysMemError::AllocationTooLarge.to_kernel_error(),
139            KernelError::OutOfMemory
140        );
141        assert_eq!(
142            PhysMemError::ZeroAllocation.to_kernel_error(),
143            KernelError::InvalidArgument
144        );
145        assert_eq!(
146            PhysMemError::InternalCorruption.to_kernel_error(),
147            KernelError::InternalError
148        );
149    }
150
151    #[test]
152    fn test_into_kernel_error() {
153        let err: KernelError = PhysMemError::OutOfMemory.into();
154        assert_eq!(err, KernelError::OutOfMemory);
155    }
156
157    #[test]
158    fn test_display() {
159        assert_eq!(format!("{}", PhysMemError::OutOfMemory), "Out of physical memory");
160    }
161
162    #[test]
163    fn test_debug() {
164        assert_eq!(format!("{:?}", PhysMemError::OutOfMemory), "OutOfMemory");
165    }
166}