kernel/vm/
vmem.rs

1use crate::object::capability::memory_mapping::MemoryMappingOps;
2use alloc::sync::Weak;
3
4/// Represents a mapping between physical and virtual memory areas.
5///
6/// This structure defines the relationship between a physical memory area
7/// and its corresponding virtual memory area in the kernel's memory management system.
8///
9/// # Fields
10///
11/// * `pmarea` - The physical memory area that is being mapped
12/// * `vmarea` - The virtual memory area where the physical memory is mapped to
13/// * `permissions` - The access permissions for this mapping
14/// * `is_shared` - Whether this mapping is shared between processes
15/// * `owner` - Optional weak reference to the object that created this mapping (None for anonymous mappings)
16#[derive(Debug, Clone)]
17pub struct VirtualMemoryMap {
18    pub pmarea: MemoryArea,
19    pub vmarea: MemoryArea,
20    pub permissions: usize,
21    pub is_shared: bool,
22    pub owner: Option<Weak<dyn MemoryMappingOps>>,
23}
24
25impl VirtualMemoryMap {
26    /// Creates a new virtual memory map with the given physical and virtual memory areas.
27    ///
28    /// # Arguments
29    /// * `pmarea` - The physical memory area to map
30    /// * `vmarea` - The virtual memory area to map to
31    /// * `permissions` - The permissions to set for the virtual memory area
32    /// * `is_shared` - Whether this memory map should be shared between tasks
33    /// * `owner` - Optional weak reference to the object that created this mapping (None for anonymous mappings)
34    ///
35    /// # Returns
36    /// A new virtual memory map with the given physical and virtual memory areas.
37    pub fn new(
38        pmarea: MemoryArea,
39        vmarea: MemoryArea,
40        permissions: usize,
41        is_shared: bool,
42        owner: Option<Weak<dyn MemoryMappingOps>>,
43    ) -> Self {
44        VirtualMemoryMap {
45            pmarea,
46            vmarea,
47            permissions,
48            is_shared,
49            owner,
50        }
51    }
52
53    /// Returns the physical address corresponding to the given virtual address.
54    ///
55    /// # Arguments
56    /// * `vaddr` - The virtual address to translate
57    ///
58    /// # Returns
59    /// The physical address corresponding to the given virtual address, if it exists.
60    /// If the virtual address is not part of the memory map, `None` is returned.
61    pub fn get_paddr(&self, vaddr: usize) -> Option<usize> {
62        if self.vmarea.start <= vaddr && vaddr <= self.vmarea.end {
63            Some(self.pmarea.start + (vaddr - self.vmarea.start))
64        } else {
65            None
66        }
67    }
68}
69
70#[derive(Debug, Clone, Copy, PartialEq)]
71pub struct MemoryArea {
72    pub start: usize,
73    pub end: usize,
74}
75
76impl MemoryArea {
77    /// Creates a new memory area with the given start and end addresses
78    pub fn new(start: usize, end: usize) -> Self {
79        Self { start, end }
80    }
81
82    /// Creates a new memory area from a pointer and size
83    pub fn from_ptr(ptr: *const u8, size: usize) -> Self {
84        let start = ptr as usize;
85        let end = if size > 0 { start + size - 1 } else { start };
86        Self { start, end }
87    }
88
89    /// Returns the size of the memory area in bytes
90    pub fn size(&self) -> usize {
91        if self.start > self.end {
92            panic!(
93                "Invalid memory area: start > end: {:#x} > {:#x}",
94                self.start, self.end
95            );
96        }
97        self.end - self.start + 1
98    }
99
100    /// Returns a slice reference to the memory area
101    ///
102    /// # Safety
103    /// This function assumes that the start and end of MemoryArea point to valid memory ranges.
104    /// If not, undefined behavior may occur.
105    /// Therefore, make sure that MemoryArea points to a valid range before using this function.
106    ///
107    /// # Returns
108    ///
109    /// A slice reference to the memory area
110    ///
111    pub unsafe fn as_slice(&self) -> &[u8] {
112        unsafe { core::slice::from_raw_parts(self.start as *const u8, self.size()) }
113    }
114
115    /// Returns a mutable slice reference to the memory area
116    ///
117    /// # Safety
118    /// This function assumes that the start and end of MemoryArea point to valid memory ranges.
119    /// If not, undefined behavior may occur.
120    /// Therefore, make sure that MemoryArea points to a valid range before using this function.
121    ///
122    /// # Returns
123    ///
124    /// A mutable slice reference to the memory area
125    ///
126    pub unsafe fn as_slice_mut(&self) -> &mut [u8] {
127        unsafe { core::slice::from_raw_parts_mut(self.start as *mut u8, self.size()) }
128    }
129}
130
131#[derive(Debug, Clone, Copy)]
132pub enum VirtualMemoryPermission {
133    Read = 0x01,
134    Write = 0x02,
135    Execute = 0x04,
136    User = 0x08,
137}
138
139impl From<usize> for VirtualMemoryPermission {
140    fn from(value: usize) -> Self {
141        match value {
142            0x01 => VirtualMemoryPermission::Read,
143            0x02 => VirtualMemoryPermission::Write,
144            0x04 => VirtualMemoryPermission::Execute,
145            0x08 => VirtualMemoryPermission::User,
146            _ => panic!("Invalid permission value: {}", value),
147        }
148    }
149}
150
151impl VirtualMemoryPermission {
152    pub fn contained_in(&self, permissions: usize) -> bool {
153        permissions & (*self as usize) != 0
154    }
155}
156
157pub enum VirtualMemoryRegion {
158    Text,
159    Data,
160    Bss,
161    Heap,
162    Stack,
163    Guard,
164    Unknown,
165}
166
167impl VirtualMemoryRegion {
168    pub fn default_permissions(&self) -> usize {
169        match self {
170            VirtualMemoryRegion::Text => {
171                VirtualMemoryPermission::Read as usize
172                    | VirtualMemoryPermission::Execute as usize
173                    | VirtualMemoryPermission::User as usize
174            }
175            VirtualMemoryRegion::Data => {
176                VirtualMemoryPermission::Read as usize
177                    | VirtualMemoryPermission::Write as usize
178                    | VirtualMemoryPermission::User as usize
179            }
180            VirtualMemoryRegion::Bss => {
181                VirtualMemoryPermission::Read as usize
182                    | VirtualMemoryPermission::Write as usize
183                    | VirtualMemoryPermission::User as usize
184            }
185            VirtualMemoryRegion::Heap => {
186                VirtualMemoryPermission::Read as usize
187                    | VirtualMemoryPermission::Write as usize
188                    | VirtualMemoryPermission::User as usize
189            }
190            VirtualMemoryRegion::Stack => {
191                VirtualMemoryPermission::Read as usize
192                    | VirtualMemoryPermission::Write as usize
193                    | VirtualMemoryPermission::User as usize
194            }
195            VirtualMemoryRegion::Guard => 0, // Any access to the guard page should cause a page fault
196            VirtualMemoryRegion::Unknown => panic!("Unknown memory segment"),
197        }
198    }
199
200    /// Returns whether this memory region should be shared between tasks by default
201    pub fn is_shareable(&self) -> bool {
202        match self {
203            VirtualMemoryRegion::Text => true, // Text segments can be shared (read-only executable code)
204            VirtualMemoryRegion::Data => false, // Data segments should not be shared (writable)
205            VirtualMemoryRegion::Bss => false, // BSS segments should not be shared (writable)
206            VirtualMemoryRegion::Heap => false, // Heap should not be shared (writable)
207            VirtualMemoryRegion::Stack => false, // Stack should not be shared (writable, task-specific)
208            VirtualMemoryRegion::Guard => true,  // Guard pages can be shared (no physical backing)
209            VirtualMemoryRegion::Unknown => false, // Unknown segments should not be shared by default
210        }
211    }
212}