1*40fe15e0SLoGin use crate::{ 2*40fe15e0SLoGin arch::mm::LockedFrameAllocator, 3*40fe15e0SLoGin libs::align::page_align_up, 4*40fe15e0SLoGin mm::{MMArch, MemoryManagementArch, VirtAddr}, 5*40fe15e0SLoGin }; 6*40fe15e0SLoGin 7*40fe15e0SLoGin use core::{ 8*40fe15e0SLoGin alloc::{AllocError, GlobalAlloc, Layout}, 9*40fe15e0SLoGin intrinsics::unlikely, 10*40fe15e0SLoGin ptr::NonNull, 11*40fe15e0SLoGin }; 12*40fe15e0SLoGin 13*40fe15e0SLoGin use super::page_frame::{FrameAllocator, PageFrameCount}; 14*40fe15e0SLoGin 15*40fe15e0SLoGin /// 类kmalloc的分配器应当实现的trait 16*40fe15e0SLoGin pub trait LocalAlloc { 17*40fe15e0SLoGin unsafe fn local_alloc(&self, layout: Layout) -> *mut u8; 18*40fe15e0SLoGin unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8; 19*40fe15e0SLoGin unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout); 20*40fe15e0SLoGin } 21*40fe15e0SLoGin 22*40fe15e0SLoGin pub struct KernelAllocator; 23*40fe15e0SLoGin 24*40fe15e0SLoGin impl KernelAllocator { 25*40fe15e0SLoGin unsafe fn alloc_in_buddy(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { 26*40fe15e0SLoGin // 计算需要申请的页数,向上取整 27*40fe15e0SLoGin let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two(); 28*40fe15e0SLoGin let page_frame_count = PageFrameCount::new(count); 29*40fe15e0SLoGin let (phy_addr, allocated_frame_count) = LockedFrameAllocator 30*40fe15e0SLoGin .allocate(page_frame_count) 31*40fe15e0SLoGin .ok_or(AllocError)?; 32*40fe15e0SLoGin 33*40fe15e0SLoGin let virt_addr = unsafe { MMArch::phys_2_virt(phy_addr).ok_or(AllocError)? }; 34*40fe15e0SLoGin if unlikely(virt_addr.is_null()) { 35*40fe15e0SLoGin return Err(AllocError); 36*40fe15e0SLoGin } 37*40fe15e0SLoGin 38*40fe15e0SLoGin let slice = unsafe { 39*40fe15e0SLoGin core::slice::from_raw_parts_mut( 40*40fe15e0SLoGin virt_addr.data() as *mut u8, 41*40fe15e0SLoGin allocated_frame_count.data() * MMArch::PAGE_SIZE, 42*40fe15e0SLoGin ) 43*40fe15e0SLoGin }; 44*40fe15e0SLoGin return Ok(NonNull::from(slice)); 45*40fe15e0SLoGin } 46*40fe15e0SLoGin 47*40fe15e0SLoGin unsafe fn free_in_buddy(&self, ptr: *mut u8, layout: Layout) { 48*40fe15e0SLoGin // 由于buddy分配的页数量是2的幂,因此释放的时候也需要按照2的幂向上取整。 49*40fe15e0SLoGin let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two(); 50*40fe15e0SLoGin let page_frame_count = PageFrameCount::new(count); 51*40fe15e0SLoGin let phy_addr = MMArch::virt_2_phys(VirtAddr::new(ptr as usize)).unwrap(); 52*40fe15e0SLoGin LockedFrameAllocator.free(phy_addr, page_frame_count); 53*40fe15e0SLoGin } 54*40fe15e0SLoGin } 55*40fe15e0SLoGin 56*40fe15e0SLoGin /// 为内核SLAB分配器实现LocalAlloc的trait 57*40fe15e0SLoGin impl LocalAlloc for KernelAllocator { 58*40fe15e0SLoGin unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 { 59*40fe15e0SLoGin return self 60*40fe15e0SLoGin .alloc_in_buddy(layout) 61*40fe15e0SLoGin .map(|x| x.as_mut_ptr() as *mut u8) 62*40fe15e0SLoGin .unwrap_or(core::ptr::null_mut() as *mut u8); 63*40fe15e0SLoGin } 64*40fe15e0SLoGin 65*40fe15e0SLoGin unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8 { 66*40fe15e0SLoGin return self 67*40fe15e0SLoGin .alloc_in_buddy(layout) 68*40fe15e0SLoGin .map(|x| { 69*40fe15e0SLoGin let ptr: *mut u8 = x.as_mut_ptr(); 70*40fe15e0SLoGin core::ptr::write_bytes(ptr, 0, x.len()); 71*40fe15e0SLoGin ptr 72*40fe15e0SLoGin }) 73*40fe15e0SLoGin .unwrap_or(core::ptr::null_mut() as *mut u8); 74*40fe15e0SLoGin } 75*40fe15e0SLoGin 76*40fe15e0SLoGin unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout) { 77*40fe15e0SLoGin self.free_in_buddy(ptr, layout); 78*40fe15e0SLoGin } 79*40fe15e0SLoGin } 80*40fe15e0SLoGin 81*40fe15e0SLoGin /// 为内核slab分配器实现GlobalAlloc特性 82*40fe15e0SLoGin unsafe impl GlobalAlloc for KernelAllocator { 83*40fe15e0SLoGin unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 84*40fe15e0SLoGin return self.local_alloc(layout); 85*40fe15e0SLoGin // self.local_alloc_zeroed(layout, 0) 86*40fe15e0SLoGin } 87*40fe15e0SLoGin 88*40fe15e0SLoGin unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { 89*40fe15e0SLoGin self.local_alloc_zeroed(layout) 90*40fe15e0SLoGin } 91*40fe15e0SLoGin 92*40fe15e0SLoGin unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { 93*40fe15e0SLoGin self.local_dealloc(ptr, layout); 94*40fe15e0SLoGin } 95*40fe15e0SLoGin } 96*40fe15e0SLoGin 97*40fe15e0SLoGin /// 内存分配错误处理函数 98*40fe15e0SLoGin #[alloc_error_handler] 99*40fe15e0SLoGin pub fn global_alloc_err_handler(layout: Layout) -> ! { 100*40fe15e0SLoGin panic!("global_alloc_error, layout: {:?}", layout); 101*40fe15e0SLoGin } 102