xref: /DragonOS/kernel/src/mm/allocator/bump.rs (revision 453452cc02e2766a28d87dd47bdee37caddc4c44)
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};
6*453452ccSLoGin use crate::mm::{
7*453452ccSLoGin     allocator::page_frame::{PhysPageFrame, PhysPageFrameIter},
8*453452ccSLoGin     init::{mm_init_status, MMInitStatus},
9*453452ccSLoGin     memblock::mem_block_manager,
10*453452ccSLoGin     no_init::pseudo_map_phys,
11*453452ccSLoGin     page::PageMapper,
12*453452ccSLoGin     MemoryManagementArch, PageTableKind, PhysAddr, PhysMemoryArea,
13*453452ccSLoGin };
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 分配器本身
3045626c85SLoGin     pub fn new(offset: usize) -> Self {
3140fe15e0SLoGin         Self {
3240fe15e0SLoGin             offset,
3340fe15e0SLoGin             phantom: PhantomData,
3440fe15e0SLoGin         }
3540fe15e0SLoGin     }
3645626c85SLoGin 
3740fe15e0SLoGin     // @brief 获取当前分配的物理内存的偏移量
3840fe15e0SLoGin     pub fn offset(&self) -> usize {
3940fe15e0SLoGin         return self.offset;
4040fe15e0SLoGin     }
4199dbf38dSLoGin 
4299dbf38dSLoGin     /// 返回剩余的尚未被分配的物理内存区域
4399dbf38dSLoGin     ///
4499dbf38dSLoGin     /// ## 返回值
4599dbf38dSLoGin     ///
4699dbf38dSLoGin     /// - `result_area`:剩余的尚未被分配的物理内存区域的数组
4799dbf38dSLoGin     /// - `offset_aligned`:返回的第一个物理内存区域内,已经分配的偏移量(相对于物理内存区域的已对齐的起始地址)
4899dbf38dSLoGin     pub fn remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option<usize> {
4999dbf38dSLoGin         let mut offset = self.offset();
5099dbf38dSLoGin 
51*453452ccSLoGin         let iter = mem_block_manager().to_iter_available();
52*453452ccSLoGin 
5399dbf38dSLoGin         let mut ret_offset_aligned = 0;
5499dbf38dSLoGin 
5599dbf38dSLoGin         let mut res_cnt = 0;
5699dbf38dSLoGin 
57*453452ccSLoGin         let mut found_start = false;
5899dbf38dSLoGin         // 遍历所有的物理内存区域
59*453452ccSLoGin         for area in iter {
60*453452ccSLoGin             if found_start == false {
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
8199dbf38dSLoGin                 if offset + 1 * MMA::PAGE_SIZE <= area_end {
82*453452ccSLoGin                     ret_offset_aligned = offset - area.area_base_aligned().data();
83*453452ccSLoGin                     found_start = true;
84*453452ccSLoGin                 }
85*453452ccSLoGin             }
86*453452ccSLoGin 
87*453452ccSLoGin             if found_start {
88*453452ccSLoGin                 if area.area_base_aligned() < area.area_end_aligned() {
89*453452ccSLoGin                     result_area[res_cnt] = area;
9099dbf38dSLoGin                     res_cnt += 1;
9199dbf38dSLoGin                 }
9299dbf38dSLoGin             }
9399dbf38dSLoGin         }
9499dbf38dSLoGin 
9599dbf38dSLoGin         let res_cnt = unsafe { Self::arch_remain_areas(result_area, res_cnt) };
9699dbf38dSLoGin         if res_cnt == 0 {
9799dbf38dSLoGin             return None;
9899dbf38dSLoGin         } else {
9999dbf38dSLoGin             return Some(ret_offset_aligned);
10099dbf38dSLoGin         }
10199dbf38dSLoGin     }
102*453452ccSLoGin 
103*453452ccSLoGin     #[inline(never)]
104*453452ccSLoGin     unsafe fn ensure_early_mapping(&self, start_paddr: PhysAddr, count: PageFrameCount) {
105*453452ccSLoGin         // 确保在内存管理未被初始化时,这地址已经被映射了
106*453452ccSLoGin         if mm_init_status() != MMInitStatus::Initialized {
107*453452ccSLoGin             // 映射涉及的页
108*453452ccSLoGin 
109*453452ccSLoGin             let iter = PhysPageFrameIter::new(
110*453452ccSLoGin                 PhysPageFrame::new(start_paddr),
111*453452ccSLoGin                 PhysPageFrame::new(start_paddr + count.bytes()),
112*453452ccSLoGin             );
113*453452ccSLoGin             let mapper =
114*453452ccSLoGin                 PageMapper::<MMA, _>::current(PageTableKind::Kernel, BumpAllocator::<MMA>::new(0));
115*453452ccSLoGin 
116*453452ccSLoGin             for p in iter {
117*453452ccSLoGin                 if let None = mapper.translate(MMA::phys_2_virt(p.phys_address()).unwrap()) {
118*453452ccSLoGin                     let vaddr = MMA::phys_2_virt(p.phys_address()).unwrap();
119*453452ccSLoGin                     pseudo_map_phys(vaddr, p.phys_address(), PageFrameCount::new(1));
120*453452ccSLoGin                 }
121*453452ccSLoGin             }
122*453452ccSLoGin         }
123*453452ccSLoGin     }
12440fe15e0SLoGin }
12540fe15e0SLoGin 
12640fe15e0SLoGin impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> {
12740fe15e0SLoGin     /// @brief: 分配count个物理页帧
12840fe15e0SLoGin     /// @param  mut self
12940fe15e0SLoGin     /// @param  count 分配的页帧数量
13040fe15e0SLoGin     /// @return 分配后的物理地址
13140fe15e0SLoGin     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
13240fe15e0SLoGin         let mut offset = self.offset();
13345626c85SLoGin 
134*453452ccSLoGin         let iter = mem_block_manager().to_iter_available();
13545626c85SLoGin 
13640fe15e0SLoGin         // 遍历所有的物理内存区域
13745626c85SLoGin         for area in iter {
13840fe15e0SLoGin             // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整
13940fe15e0SLoGin             // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
14099dbf38dSLoGin             let area_base = area.area_base_aligned().data();
14140fe15e0SLoGin             // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整
14240fe15e0SLoGin             // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
14399dbf38dSLoGin             let area_end = area.area_end_aligned().data();
14440fe15e0SLoGin 
14540fe15e0SLoGin             // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域
14640fe15e0SLoGin             if offset >= area_end {
14740fe15e0SLoGin                 continue;
14840fe15e0SLoGin             }
14940fe15e0SLoGin 
15040fe15e0SLoGin             // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base
15140fe15e0SLoGin             if offset < area_base {
15240fe15e0SLoGin                 offset = area_base;
15340fe15e0SLoGin             } else if offset < area_end {
15440fe15e0SLoGin                 // 将offset对齐到PAGE_SIZE
15540fe15e0SLoGin                 offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1);
15640fe15e0SLoGin             }
15740fe15e0SLoGin             // 如果当前offset到area_end的距离大于等于count.data() * PAGE_SIZE,说明当前的物理内存区域足以分配count个页帧
15840fe15e0SLoGin             if offset + count.data() * MMA::PAGE_SIZE <= area_end {
15940fe15e0SLoGin                 let res_page_phys = offset;
16040fe15e0SLoGin                 // 将offset增加至分配后的内存
16140fe15e0SLoGin                 self.offset = offset + count.data() * MMA::PAGE_SIZE;
16240fe15e0SLoGin 
163*453452ccSLoGin                 let r = (PhysAddr(res_page_phys), count);
164*453452ccSLoGin                 self.ensure_early_mapping(r.0, r.1);
165*453452ccSLoGin                 return Some(r);
16640fe15e0SLoGin             }
16740fe15e0SLoGin         }
16840fe15e0SLoGin         return None;
16940fe15e0SLoGin     }
17040fe15e0SLoGin 
17140fe15e0SLoGin     unsafe fn free(&mut self, _address: PhysAddr, _count: PageFrameCount) {
17240fe15e0SLoGin         // TODO: 支持释放页帧
17340fe15e0SLoGin         unimplemented!("BumpAllocator::free not implemented");
17440fe15e0SLoGin     }
17540fe15e0SLoGin     /// @brief: 获取内存区域页帧的使用情况
17640fe15e0SLoGin     /// @param  self
17740fe15e0SLoGin     /// @return 页帧的使用情况
17840fe15e0SLoGin     unsafe fn usage(&self) -> PageFrameUsage {
17940fe15e0SLoGin         let mut total = 0;
18040fe15e0SLoGin         let mut used = 0;
181*453452ccSLoGin         let iter = mem_block_manager().to_iter_available();
18245626c85SLoGin         for area in iter {
18340fe15e0SLoGin             // 将area的base地址与PAGE_SIZE对齐,对其时向上取整
18440fe15e0SLoGin             let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT);
18540fe15e0SLoGin             // 将area的末尾地址与PAGE_SIZE对齐,对其时向下取整
18640fe15e0SLoGin             let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT);
18740fe15e0SLoGin 
18840fe15e0SLoGin             total += (area_end - area_base) >> MMA::PAGE_SHIFT;
18940fe15e0SLoGin             // 如果offset大于area_end,说明当前物理区域被分配完,都需要加到used中
19040fe15e0SLoGin             if self.offset >= area_end {
19140fe15e0SLoGin                 used += (area_end - area_base) >> MMA::PAGE_SHIFT;
19240fe15e0SLoGin             } else if self.offset < area_base {
19340fe15e0SLoGin                 // 如果offset小于area_base,说明当前物理区域还没有分配过页帧,都不需要加到used中
19440fe15e0SLoGin                 continue;
19540fe15e0SLoGin             } else {
19640fe15e0SLoGin                 used += (self.offset - area_base) >> MMA::PAGE_SHIFT;
19740fe15e0SLoGin             }
19840fe15e0SLoGin         }
19940fe15e0SLoGin         let frame = PageFrameUsage::new(PageFrameCount::new(used), PageFrameCount::new(total));
20040fe15e0SLoGin         return frame;
20140fe15e0SLoGin     }
20240fe15e0SLoGin }
203