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