xref: /DragonOS/kernel/src/mm/allocator/bump.rs (revision b5b571e02693d91eb6918d3b7561e088c3e7ee81)
140fe15e0SLoGin /// @Auther: Kong
240fe15e0SLoGin /// @Date: 2023-03-27 06:54:08
340fe15e0SLoGin /// @FilePath: /DragonOS/kernel/src/mm/allocator/bump.rs
440fe15e0SLoGin /// @Description: bump allocator线性分配器
540fe15e0SLoGin use super::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
6453452ccSLoGin use crate::mm::{
7453452ccSLoGin     allocator::page_frame::{PhysPageFrame, PhysPageFrameIter},
8453452ccSLoGin     init::{mm_init_status, MMInitStatus},
9453452ccSLoGin     memblock::mem_block_manager,
10453452ccSLoGin     no_init::pseudo_map_phys,
11453452ccSLoGin     page::PageMapper,
12453452ccSLoGin     MemoryManagementArch, PageTableKind, PhysAddr, PhysMemoryArea,
13453452ccSLoGin };
1440fe15e0SLoGin use core::marker::PhantomData;
1540fe15e0SLoGin 
1640fe15e0SLoGin /// 线性分配器
1740fe15e0SLoGin pub struct BumpAllocator<MMA> {
1840fe15e0SLoGin     // 表示当前分配的物理内存的偏移量.
1940fe15e0SLoGin     offset: usize,
2040fe15e0SLoGin     // 一个占位类型,用于标记 A 类型在结构体中的存在。但是,它并不会占用任何内存空间,因为它的大小为 0。
2140fe15e0SLoGin     phantom: PhantomData<MMA>,
2240fe15e0SLoGin }
2340fe15e0SLoGin 
2440fe15e0SLoGin /// 为BumpAllocator实现FrameAllocator
2540fe15e0SLoGin impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
2640fe15e0SLoGin     /// @brief: 创建一个线性分配器
2740fe15e0SLoGin     /// @param Fareas 当前的内存区域
2840fe15e0SLoGin     /// @param offset 当前的偏移量
2940fe15e0SLoGin     /// @return 分配器本身
new(offset: usize) -> Self3045626c85SLoGin     pub fn new(offset: usize) -> Self {
3140fe15e0SLoGin         Self {
3240fe15e0SLoGin             offset,
3340fe15e0SLoGin             phantom: PhantomData,
3440fe15e0SLoGin         }
3540fe15e0SLoGin     }
3645626c85SLoGin 
3740fe15e0SLoGin     // @brief 获取当前分配的物理内存的偏移量
offset(&self) -> usize3840fe15e0SLoGin     pub fn offset(&self) -> usize {
3940fe15e0SLoGin         return self.offset;
4040fe15e0SLoGin     }
4199dbf38dSLoGin 
4299dbf38dSLoGin     /// 返回剩余的尚未被分配的物理内存区域
4399dbf38dSLoGin     ///
4499dbf38dSLoGin     /// ## 返回值
4599dbf38dSLoGin     ///
4699dbf38dSLoGin     /// - `result_area`:剩余的尚未被分配的物理内存区域的数组
4799dbf38dSLoGin     /// - `offset_aligned`:返回的第一个物理内存区域内,已经分配的偏移量(相对于物理内存区域的已对齐的起始地址)
remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option<usize>4899dbf38dSLoGin     pub fn remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option<usize> {
4999dbf38dSLoGin         let mut offset = self.offset();
5099dbf38dSLoGin 
51453452ccSLoGin         let iter = mem_block_manager().to_iter_available();
52453452ccSLoGin 
5399dbf38dSLoGin         let mut ret_offset_aligned = 0;
5499dbf38dSLoGin 
5599dbf38dSLoGin         let mut res_cnt = 0;
5699dbf38dSLoGin 
57453452ccSLoGin         let mut found_start = false;
5899dbf38dSLoGin         // 遍历所有的物理内存区域
59453452ccSLoGin         for area in iter {
60*b5b571e0SLoGin             if !found_start {
6199dbf38dSLoGin                 // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
6299dbf38dSLoGin                 // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
6399dbf38dSLoGin                 let area_base = area.area_base_aligned().data();
6499dbf38dSLoGin                 // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整
6599dbf38dSLoGin                 // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
6699dbf38dSLoGin                 let area_end = area.area_end_aligned().data();
6799dbf38dSLoGin 
6899dbf38dSLoGin                 // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域
6999dbf38dSLoGin                 if offset >= area_end {
7099dbf38dSLoGin                     continue;
7199dbf38dSLoGin                 }
7299dbf38dSLoGin 
7399dbf38dSLoGin                 // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base
7499dbf38dSLoGin                 if offset < area_base {
7599dbf38dSLoGin                     offset = area_base;
7699dbf38dSLoGin                 } else if offset < area_end {
7799dbf38dSLoGin                     // 将offset对齐到PAGE_SIZE
7899dbf38dSLoGin                     offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
7999dbf38dSLoGin                 }
8099dbf38dSLoGin                 // found
81*b5b571e0SLoGin                 if offset + MMA::PAGE_SIZE <= area_end {
82453452ccSLoGin                     ret_offset_aligned = offset - area.area_base_aligned().data();
83453452ccSLoGin                     found_start = true;
84453452ccSLoGin                 }
85453452ccSLoGin             }
86453452ccSLoGin 
87*b5b571e0SLoGin             if found_start && area.area_base_aligned() < area.area_end_aligned() {
88453452ccSLoGin                 result_area[res_cnt] = area;
8999dbf38dSLoGin                 res_cnt += 1;
9099dbf38dSLoGin             }
9199dbf38dSLoGin         }
9299dbf38dSLoGin 
9399dbf38dSLoGin         let res_cnt = unsafe { Self::arch_remain_areas(result_area, res_cnt) };
9499dbf38dSLoGin         if res_cnt == 0 {
9599dbf38dSLoGin             return None;
9699dbf38dSLoGin         } else {
9799dbf38dSLoGin             return Some(ret_offset_aligned);
9899dbf38dSLoGin         }
9999dbf38dSLoGin     }
100453452ccSLoGin 
101453452ccSLoGin     #[inline(never)]
ensure_early_mapping(&self, start_paddr: PhysAddr, count: PageFrameCount)102453452ccSLoGin     unsafe fn ensure_early_mapping(&self, start_paddr: PhysAddr, count: PageFrameCount) {
103453452ccSLoGin         // 确保在内存管理未被初始化时,这地址已经被映射了
104453452ccSLoGin         if mm_init_status() != MMInitStatus::Initialized {
105453452ccSLoGin             // 映射涉及的页
106453452ccSLoGin 
107453452ccSLoGin             let iter = PhysPageFrameIter::new(
108453452ccSLoGin                 PhysPageFrame::new(start_paddr),
109453452ccSLoGin                 PhysPageFrame::new(start_paddr + count.bytes()),
110453452ccSLoGin             );
111453452ccSLoGin             let mapper =
112453452ccSLoGin                 PageMapper::<MMA, _>::current(PageTableKind::Kernel, BumpAllocator::<MMA>::new(0));
113453452ccSLoGin 
114453452ccSLoGin             for p in iter {
115*b5b571e0SLoGin                 if mapper
116*b5b571e0SLoGin                     .translate(MMA::phys_2_virt(p.phys_address()).unwrap())
117*b5b571e0SLoGin                     .is_none()
118*b5b571e0SLoGin                 {
119453452ccSLoGin                     let vaddr = MMA::phys_2_virt(p.phys_address()).unwrap();
120453452ccSLoGin                     pseudo_map_phys(vaddr, p.phys_address(), PageFrameCount::new(1));
121453452ccSLoGin                 }
122453452ccSLoGin             }
123453452ccSLoGin         }
124453452ccSLoGin     }
12540fe15e0SLoGin }
12640fe15e0SLoGin 
12740fe15e0SLoGin impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
12840fe15e0SLoGin     /// @brief: 分配count个物理页帧
12940fe15e0SLoGin     /// @param  mut self
13040fe15e0SLoGin     /// @param  count 分配的页帧数量
13140fe15e0SLoGin     /// @return 分配后的物理地址
allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)>13240fe15e0SLoGin     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
13340fe15e0SLoGin         let mut offset = self.offset();
13445626c85SLoGin 
135453452ccSLoGin         let iter = mem_block_manager().to_iter_available();
13645626c85SLoGin 
13740fe15e0SLoGin         // 遍历所有的物理内存区域
13845626c85SLoGin         for area in iter {
13940fe15e0SLoGin             // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
14040fe15e0SLoGin             // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
14199dbf38dSLoGin             let area_base = area.area_base_aligned().data();
14240fe15e0SLoGin             // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整
14340fe15e0SLoGin             // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
14499dbf38dSLoGin             let area_end = area.area_end_aligned().data();
14540fe15e0SLoGin 
14640fe15e0SLoGin             // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域
14740fe15e0SLoGin             if offset >= area_end {
14840fe15e0SLoGin                 continue;
14940fe15e0SLoGin             }
15040fe15e0SLoGin 
15140fe15e0SLoGin             // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base
15240fe15e0SLoGin             if offset < area_base {
15340fe15e0SLoGin                 offset = area_base;
15440fe15e0SLoGin             } else if offset < area_end {
15540fe15e0SLoGin                 // 将offset对齐到PAGE_SIZE
15640fe15e0SLoGin                 offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
15740fe15e0SLoGin             }
15840fe15e0SLoGin             // 如果当前offset到area_end的距离大于等于count.data() * PAGE_SIZE,说明当前的物理内存区域足以分配count个页帧
15940fe15e0SLoGin             if offset + count.data() * MMA::PAGE_SIZE <= area_end {
16040fe15e0SLoGin                 let res_page_phys = offset;
16140fe15e0SLoGin                 // 将offset增加至分配后的内存
16240fe15e0SLoGin                 self.offset = offset + count.data() * MMA::PAGE_SIZE;
16340fe15e0SLoGin 
164453452ccSLoGin                 let r = (PhysAddr(res_page_phys), count);
165453452ccSLoGin                 self.ensure_early_mapping(r.0, r.1);
166453452ccSLoGin                 return Some(r);
16740fe15e0SLoGin             }
16840fe15e0SLoGin         }
16940fe15e0SLoGin         return None;
17040fe15e0SLoGin     }
17140fe15e0SLoGin 
free(&mut self, _address: PhysAddr, _count: PageFrameCount)17240fe15e0SLoGin     unsafe fn free(&mut self, _address: PhysAddr, _count: PageFrameCount) {
17340fe15e0SLoGin         // TODO: 支持释放页帧
17440fe15e0SLoGin         unimplemented!("BumpAllocator::free not implemented");
17540fe15e0SLoGin     }
17640fe15e0SLoGin     /// @brief: 获取内存区域页帧的使用情况
17740fe15e0SLoGin     /// @param  self
17840fe15e0SLoGin     /// @return 页帧的使用情况
usage(&self) -> PageFrameUsage17940fe15e0SLoGin     unsafe fn usage(&self) -> PageFrameUsage {
18040fe15e0SLoGin         let mut total = 0;
18140fe15e0SLoGin         let mut used = 0;
182453452ccSLoGin         let iter = mem_block_manager().to_iter_available();
18345626c85SLoGin         for area in iter {
18440fe15e0SLoGin             // 将area的base地址与PAGE_SIZE对齐,对其时向上取整
18540fe15e0SLoGin             let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
18640fe15e0SLoGin             // 将area的末尾地址与PAGE_SIZE对齐,对其时向下取整
18740fe15e0SLoGin             let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
18840fe15e0SLoGin 
18940fe15e0SLoGin             total += (area_end - area_base) >> MMA::PAGE_SHIFT;
19040fe15e0SLoGin             // 如果offset大于area_end,说明当前物理区域被分配完,都需要加到used中
19140fe15e0SLoGin             if self.offset >= area_end {
19240fe15e0SLoGin                 used += (area_end - area_base) >> MMA::PAGE_SHIFT;
19340fe15e0SLoGin             } else if self.offset < area_base {
19440fe15e0SLoGin                 // 如果offset小于area_base,说明当前物理区域还没有分配过页帧,都不需要加到used中
19540fe15e0SLoGin                 continue;
19640fe15e0SLoGin             } else {
19740fe15e0SLoGin                 used += (self.offset - area_base) >> MMA::PAGE_SHIFT;
19840fe15e0SLoGin             }
19940fe15e0SLoGin         }
20040fe15e0SLoGin         let frame = PageFrameUsage::new(PageFrameCount::new(used), PageFrameCount::new(total));
20140fe15e0SLoGin         return frame;
20240fe15e0SLoGin     }
20340fe15e0SLoGin }
204