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() as *mut u8) 65 .unwrap_or(core::ptr::null_mut() as *mut u8); 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() as *mut u8); 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( 90 layout.clone(), 91 Some(r as usize), 92 None, 93 )), 94 klog_types::LogSource::Buddy, 95 ); 96 97 return r; 98 99 // self.local_alloc_zeroed(layout, 0) 100 } 101 102 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { 103 let r = self.local_alloc_zeroed(layout); 104 105 mm_debug_log( 106 klog_types::AllocatorLogType::AllocZeroed(AllocLogItem::new( 107 layout.clone(), 108 Some(r as usize), 109 None, 110 )), 111 klog_types::LogSource::Buddy, 112 ); 113 114 return r; 115 } 116 117 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { 118 mm_debug_log( 119 klog_types::AllocatorLogType::Free(AllocLogItem::new( 120 layout.clone(), 121 Some(ptr as usize), 122 None, 123 )), 124 klog_types::LogSource::Buddy, 125 ); 126 127 self.local_dealloc(ptr, layout); 128 } 129 } 130 131 /// 为内核slab分配器实现Allocator特性 132 // unsafe impl Allocator for KernelAllocator { 133 // fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { 134 // let memory = unsafe {self.local_alloc(layout)}; 135 // if memory.is_null() { 136 // Err(AllocError) 137 // } else { 138 // let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) }; 139 // Ok(unsafe { NonNull::new_unchecked(slice) }) 140 // } 141 // } 142 143 // fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { 144 // let memory = unsafe {self.local_alloc_zeroed(layout)}; 145 // if memory.is_null() { 146 // Err(AllocError) 147 // } else { 148 // let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) }; 149 // Ok(unsafe { NonNull::new_unchecked(slice) }) 150 // } 151 // } 152 153 // unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { 154 // self.local_dealloc(ptr.cast().as_ptr(), layout); 155 // } 156 // } 157 158 /// 内存分配错误处理函数 159 #[cfg(target_os = "none")] 160 #[alloc_error_handler] 161 pub fn global_alloc_err_handler(layout: Layout) -> ! { 162 panic!("global_alloc_error, layout: {:?}", layout); 163 } 164