kernel/object/capability/memory_mapping/
mod.rs1pub mod syscall;
7
8pub use syscall::{sys_memory_map, sys_memory_unmap};
9
10pub trait MemoryMappingOps: Send + Sync {
17 fn get_mapping_info(
29 &self,
30 offset: usize,
31 length: usize,
32 ) -> Result<(usize, usize, bool), &'static str>;
33
34 fn get_mapping_info_with(
39 &self,
40 offset: usize,
41 length: usize,
42 _is_shared: bool,
43 ) -> Result<(usize, usize, bool), &'static str> {
44 self.get_mapping_info(offset, length)
45 }
46
47 fn on_mapped(&self, vaddr: usize, paddr: usize, length: usize, offset: usize) {}
59
60 fn on_unmapped(&self, vaddr: usize, length: usize) {}
70
71 fn supports_mmap(&self) -> bool {
76 true
77 }
78
79 fn mmap_owner_name(&self) -> alloc::string::String {
85 alloc::string::String::from("object")
86 }
87
88 fn resolve_fault(
90 &self,
91 access: &crate::object::capability::memory_mapping::AccessKind,
92 map: &crate::vm::vmem::VirtualMemoryMap,
93 ) -> core::result::Result<
94 crate::object::capability::memory_mapping::ResolveFaultResult,
95 crate::object::capability::memory_mapping::ResolveFaultError,
96 > {
97 let page_vaddr = access.vaddr & !(crate::environment::PAGE_SIZE - 1);
98 let offset_in_mapping = page_vaddr - map.vmarea.start;
99 Ok(
100 crate::object::capability::memory_mapping::ResolveFaultResult {
101 paddr_page_base: map.pmarea.start + offset_in_mapping,
102 is_tail: false,
103 },
104 )
105 }
106}
107
108#[derive(Clone, Copy, Debug, PartialEq, Eq)]
109pub enum AccessOp {
110 Instruction,
111 Load,
112 Store,
113}
114
115#[derive(Clone, Copy, Debug)]
116pub struct AccessKind {
117 pub op: AccessOp,
118 pub vaddr: usize,
119 pub size: Option<usize>,
120}
121
122#[derive(Clone, Copy, Debug)]
123pub struct ResolveFaultResult {
124 pub paddr_page_base: usize,
125 pub is_tail: bool,
126}
127
128#[derive(Clone, Copy, Debug)]
129pub enum ResolveFaultError {
130 Invalid,
131 Unmapped,
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 struct MockMappableObject {
140 should_fail: bool,
141 mapped_regions: spin::RwLock<alloc::vec::Vec<(usize, usize)>>, }
143
144 impl MockMappableObject {
145 fn new(should_fail: bool) -> Self {
146 MockMappableObject {
147 should_fail,
148 mapped_regions: spin::RwLock::new(alloc::vec::Vec::new()),
149 }
150 }
151 }
152
153 impl MemoryMappingOps for MockMappableObject {
154 fn get_mapping_info(
155 &self,
156 offset: usize,
157 _length: usize,
158 ) -> Result<(usize, usize, bool), &'static str> {
159 if self.should_fail {
160 Err("Mock get_mapping_info failure")
161 } else {
162 Ok((0x80000000 + offset, 0x3, false))
164 }
165 }
166
167 fn on_mapped(&self, vaddr: usize, _paddr: usize, length: usize, _offset: usize) {
168 if !self.should_fail {
169 self.mapped_regions.write().push((vaddr, length));
170 }
171 }
172
173 fn on_unmapped(&self, vaddr: usize, length: usize) {
174 if !self.should_fail {
175 let mut regions = self.mapped_regions.write();
176 if let Some(pos) = regions
177 .iter()
178 .position(|(v, l)| *v == vaddr && *l == length)
179 {
180 regions.remove(pos);
181 }
182 }
183 }
184
185 fn supports_mmap(&self) -> bool {
186 !self.should_fail
187 }
188
189 fn mmap_owner_name(&self) -> alloc::string::String {
190 alloc::string::String::from("mock_object")
191 }
192 }
193
194 #[test_case]
195 fn test_memory_mapping_ops_trait() {
196 let mock_obj = MockMappableObject::new(false);
198
199 assert!(mock_obj.supports_mmap());
201
202 let result = mock_obj.get_mapping_info(1024, 8192);
204 assert!(result.is_ok());
205 let (paddr, permissions, is_shared) = result.unwrap();
206 assert_eq!(paddr, 0x80000400); assert_eq!(permissions, 0x3);
208 assert!(!is_shared);
209
210 mock_obj.on_mapped(0x10000000, 0x80000400, 8192, 1024);
212 assert_eq!(mock_obj.mapped_regions.read().len(), 1);
213 assert_eq!(mock_obj.mapped_regions.read()[0], (0x10000000, 8192));
214
215 mock_obj.on_unmapped(0x10000000, 8192);
217 assert_eq!(mock_obj.mapped_regions.read().len(), 0);
218 }
219
220 #[test_case]
221 fn test_memory_mapping_failure_cases() {
222 let mock_fail_obj = MockMappableObject::new(true);
224
225 assert!(!mock_fail_obj.supports_mmap());
227
228 let result = mock_fail_obj.get_mapping_info(0, 4096);
230 assert!(result.is_err());
231 assert_eq!(result.unwrap_err(), "Mock get_mapping_info failure");
232
233 mock_fail_obj.on_mapped(0x10000000, 0x80000000, 4096, 0);
235 mock_fail_obj.on_unmapped(0x10000000, 4096);
236 }
238}