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}; 640fe15e0SLoGin use crate::mm::{MemoryManagementArch, PhysAddr, PhysMemoryArea}; 740fe15e0SLoGin use core::marker::PhantomData; 840fe15e0SLoGin 940fe15e0SLoGin /// 线性分配器 1040fe15e0SLoGin pub struct BumpAllocator<MMA> { 1140fe15e0SLoGin // 表示可用物理内存区域的数组。每个 PhysMemoryArea 结构体描述一个物理内存区域的起始地址和大小。 1240fe15e0SLoGin areas: &'static [PhysMemoryArea], 1340fe15e0SLoGin // 表示当前分配的物理内存的偏移量. 1440fe15e0SLoGin offset: usize, 1540fe15e0SLoGin // 一个占位类型,用于标记 A 类型在结构体中的存在。但是,它并不会占用任何内存空间,因为它的大小为 0。 1640fe15e0SLoGin phantom: PhantomData<MMA>, 1740fe15e0SLoGin } 1840fe15e0SLoGin 1940fe15e0SLoGin /// 为BumpAllocator实现FrameAllocator 2040fe15e0SLoGin impl<MMA: MemoryManagementArch> BumpAllocator<MMA> { 2140fe15e0SLoGin /// @brief: 创建一个线性分配器 2240fe15e0SLoGin /// @param Fareas 当前的内存区域 2340fe15e0SLoGin /// @param offset 当前的偏移量 2440fe15e0SLoGin /// @return 分配器本身 2540fe15e0SLoGin pub fn new(areas: &'static [PhysMemoryArea], offset: usize) -> Self { 2640fe15e0SLoGin Self { 2740fe15e0SLoGin areas, 2840fe15e0SLoGin offset, 2940fe15e0SLoGin phantom: PhantomData, 3040fe15e0SLoGin } 3140fe15e0SLoGin } 3240fe15e0SLoGin // @brief 获取页帧使用情况 3340fe15e0SLoGin pub fn areas(&self) -> &'static [PhysMemoryArea] { 3440fe15e0SLoGin return self.areas; 3540fe15e0SLoGin } 3640fe15e0SLoGin // @brief 获取当前分配的物理内存的偏移量 3740fe15e0SLoGin pub fn offset(&self) -> usize { 3840fe15e0SLoGin return self.offset; 3940fe15e0SLoGin } 40*99dbf38dSLoGin 41*99dbf38dSLoGin /// 返回剩余的尚未被分配的物理内存区域 42*99dbf38dSLoGin /// 43*99dbf38dSLoGin /// ## 返回值 44*99dbf38dSLoGin /// 45*99dbf38dSLoGin /// - `result_area`:剩余的尚未被分配的物理内存区域的数组 46*99dbf38dSLoGin /// - `offset_aligned`:返回的第一个物理内存区域内,已经分配的偏移量(相对于物理内存区域的已对齐的起始地址) 47*99dbf38dSLoGin pub fn remain_areas(&self, result_area: &mut [PhysMemoryArea]) -> Option<usize> { 48*99dbf38dSLoGin let mut offset = self.offset(); 49*99dbf38dSLoGin 50*99dbf38dSLoGin let mut ret_offset_aligned = 0; 51*99dbf38dSLoGin 52*99dbf38dSLoGin let mut res_cnt = 0; 53*99dbf38dSLoGin 54*99dbf38dSLoGin // 遍历所有的物理内存区域 55*99dbf38dSLoGin for i in 0..self.areas().len() { 56*99dbf38dSLoGin let area = &self.areas()[i]; 57*99dbf38dSLoGin // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整 58*99dbf38dSLoGin // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT); 59*99dbf38dSLoGin let area_base = area.area_base_aligned().data(); 60*99dbf38dSLoGin // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整 61*99dbf38dSLoGin // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT); 62*99dbf38dSLoGin let area_end = area.area_end_aligned().data(); 63*99dbf38dSLoGin 64*99dbf38dSLoGin // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域 65*99dbf38dSLoGin if offset >= area_end { 66*99dbf38dSLoGin continue; 67*99dbf38dSLoGin } 68*99dbf38dSLoGin 69*99dbf38dSLoGin // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base 70*99dbf38dSLoGin if offset < area_base { 71*99dbf38dSLoGin offset = area_base; 72*99dbf38dSLoGin } else if offset < area_end { 73*99dbf38dSLoGin // 将offset对齐到PAGE_SIZE 74*99dbf38dSLoGin offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1); 75*99dbf38dSLoGin } 76*99dbf38dSLoGin // found 77*99dbf38dSLoGin if offset + 1 * MMA::PAGE_SIZE <= area_end { 78*99dbf38dSLoGin for j in i..self.areas().len() { 79*99dbf38dSLoGin if self.areas()[j].area_base_aligned() < self.areas()[j].area_end_aligned() { 80*99dbf38dSLoGin result_area[res_cnt] = self.areas()[j]; 81*99dbf38dSLoGin res_cnt += 1; 82*99dbf38dSLoGin } 83*99dbf38dSLoGin } 84*99dbf38dSLoGin ret_offset_aligned = offset; 85*99dbf38dSLoGin break; 86*99dbf38dSLoGin } 87*99dbf38dSLoGin } 88*99dbf38dSLoGin 89*99dbf38dSLoGin let res_cnt = unsafe { Self::arch_remain_areas(result_area, res_cnt) }; 90*99dbf38dSLoGin if res_cnt == 0 { 91*99dbf38dSLoGin return None; 92*99dbf38dSLoGin } else { 93*99dbf38dSLoGin return Some(ret_offset_aligned); 94*99dbf38dSLoGin } 95*99dbf38dSLoGin } 9640fe15e0SLoGin } 9740fe15e0SLoGin 9840fe15e0SLoGin impl<MMA: MemoryManagementArch> FrameAllocator for BumpAllocator<MMA> { 9940fe15e0SLoGin /// @brief: 分配count个物理页帧 10040fe15e0SLoGin /// @param mut self 10140fe15e0SLoGin /// @param count 分配的页帧数量 10240fe15e0SLoGin /// @return 分配后的物理地址 10340fe15e0SLoGin unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { 10440fe15e0SLoGin let mut offset = self.offset(); 10540fe15e0SLoGin // 遍历所有的物理内存区域 10640fe15e0SLoGin for area in self.areas().iter() { 10740fe15e0SLoGin // 将area的base地址与PAGE_SIZE对齐,对齐时向上取整 10840fe15e0SLoGin // let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT); 109*99dbf38dSLoGin let area_base = area.area_base_aligned().data(); 11040fe15e0SLoGin // 将area的末尾地址与PAGE_SIZE对齐,对齐时向下取整 11140fe15e0SLoGin // let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT); 112*99dbf38dSLoGin let area_end = area.area_end_aligned().data(); 11340fe15e0SLoGin 11440fe15e0SLoGin // 如果offset大于area_end,说明当前的物理内存区域已经分配完了,需要跳到下一个物理内存区域 11540fe15e0SLoGin if offset >= area_end { 11640fe15e0SLoGin continue; 11740fe15e0SLoGin } 11840fe15e0SLoGin 11940fe15e0SLoGin // 如果offset小于area_base ,说明当前的物理内存区域还没有分配过页帧,将offset设置为area_base 12040fe15e0SLoGin if offset < area_base { 12140fe15e0SLoGin offset = area_base; 12240fe15e0SLoGin } else if offset < area_end { 12340fe15e0SLoGin // 将offset对齐到PAGE_SIZE 12440fe15e0SLoGin offset = (offset + (MMA::PAGE_SIZE - 1)) & !(MMA::PAGE_SIZE - 1); 12540fe15e0SLoGin } 12640fe15e0SLoGin // 如果当前offset到area_end的距离大于等于count.data() * PAGE_SIZE,说明当前的物理内存区域足以分配count个页帧 12740fe15e0SLoGin if offset + count.data() * MMA::PAGE_SIZE <= area_end { 12840fe15e0SLoGin let res_page_phys = offset; 12940fe15e0SLoGin // 将offset增加至分配后的内存 13040fe15e0SLoGin self.offset = offset + count.data() * MMA::PAGE_SIZE; 13140fe15e0SLoGin 13240fe15e0SLoGin return Some((PhysAddr(res_page_phys), count)); 13340fe15e0SLoGin } 13440fe15e0SLoGin } 13540fe15e0SLoGin return None; 13640fe15e0SLoGin } 13740fe15e0SLoGin 13840fe15e0SLoGin unsafe fn free(&mut self, _address: PhysAddr, _count: PageFrameCount) { 13940fe15e0SLoGin // TODO: 支持释放页帧 14040fe15e0SLoGin unimplemented!("BumpAllocator::free not implemented"); 14140fe15e0SLoGin } 14240fe15e0SLoGin /// @brief: 获取内存区域页帧的使用情况 14340fe15e0SLoGin /// @param self 14440fe15e0SLoGin /// @return 页帧的使用情况 14540fe15e0SLoGin unsafe fn usage(&self) -> PageFrameUsage { 14640fe15e0SLoGin let mut total = 0; 14740fe15e0SLoGin let mut used = 0; 14840fe15e0SLoGin for area in self.areas().iter() { 14940fe15e0SLoGin // 将area的base地址与PAGE_SIZE对齐,对其时向上取整 15040fe15e0SLoGin let area_base = (area.base.data() + MMA::PAGE_SHIFT) & !(MMA::PAGE_SHIFT); 15140fe15e0SLoGin // 将area的末尾地址与PAGE_SIZE对齐,对其时向下取整 15240fe15e0SLoGin let area_end = (area.base.data() + area.size) & !(MMA::PAGE_SHIFT); 15340fe15e0SLoGin 15440fe15e0SLoGin total += (area_end - area_base) >> MMA::PAGE_SHIFT; 15540fe15e0SLoGin // 如果offset大于area_end,说明当前物理区域被分配完,都需要加到used中 15640fe15e0SLoGin if self.offset >= area_end { 15740fe15e0SLoGin used += (area_end - area_base) >> MMA::PAGE_SHIFT; 15840fe15e0SLoGin } else if self.offset < area_base { 15940fe15e0SLoGin // 如果offset小于area_base,说明当前物理区域还没有分配过页帧,都不需要加到used中 16040fe15e0SLoGin continue; 16140fe15e0SLoGin } else { 16240fe15e0SLoGin used += (self.offset - area_base) >> MMA::PAGE_SHIFT; 16340fe15e0SLoGin } 16440fe15e0SLoGin } 16540fe15e0SLoGin let frame = PageFrameUsage::new(PageFrameCount::new(used), PageFrameCount::new(total)); 16640fe15e0SLoGin return frame; 16740fe15e0SLoGin } 16840fe15e0SLoGin } 169