xref: /DragonOS/kernel/src/mm/allocator/kernel_allocator.rs (revision 7b32f5080f42bcbf7d2421013f3ea53c776a063c)
1*7b32f508SLoGin use klog_types::AllocLogItem;
2*7b32f508SLoGin 
340fe15e0SLoGin use crate::{
440fe15e0SLoGin     arch::mm::LockedFrameAllocator,
5*7b32f508SLoGin     debug::klog::mm::mm_debug_log,
640fe15e0SLoGin     libs::align::page_align_up,
740fe15e0SLoGin     mm::{MMArch, MemoryManagementArch, VirtAddr},
840fe15e0SLoGin };
940fe15e0SLoGin 
1040fe15e0SLoGin use core::{
1140fe15e0SLoGin     alloc::{AllocError, GlobalAlloc, Layout},
1240fe15e0SLoGin     intrinsics::unlikely,
1340fe15e0SLoGin     ptr::NonNull,
1440fe15e0SLoGin };
1540fe15e0SLoGin 
1640fe15e0SLoGin use super::page_frame::{FrameAllocator, PageFrameCount};
1740fe15e0SLoGin 
1840fe15e0SLoGin /// 类kmalloc的分配器应当实现的trait
1940fe15e0SLoGin pub trait LocalAlloc {
2040fe15e0SLoGin     unsafe fn local_alloc(&self, layout: Layout) -> *mut u8;
2140fe15e0SLoGin     unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8;
2240fe15e0SLoGin     unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout);
2340fe15e0SLoGin }
2440fe15e0SLoGin 
2540fe15e0SLoGin pub struct KernelAllocator;
2640fe15e0SLoGin 
2740fe15e0SLoGin impl KernelAllocator {
2840fe15e0SLoGin     unsafe fn alloc_in_buddy(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
2940fe15e0SLoGin         // 计算需要申请的页数,向上取整
3040fe15e0SLoGin         let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two();
3140fe15e0SLoGin         let page_frame_count = PageFrameCount::new(count);
3240fe15e0SLoGin         let (phy_addr, allocated_frame_count) = LockedFrameAllocator
3340fe15e0SLoGin             .allocate(page_frame_count)
3440fe15e0SLoGin             .ok_or(AllocError)?;
3540fe15e0SLoGin 
3640fe15e0SLoGin         let virt_addr = unsafe { MMArch::phys_2_virt(phy_addr).ok_or(AllocError)? };
3740fe15e0SLoGin         if unlikely(virt_addr.is_null()) {
3840fe15e0SLoGin             return Err(AllocError);
3940fe15e0SLoGin         }
4040fe15e0SLoGin 
4140fe15e0SLoGin         let slice = unsafe {
4240fe15e0SLoGin             core::slice::from_raw_parts_mut(
4340fe15e0SLoGin                 virt_addr.data() as *mut u8,
4440fe15e0SLoGin                 allocated_frame_count.data() * MMArch::PAGE_SIZE,
4540fe15e0SLoGin             )
4640fe15e0SLoGin         };
4740fe15e0SLoGin         return Ok(NonNull::from(slice));
4840fe15e0SLoGin     }
4940fe15e0SLoGin 
5040fe15e0SLoGin     unsafe fn free_in_buddy(&self, ptr: *mut u8, layout: Layout) {
5140fe15e0SLoGin         // 由于buddy分配的页数量是2的幂,因此释放的时候也需要按照2的幂向上取整。
5240fe15e0SLoGin         let count = (page_align_up(layout.size()) / MMArch::PAGE_SIZE).next_power_of_two();
5340fe15e0SLoGin         let page_frame_count = PageFrameCount::new(count);
5440fe15e0SLoGin         let phy_addr = MMArch::virt_2_phys(VirtAddr::new(ptr as usize)).unwrap();
5540fe15e0SLoGin         LockedFrameAllocator.free(phy_addr, page_frame_count);
5640fe15e0SLoGin     }
5740fe15e0SLoGin }
5840fe15e0SLoGin 
5940fe15e0SLoGin /// 为内核SLAB分配器实现LocalAlloc的trait
6040fe15e0SLoGin impl LocalAlloc for KernelAllocator {
6140fe15e0SLoGin     unsafe fn local_alloc(&self, layout: Layout) -> *mut u8 {
6240fe15e0SLoGin         return self
6340fe15e0SLoGin             .alloc_in_buddy(layout)
6440fe15e0SLoGin             .map(|x| x.as_mut_ptr() as *mut u8)
6540fe15e0SLoGin             .unwrap_or(core::ptr::null_mut() as *mut u8);
6640fe15e0SLoGin     }
6740fe15e0SLoGin 
6840fe15e0SLoGin     unsafe fn local_alloc_zeroed(&self, layout: Layout) -> *mut u8 {
6940fe15e0SLoGin         return self
7040fe15e0SLoGin             .alloc_in_buddy(layout)
7140fe15e0SLoGin             .map(|x| {
7240fe15e0SLoGin                 let ptr: *mut u8 = x.as_mut_ptr();
7340fe15e0SLoGin                 core::ptr::write_bytes(ptr, 0, x.len());
7440fe15e0SLoGin                 ptr
7540fe15e0SLoGin             })
7640fe15e0SLoGin             .unwrap_or(core::ptr::null_mut() as *mut u8);
7740fe15e0SLoGin     }
7840fe15e0SLoGin 
7940fe15e0SLoGin     unsafe fn local_dealloc(&self, ptr: *mut u8, layout: Layout) {
8040fe15e0SLoGin         self.free_in_buddy(ptr, layout);
8140fe15e0SLoGin     }
8240fe15e0SLoGin }
8340fe15e0SLoGin 
8440fe15e0SLoGin /// 为内核slab分配器实现GlobalAlloc特性
8540fe15e0SLoGin unsafe impl GlobalAlloc for KernelAllocator {
8640fe15e0SLoGin     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
87*7b32f508SLoGin         let r = self.local_alloc(layout);
88*7b32f508SLoGin         mm_debug_log(
89*7b32f508SLoGin             klog_types::AllocatorLogType::Alloc(AllocLogItem::new(
90*7b32f508SLoGin                 layout.clone(),
91*7b32f508SLoGin                 Some(r as usize),
92*7b32f508SLoGin                 None,
93*7b32f508SLoGin             )),
94*7b32f508SLoGin             klog_types::LogSource::Buddy,
95*7b32f508SLoGin         );
96*7b32f508SLoGin 
97*7b32f508SLoGin         return r;
98*7b32f508SLoGin 
9940fe15e0SLoGin         // self.local_alloc_zeroed(layout, 0)
10040fe15e0SLoGin     }
10140fe15e0SLoGin 
10240fe15e0SLoGin     unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
103*7b32f508SLoGin         let r = self.local_alloc_zeroed(layout);
104*7b32f508SLoGin 
105*7b32f508SLoGin         mm_debug_log(
106*7b32f508SLoGin             klog_types::AllocatorLogType::AllocZeroed(AllocLogItem::new(
107*7b32f508SLoGin                 layout.clone(),
108*7b32f508SLoGin                 Some(r as usize),
109*7b32f508SLoGin                 None,
110*7b32f508SLoGin             )),
111*7b32f508SLoGin             klog_types::LogSource::Buddy,
112*7b32f508SLoGin         );
113*7b32f508SLoGin 
114*7b32f508SLoGin         return r;
11540fe15e0SLoGin     }
11640fe15e0SLoGin 
11740fe15e0SLoGin     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
118*7b32f508SLoGin         mm_debug_log(
119*7b32f508SLoGin             klog_types::AllocatorLogType::Free(AllocLogItem::new(
120*7b32f508SLoGin                 layout.clone(),
121*7b32f508SLoGin                 Some(ptr as usize),
122*7b32f508SLoGin                 None,
123*7b32f508SLoGin             )),
124*7b32f508SLoGin             klog_types::LogSource::Buddy,
125*7b32f508SLoGin         );
126*7b32f508SLoGin 
12740fe15e0SLoGin         self.local_dealloc(ptr, layout);
12840fe15e0SLoGin     }
12940fe15e0SLoGin }
13040fe15e0SLoGin 
13140314b30SXiaoye Zheng /// 为内核slab分配器实现Allocator特性
13240314b30SXiaoye Zheng // unsafe impl Allocator for KernelAllocator {
13340314b30SXiaoye Zheng //     fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
13440314b30SXiaoye Zheng //         let memory = unsafe {self.local_alloc(layout)};
13540314b30SXiaoye Zheng //         if memory.is_null() {
13640314b30SXiaoye Zheng //             Err(AllocError)
13740314b30SXiaoye Zheng //         } else {
13840314b30SXiaoye Zheng //             let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) };
13940314b30SXiaoye Zheng //             Ok(unsafe { NonNull::new_unchecked(slice) })
14040314b30SXiaoye Zheng //         }
14140314b30SXiaoye Zheng //     }
14240314b30SXiaoye Zheng 
14340314b30SXiaoye Zheng //     fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
14440314b30SXiaoye Zheng //         let memory = unsafe {self.local_alloc_zeroed(layout)};
14540314b30SXiaoye Zheng //         if memory.is_null() {
14640314b30SXiaoye Zheng //             Err(AllocError)
14740314b30SXiaoye Zheng //         } else {
14840314b30SXiaoye Zheng //             let slice = unsafe { core::slice::from_raw_parts_mut(memory, layout.size()) };
14940314b30SXiaoye Zheng //             Ok(unsafe { NonNull::new_unchecked(slice) })
15040314b30SXiaoye Zheng //         }
15140314b30SXiaoye Zheng //     }
15240314b30SXiaoye Zheng 
15340314b30SXiaoye Zheng //     unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
15440314b30SXiaoye Zheng //         self.local_dealloc(ptr.cast().as_ptr(), layout);
15540314b30SXiaoye Zheng //     }
15640314b30SXiaoye Zheng // }
15740314b30SXiaoye Zheng 
15840fe15e0SLoGin /// 内存分配错误处理函数
159fba56231SLoGin #[cfg(target_os = "none")]
16040fe15e0SLoGin #[alloc_error_handler]
16140fe15e0SLoGin pub fn global_alloc_err_handler(layout: Layout) -> ! {
16240fe15e0SLoGin     panic!("global_alloc_error, layout: {:?}", layout);
16340fe15e0SLoGin }
164