1use alloc::collections::BTreeMap;
2#[allow(unused_imports)] use alloc::vec::Vec;
4use core::fmt;
5
6use memory_addr::{AddrRange, MemoryAddr};
7
8use crate::{MappingBackend, MappingError, MappingResult, MemoryArea};
9
10pub struct MemorySet<B: MappingBackend> {
12 areas: BTreeMap<B::Addr, MemoryArea<B>>,
13}
14
15impl<B: MappingBackend> MemorySet<B> {
16 pub const fn new() -> Self {
18 Self {
19 areas: BTreeMap::new(),
20 }
21 }
22
23 pub fn len(&self) -> usize {
25 self.areas.len()
26 }
27
28 pub fn is_empty(&self) -> bool {
30 self.areas.is_empty()
31 }
32
33 pub fn iter(&self) -> impl Iterator<Item = &MemoryArea<B>> {
35 self.areas.values()
36 }
37
38 pub fn overlaps(&self, range: AddrRange<B::Addr>) -> bool {
40 if let Some((_, before)) = self.areas.range(..range.start).last() {
41 if before.va_range().overlaps(range) {
42 return true;
43 }
44 }
45 if let Some((_, after)) = self.areas.range(range.start..).next() {
46 if after.va_range().overlaps(range) {
47 return true;
48 }
49 }
50 false
51 }
52
53 pub fn find(&self, addr: B::Addr) -> Option<&MemoryArea<B>> {
55 let candidate = self.areas.range(..=addr).last().map(|(_, a)| a);
56 candidate.filter(|a| a.va_range().contains(addr))
57 }
58
59 pub fn find_free_area(
67 &self,
68 hint: B::Addr,
69 size: usize,
70 limit: AddrRange<B::Addr>,
71 ) -> Option<B::Addr> {
72 let mut last_end = hint.max(limit.start);
74 if let Some((_, area)) = self.areas.range(..last_end).last() {
75 last_end = last_end.max(area.end());
76 }
77 for (&addr, area) in self.areas.range(last_end..) {
78 if last_end.checked_add(size).is_some_and(|end| end <= addr) {
79 return Some(last_end);
80 }
81 last_end = area.end();
82 }
83 if last_end
84 .checked_add(size)
85 .is_some_and(|end| end <= limit.end)
86 {
87 Some(last_end)
88 } else {
89 None
90 }
91 }
92
93 pub fn map(
102 &mut self,
103 area: MemoryArea<B>,
104 page_table: &mut B::PageTable,
105 unmap_overlap: bool,
106 ) -> MappingResult {
107 if area.va_range().is_empty() {
108 return Err(MappingError::InvalidParam);
109 }
110
111 if self.overlaps(area.va_range()) {
112 if unmap_overlap {
113 self.unmap(area.start(), area.size(), page_table)?;
114 } else {
115 return Err(MappingError::AlreadyExists);
116 }
117 }
118
119 area.map_area(page_table)?;
120 assert!(self.areas.insert(area.start(), area).is_none());
121 Ok(())
122 }
123
124 pub fn unmap(
131 &mut self,
132 start: B::Addr,
133 size: usize,
134 page_table: &mut B::PageTable,
135 ) -> MappingResult {
136 let range =
137 AddrRange::try_from_start_size(start, size).ok_or(MappingError::InvalidParam)?;
138 if range.is_empty() {
139 return Ok(());
140 }
141
142 let end = range.end;
143
144 self.areas.retain(|_, area| {
146 if area.va_range().contained_in(range) {
147 area.unmap_area(page_table).unwrap();
148 false
149 } else {
150 true
151 }
152 });
153
154 if let Some((&before_start, before)) = self.areas.range_mut(..start).last() {
156 let before_end = before.end();
157 if before_end > start {
158 if before_end <= end {
159 before.shrink_right(start.sub_addr(before_start), page_table)?;
161 } else {
162 let right_part = before.split(end).unwrap();
164 before.shrink_right(start.sub_addr(before_start), page_table)?;
165 assert_eq!(right_part.start().into(), Into::<usize>::into(end));
166 self.areas.insert(end, right_part);
167 }
168 }
169 }
170
171 if let Some((&after_start, after)) = self.areas.range_mut(start..).next() {
173 let after_end = after.end();
174 if after_start < end {
175 let mut new_area = self.areas.remove(&after_start).unwrap();
177 new_area.shrink_left(after_end.sub_addr(end), page_table)?;
178 assert_eq!(new_area.start().into(), Into::<usize>::into(end));
179 self.areas.insert(end, new_area);
180 }
181 }
182
183 Ok(())
184 }
185
186 pub fn clear(&mut self, page_table: &mut B::PageTable) -> MappingResult {
188 for (_, area) in self.areas.iter() {
189 area.unmap_area(page_table)?;
190 }
191 self.areas.clear();
192 Ok(())
193 }
194
195 pub fn protect(
205 &mut self,
206 start: B::Addr,
207 size: usize,
208 update_flags: impl Fn(B::Flags) -> Option<B::Flags>,
209 page_table: &mut B::PageTable,
210 ) -> MappingResult {
211 let end = start.checked_add(size).ok_or(MappingError::InvalidParam)?;
212 let mut to_insert = Vec::new();
213 for (&area_start, area) in self.areas.iter_mut() {
214 let area_end = area.end();
215
216 if let Some(new_flags) = update_flags(area.flags()) {
217 if area_start >= end {
218 break;
221 } else if area_end <= start {
222 } else if area_start >= start && area_end <= end {
226 area.protect_area(new_flags, page_table)?;
229 area.set_flags(new_flags);
230 } else if area_start < start && area_end > end {
231 let right_part = area.split(end).unwrap();
234 area.set_end(start);
235
236 let mut middle_part =
237 MemoryArea::new(start, size, area.flags(), area.backend().clone());
238 middle_part.protect_area(new_flags, page_table)?;
239 middle_part.set_flags(new_flags);
240
241 to_insert.push((right_part.start(), right_part));
242 to_insert.push((middle_part.start(), middle_part));
243 } else if area_end > end {
244 let right_part = area.split(end).unwrap();
247 area.protect_area(new_flags, page_table)?;
248 area.set_flags(new_flags);
249
250 to_insert.push((right_part.start(), right_part));
251 } else {
252 let mut right_part = area.split(start).unwrap();
255 right_part.protect_area(new_flags, page_table)?;
256 right_part.set_flags(new_flags);
257
258 to_insert.push((right_part.start(), right_part));
259 }
260 }
261 }
262 self.areas.extend(to_insert);
263 Ok(())
264 }
265}
266
267impl<B: MappingBackend> fmt::Debug for MemorySet<B>
268where
269 B::Addr: fmt::Debug,
270 B::Flags: fmt::Debug,
271{
272 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
273 f.debug_list().entries(self.areas.values()).finish()
274 }
275}