1 use klog_types::AllocLogItem; 2 3 use crate::{ 4 arch::mm::LockedFrameAllocator, 5 debug::klog::mm::mm_debug_log, 6 libs::align::page_align_up, 7 mm::{MMArch, MemoryManagementArch, VirtAddr}, 8 }; 9 10 use core::{ 11 alloc::{AllocError, GlobalAlloc, Layout}, 12 intrinsics::unlikely, 13 ptr::NonNull, 14 }; 15 16 use super::page_frame::{FrameAllocator, PageFrameCount}; 17 18 /// 类kmalloc的分配器应当实现的trait 19 pub trait LocalAlloc { 20 unsafe fn local_alloc(&self, layout: Layout) -> *mut u8; 21 unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8; 22 unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout); 23 } 24 25 pub struct KernelAllocator; 26 27 impl KernelAllocator { 28 unsafe fn alloc_in_buddy(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { 29 // 计算需要申请的页数,向上取整 30 let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two(); 31 let page_frame_count = PageFrameCount::new(count); 32 let (phy_addr, allocated_frame_count) = LockedFrameAllocator 33 .allocate(page_frame_count) 34 .ok_or(AllocError)?; 35 36 let virt_addr = unsafe { MMArch::phys_2_virt(phy_addr).ok_or(AllocError)? }; 37 if unlikely(virt_addr.is_null()) { 38 return Err(AllocError); 39 } 40 41 let slice = unsafe { 42 core::slice::from_raw_parts_mut( 43 virt_addr.data() as *mut u8, 44 allocated_frame_count.data() * MMArch::PAGE_SIZE, 45 ) 46 }; 47 return Ok(NonNull::from(slice)); 48 } 49 50 unsafe fn free_in_buddy(&self, ptr: *mut u8, layout: Layout) { 51 // 由于buddy分配的页数量是2的幂,因此释放的时候也需要按照2的幂向上取整。 52 let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two(); 53 let page_frame_count = PageFrameCount::new(count); 54 let phy_addr = MMArch::virt_2_phys(VirtAddr::new(ptr as usize)).unwrap(); 55 LockedFrameAllocator.free(phy_addr, page_frame_count); 56 } 57 } 58 59 /// 为内核分配器实现LocalAlloc的trait 60 impl LocalAlloc for KernelAllocator { 61 unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 { 62 return self 63 .alloc_in_buddy(layout) 64 .map(|x| x.as_mut_ptr()) 65 .unwrap_or(core::ptr::null_mut()); 66 } 67 68 unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8 { 69 return self 70 .alloc_in_buddy(layout) 71 .map(|x| { 72 let ptr: *mut u8 = x.as_mut_ptr(); 73 core::ptr::write_bytes(ptr, 0, x.len()); 74 ptr 75 }) 76 .unwrap_or(core::ptr::null_mut()); 77 } 78 79 unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout) { 80 self.free_in_buddy(ptr, layout); 81 } 82 } 83 84 /// 为内核slab分配器实现GlobalAlloc特性 85 unsafe impl GlobalAlloc for KernelAllocator { 86 unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 87 let r = self.local_alloc_zeroed(layout); 88 mm_debug_log( 89 klog_types::AllocatorLogType::Alloc(AllocLogItem::new(layout, Some(r as usize), None)), 90 klog_types::LogSource::Buddy, 91 ); 92 93 return r; 94 95 // self.local_alloc_zeroed(layout, 0) 96 } 97 98 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { 99 let r = self.local_alloc_zeroed(layout); 100 101 mm_debug_log( 102 klog_types::AllocatorLogType::AllocZeroed(AllocLogItem::new( 103 layout, 104 Some(r as usize), 105 None, 106 )), 107 klog_types::LogSource::Buddy, 108 ); 109 110 return r; 111 } 112 113 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { 114 mm_debug_log( 115 klog_types::AllocatorLogType::Free(AllocLogItem::new(layout, Some(ptr as usize), None)), 116 klog_types::LogSource::Buddy, 117 ); 118 119 self.local_dealloc(ptr, layout); 120 } 121 } 122 123 /// 为内核slab分配器实现Allocator特性 124 // unsafe impl Allocator for KernelAllocator { 125 // fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { 126 // let memory = unsafe {self.local_alloc(layout)}; 127 // if memory.is_null() { 128 // Err(AllocError) 129 // } else { 130 // let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) }; 131 // Ok(unsafe { NonNull::new_unchecked(slice) }) 132 // } 133 // } 134 135 // fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { 136 // let memory = unsafe {self.local_alloc_zeroed(layout)}; 137 // if memory.is_null() { 138 // Err(AllocError) 139 // } else { 140 // let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) }; 141 // Ok(unsafe { NonNull::new_unchecked(slice) }) 142 // } 143 // } 144 145 // unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { 146 // self.local_dealloc(ptr.cast().as_ptr(), layout); 147 // } 148 // } 149 150 /// 内存分配错误处理函数 151 #[cfg(target_os = "none")] 152 #[alloc_error_handler] 153 pub fn global_alloc_err_handler(layout: Layout) -> ! { 154 panic!("global_alloc_error, layout: {:?}", layout); 155 } 156