xref: /DragonOS/kernel/src/mm/memblock.rs (revision 1df85daf8f1b4426fe09d489d815997cdf989a87)
1 use core::intrinsics::unlikely;
2 
3 use system_error::SystemError;
4 
5 use crate::libs::{
6     align::{page_align_down, page_align_up},
7     spinlock::{SpinLock, SpinLockGuard},
8 };
9 
10 use super::{PhysAddr, PhysMemoryArea};
11 
12 pub const INITIAL_MEMORY_REGIONS_NUM: usize = 128;
13 
14 /// 初始内存区域
15 static MEM_BLOCK_MANAGER: MemBlockManager = MemBlockManager::new();
16 
17 #[inline(always)]
18 pub fn mem_block_manager() -> &'static MemBlockManager {
19     &MEM_BLOCK_MANAGER
20 }
21 
22 /// 内存区域管理器
23 #[derive(Debug)]
24 pub struct MemBlockManager {
25     inner: SpinLock<InnerMemBlockManager>,
26 }
27 
28 #[derive(Debug)]
29 pub struct InnerMemBlockManager {
30     /// 初始内存区域
31     ///
32     /// 用于记录内核启动时的内存布局, 这些区域保持升序、不重叠
33     initial_memory_regions: [PhysMemoryArea; INITIAL_MEMORY_REGIONS_NUM],
34     initial_memory_regions_num: usize,
35 }
36 
37 impl MemBlockManager {
38     #[allow(dead_code)]
39     pub const MIN_MEMBLOCK_ADDR: PhysAddr = PhysAddr::new(0);
40     #[allow(dead_code)]
41     pub const MAX_MEMBLOCK_ADDR: PhysAddr = PhysAddr::new(usize::MAX);
42     const fn new() -> Self {
43         Self {
44             inner: SpinLock::new(InnerMemBlockManager {
45                 initial_memory_regions: [PhysMemoryArea::DEFAULT; INITIAL_MEMORY_REGIONS_NUM],
46                 initial_memory_regions_num: 0,
47             }),
48         }
49     }
50 
51     /// 添加内存区域
52     ///
53     /// 如果添加的区域与已有区域有重叠,会将重叠的区域合并
54     #[allow(dead_code)]
55     pub fn add_block(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
56         let r = self.add_range(base, size, MemoryAreaAttr::empty());
57         return r;
58     }
59 
60     /// 添加内存区域
61     ///
62     /// 如果添加的区域与已有区域有重叠,会将重叠的区域合并
63     fn add_range(
64         &self,
65         base: PhysAddr,
66         size: usize,
67         flags: MemoryAreaAttr,
68     ) -> Result<(), SystemError> {
69         if size == 0 {
70             return Ok(());
71         }
72         let mut inner = self.inner.lock();
73         if inner.initial_memory_regions_num >= INITIAL_MEMORY_REGIONS_NUM {
74             panic!("Too many memory regions!");
75         }
76 
77         let block = PhysMemoryArea::new(base, size, MemoryAreaAttr::empty());
78         // 特判第一个区域
79         if inner.initial_memory_regions_num == 0 {
80             inner.initial_memory_regions[0] = block;
81             inner.initial_memory_regions_num += 1;
82             return Ok(());
83         }
84 
85         // 先计算需要添加的区域数量
86         let blocks_to_add = self
87             .do_add_block(&mut inner, block, false, flags)
88             .expect("Failed to count blocks to add!");
89 
90         if inner.initial_memory_regions_num + blocks_to_add > INITIAL_MEMORY_REGIONS_NUM {
91             kerror!("Too many memory regions!");
92             return Err(SystemError::ENOMEM);
93         }
94 
95         // 然后添加区域
96         self.do_add_block(&mut inner, block, true, flags)
97             .expect("Failed to add block!");
98 
99         return Ok(());
100     }
101 
102     fn do_add_block(
103         &self,
104         inner: &mut SpinLockGuard<'_, InnerMemBlockManager>,
105         block: PhysMemoryArea,
106         insert: bool,
107         flags: MemoryAreaAttr,
108     ) -> Result<usize, SystemError> {
109         let mut base = block.base;
110         let end = block.base + block.size;
111         let mut i = 0;
112         let mut start_index = -1;
113         let mut end_index = -1;
114 
115         let mut num_to_add = 0;
116 
117         while i < inner.initial_memory_regions_num {
118             let range_base = inner.initial_memory_regions[i].base;
119             let range_end =
120                 inner.initial_memory_regions[i].base + inner.initial_memory_regions[i].size;
121 
122             if range_base >= end {
123                 break;
124             }
125             if range_end <= base {
126                 i += 1;
127                 continue;
128             }
129 
130             // 有重叠
131 
132             if range_base > base {
133                 num_to_add += 1;
134                 if insert {
135                     if start_index == -1 {
136                         start_index = i as isize;
137                     }
138                     end_index = (i + 1) as isize;
139                     self.do_insert_area(inner, i, base, range_base - base, flags);
140                     i += 1;
141                 }
142             }
143 
144             i += 1;
145             base = core::cmp::min(range_end, end);
146         }
147 
148         if base < end {
149             num_to_add += 1;
150             if insert {
151                 if start_index == -1 {
152                     start_index = i as isize;
153                 }
154                 end_index = (i + 1) as isize;
155                 self.do_insert_area(inner, i, base, end - base, flags);
156             }
157         }
158 
159         if num_to_add == 0 {
160             return Ok(0);
161         }
162 
163         if insert {
164             self.do_merge_blocks(inner, start_index, end_index);
165         }
166         return Ok(num_to_add);
167     }
168 
169     fn do_insert_area(
170         &self,
171         inner: &mut SpinLockGuard<'_, InnerMemBlockManager>,
172         index: usize,
173         base: PhysAddr,
174         size: usize,
175         flags: MemoryAreaAttr,
176     ) {
177         let copy_elements = inner.initial_memory_regions_num - index;
178         inner
179             .initial_memory_regions
180             .copy_within(index..index + copy_elements, index + 1);
181         inner.initial_memory_regions[index] = PhysMemoryArea::new(base, size, flags);
182         inner.initial_memory_regions_num += 1;
183     }
184 
185     fn do_merge_blocks(
186         &self,
187         inner: &mut SpinLockGuard<'_, InnerMemBlockManager>,
188         start_index: isize,
189         mut end_index: isize,
190     ) {
191         let mut i = 0;
192         if start_index > 0 {
193             i = start_index - 1;
194         }
195         end_index = core::cmp::min(end_index, inner.initial_memory_regions_num as isize - 1);
196 
197         while i < end_index {
198             {
199                 let next_base = inner.initial_memory_regions[(i + 1) as usize].base;
200                 let next_size = inner.initial_memory_regions[(i + 1) as usize].size;
201                 let next_flags = inner.initial_memory_regions[(i + 1) as usize].flags;
202                 let this = &mut inner.initial_memory_regions[i as usize];
203 
204                 if this.base + this.size != next_base || this.flags != next_flags {
205                     if unlikely(this.base + this.size > next_base) {
206                         kBUG!("this->base + this->size > next->base");
207                     }
208                     i += 1;
209                     continue;
210                 }
211                 this.size += next_size;
212             }
213             // 移动后面的区域
214             let copy_elements = inner.initial_memory_regions_num - (i + 2) as usize;
215             inner.initial_memory_regions.copy_within(
216                 (i + 2) as usize..(i as usize + 2 + copy_elements),
217                 (i + 1) as usize,
218             );
219 
220             inner.initial_memory_regions_num -= 1;
221             end_index -= 1;
222         }
223     }
224 
225     /// 移除内存区域
226     ///
227     /// 如果移除的区域与已有区域有重叠,会将重叠的区域分割
228     #[allow(dead_code)]
229     pub fn remove_block(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
230         if size == 0 {
231             return Ok(());
232         }
233         let mut inner = self.inner.lock();
234         if inner.initial_memory_regions_num == 0 {
235             return Ok(());
236         }
237 
238         let (start_index, end_index) = self
239             .isolate_range(&mut inner, base, size)
240             .expect("Failed to isolate range!");
241 
242         for i in (start_index..end_index).rev() {
243             self.do_remove_region(&mut inner, i);
244         }
245         return Ok(());
246     }
247 
248     fn do_remove_region(&self, inner: &mut SpinLockGuard<'_, InnerMemBlockManager>, index: usize) {
249         let copy_elements = inner.initial_memory_regions_num - index - 1;
250         inner
251             .initial_memory_regions
252             .copy_within(index + 1..index + 1 + copy_elements, index);
253 
254         inner.initial_memory_regions_num -= 1;
255 
256         if inner.initial_memory_regions_num == 0 {
257             inner.initial_memory_regions[0].base = PhysAddr::new(0);
258             inner.initial_memory_regions[0].size = 0;
259         }
260     }
261 
262     /// 在一个内存块管理器中找到一个物理地址范围内的
263     /// 空闲块,并隔离出所需的内存大小
264     ///
265     /// ## 返回值
266     ///
267     /// - Ok((start_index, end_index)) 表示成功找到了一个连续的内存区域来满足所需的 size。这里:
268     ///     - start_index 是指定的起始内存区域的索引。
269     ///     - end_index 是指定的结束内存区域的索引,它实际上不包含在返回的连续区域中,但它标志着下一个可能的不连续区域的开始。
270     /// - Err(SystemError) 则表示没有找到足够的空间来满足请求的 size,可能是因为内存区域不足或存在其他系统错误
271     fn isolate_range(
272         &self,
273         inner: &mut SpinLockGuard<'_, InnerMemBlockManager>,
274         base: PhysAddr,
275         size: usize,
276     ) -> Result<(usize, usize), SystemError> {
277         let end = base + size;
278 
279         let mut idx = 0;
280 
281         let mut start_index = 0;
282         let mut end_index = 0;
283 
284         if size == 0 {
285             return Ok((0, 0));
286         }
287 
288         while idx < inner.initial_memory_regions_num {
289             let range_base = inner.initial_memory_regions[idx].base;
290             let range_end = range_base + inner.initial_memory_regions[idx].size;
291 
292             if range_base >= end {
293                 break;
294             }
295             if range_end <= base {
296                 idx = idx.checked_add(1).unwrap_or(0);
297                 continue;
298             }
299 
300             if range_base < base {
301                 // regions[idx] intersects from below
302                 inner.initial_memory_regions[idx].base = base;
303                 inner.initial_memory_regions[idx].size -= base - range_base;
304                 self.do_insert_area(
305                     inner,
306                     idx,
307                     range_base,
308                     base - range_base,
309                     inner.initial_memory_regions[idx].flags,
310                 );
311             } else if range_end > end {
312                 // regions[idx] intersects from above
313                 inner.initial_memory_regions[idx].base = end;
314                 inner.initial_memory_regions[idx].size -= end - range_base;
315 
316                 self.do_insert_area(
317                     inner,
318                     idx,
319                     range_base,
320                     end - range_base,
321                     inner.initial_memory_regions[idx].flags,
322                 );
323                 if idx == 0 {
324                     idx = usize::MAX;
325                 } else {
326                     idx -= 1;
327                 }
328             } else {
329                 // regions[idx] is inside the range, record it
330                 if end_index == 0 {
331                     start_index = idx;
332                 }
333                 end_index = idx + 1;
334             }
335 
336             idx = idx.checked_add(1).unwrap_or(0);
337         }
338 
339         return Ok((start_index, end_index));
340     }
341 
342     /// mark_nomap - 用`MemoryAreaAttr::NOMAP`标志标记内存区域
343     ///
344     /// ## 参数
345     ///
346     /// - base: 区域的物理基地址
347     /// - size: 区域的大小
348     ///
349     /// 使用`MemoryAreaAttr::NOMAP`标志标记的内存区域将不会被添加到物理内存的直接映射中。这些区域仍然会被内存映射所覆盖。内存映射中代表NOMAP内存帧的struct page将被PageReserved()。
350     /// 注意:如果被标记为`MemoryAreaAttr::NOMAP`的内存是从memblock分配的,调用者必须忽略该内存
351     pub fn mark_nomap(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
352         return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::NOMAP);
353     }
354 
355     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/mm/memblock.c?fi=memblock_mark_mirror#940
356     pub fn mark_mirror(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
357         return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::MIRROR);
358     }
359 
360     fn set_or_clear_flags(
361         &self,
362         mut base: PhysAddr,
363         mut size: usize,
364         set: bool,
365         flags: MemoryAreaAttr,
366     ) -> Result<(), SystemError> {
367         let rsvd_base = PhysAddr::new(page_align_down(base.data()));
368         size = page_align_up(size + base.data() - rsvd_base.data());
369         base = rsvd_base;
370 
371         let mut inner = self.inner.lock();
372         let (start_index, end_index) = self.isolate_range(&mut inner, base, size)?;
373         for i in start_index..end_index {
374             if set {
375                 inner.initial_memory_regions[i].flags |= flags;
376             } else {
377                 inner.initial_memory_regions[i].flags &= !flags;
378             }
379         }
380 
381         let num = inner.initial_memory_regions_num as isize;
382         self.do_merge_blocks(&mut inner, 0, num);
383         return Ok(());
384     }
385 
386     /// 标记内存区域为保留区域
387     pub fn reserve_block(&self, base: PhysAddr, size: usize) -> Result<(), SystemError> {
388         return self.set_or_clear_flags(base, size, true, MemoryAreaAttr::RESERVED);
389     }
390 
391     /// 判断[base, base+size)与已有区域是否有重叠
392     pub fn is_overlapped(&self, base: PhysAddr, size: usize) -> bool {
393         let inner = self.inner.lock();
394         return self.do_is_overlapped(base, size, false, &inner);
395     }
396 
397     /// 判断[base, base+size)与已有Reserved区域是否有重叠
398     pub fn is_overlapped_with_reserved(&self, base: PhysAddr, size: usize) -> bool {
399         let inner = self.inner.lock();
400         return self.do_is_overlapped(base, size, true, &inner);
401     }
402 
403     fn do_is_overlapped(
404         &self,
405         base: PhysAddr,
406         size: usize,
407         require_reserved: bool,
408         inner: &SpinLockGuard<'_, InnerMemBlockManager>,
409     ) -> bool {
410         let mut res = false;
411         for i in 0..inner.initial_memory_regions_num {
412             if require_reserved
413                 && !inner.initial_memory_regions[i]
414                     .flags
415                     .contains(MemoryAreaAttr::RESERVED)
416             {
417                 // 忽略非保留区域
418                 continue;
419             }
420 
421             let range_base = inner.initial_memory_regions[i].base;
422             let range_end = range_base + inner.initial_memory_regions[i].size;
423             if (base >= range_base && base < range_end)
424                 || (base + size > range_base && base + size <= range_end)
425                 || (base <= range_base && base + size >= range_end)
426             {
427                 res = true;
428                 break;
429             }
430         }
431 
432         return res;
433     }
434 
435     /// 生成迭代器
436     pub fn to_iter(&self) -> MemBlockIter {
437         let inner = self.inner.lock();
438         return MemBlockIter {
439             inner,
440             index: 0,
441             usable_only: false,
442         };
443     }
444 
445     /// 生成迭代器,迭代所有可用的物理内存区域
446     pub fn to_iter_available(&self) -> MemBlockIter {
447         let inner = self.inner.lock();
448         return MemBlockIter {
449             inner,
450             index: 0,
451             usable_only: true,
452         };
453     }
454 
455     /// 获取初始内存区域数量
456     pub fn total_initial_memory_regions(&self) -> usize {
457         let inner = self.inner.lock();
458         return inner.initial_memory_regions_num;
459     }
460 
461     /// 根据索引获取初始内存区域
462     pub fn get_initial_memory_region(&self, index: usize) -> Option<PhysMemoryArea> {
463         let inner = self.inner.lock();
464         return inner.initial_memory_regions.get(index).copied();
465     }
466 }
467 
468 pub struct MemBlockIter<'a> {
469     inner: SpinLockGuard<'a, InnerMemBlockManager>,
470     index: usize,
471     usable_only: bool,
472 }
473 
474 #[allow(dead_code)]
475 impl<'a> MemBlockIter<'a> {
476     /// 获取内存区域数量
477     pub fn total_num(&self) -> usize {
478         self.inner.initial_memory_regions_num
479     }
480 
481     /// 获取指定索引的内存区域
482     pub fn get_area(&self, index: usize) -> &PhysMemoryArea {
483         &self.inner.initial_memory_regions[index]
484     }
485 
486     /// 获取当前索引
487     pub fn current_index(&self) -> usize {
488         self.index
489     }
490 }
491 
492 impl<'a> Iterator for MemBlockIter<'a> {
493     type Item = PhysMemoryArea;
494 
495     fn next(&mut self) -> Option<Self::Item> {
496         while self.index < self.inner.initial_memory_regions_num {
497             if self.usable_only
498                 && !self.inner.initial_memory_regions[self.index]
499                     .flags
500                     .is_empty()
501             {
502                 self.index += 1;
503                 if self.index >= self.inner.initial_memory_regions_num {
504                     return None;
505                 }
506                 continue;
507             }
508             break;
509         }
510         if self.index >= self.inner.initial_memory_regions_num {
511             return None;
512         }
513         let ret = self.inner.initial_memory_regions[self.index];
514         self.index += 1;
515         return Some(ret);
516     }
517 }
518 
519 bitflags! {
520     /// 内存区域属性
521     #[allow(clippy::bad_bit_mask)]
522     pub struct MemoryAreaAttr: u32 {
523         /// No special request
524         const NONE = 0x0;
525         /// Hotpluggable region
526         const HOTPLUG = (1 << 0);
527         /// Mirrored region
528         const MIRROR = (1 << 1);
529         /// do not add to kenrel direct mapping
530         const NOMAP = (1 << 2);
531         /// Always detected via a driver
532         const DRIVER_MANAGED = (1 << 3);
533         /// Memory is reserved
534         const RESERVED = (1 << 4);
535     }
536 }
537