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}