140fe15e0SLoGin //! 这是暴露给C的接口,用于在C语言中使用Rust的内存分配器。 240fe15e0SLoGin 340fe15e0SLoGin use core::intrinsics::unlikely; 440fe15e0SLoGin 540fe15e0SLoGin use alloc::vec::Vec; 640fe15e0SLoGin use hashbrown::HashMap; 791e9d4abSLoGin use system_error::SystemError; 840fe15e0SLoGin 940fe15e0SLoGin use crate::{ 1046e234aeSLoGin include::bindings::bindings::{gfp_t, PAGE_U_S}, 1140fe15e0SLoGin kerror, 1240fe15e0SLoGin libs::{align::page_align_up, spinlock::SpinLock}, 1340fe15e0SLoGin mm::MMArch, 1440fe15e0SLoGin }; 1540fe15e0SLoGin 1640fe15e0SLoGin use super::{ 175b59005fSLoGin allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, mmio_buddy::mmio_pool, 185b59005fSLoGin no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr, 1940fe15e0SLoGin }; 2040fe15e0SLoGin 2140fe15e0SLoGin lazy_static! { 2240fe15e0SLoGin // 用于记录内核分配给C的空间信息 2340fe15e0SLoGin static ref C_ALLOCATION_MAP: SpinLock<HashMap<VirtAddr, (VirtAddr, usize, usize)>> = SpinLock::new(HashMap::new()); 2440fe15e0SLoGin } 2540fe15e0SLoGin 2640fe15e0SLoGin /// [EXTERN TO C] Use pseudo mapper to map physical memory to virtual memory. 2740fe15e0SLoGin #[no_mangle] 2840fe15e0SLoGin pub unsafe extern "C" fn rs_pseudo_map_phys(vaddr: usize, paddr: usize, size: usize) { 2940fe15e0SLoGin let vaddr = VirtAddr::new(vaddr); 3040fe15e0SLoGin let paddr = PhysAddr::new(paddr); 3140fe15e0SLoGin let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE); 3240fe15e0SLoGin pseudo_map_phys(vaddr, paddr, count); 3340fe15e0SLoGin } 3440fe15e0SLoGin 3540fe15e0SLoGin /// [EXTERN TO C] Use kernel mapper to map physical memory to virtual memory. 3640fe15e0SLoGin #[no_mangle] 3740fe15e0SLoGin pub unsafe extern "C" fn rs_map_phys(vaddr: usize, paddr: usize, size: usize, flags: usize) { 3840fe15e0SLoGin let mut vaddr = VirtAddr::new(vaddr); 3940fe15e0SLoGin let mut paddr = PhysAddr::new(paddr); 4040fe15e0SLoGin let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE); 4140fe15e0SLoGin // kdebug!("rs_map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}"); 4240fe15e0SLoGin 4340fe15e0SLoGin let mut page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true); 4440fe15e0SLoGin if flags & PAGE_U_S as usize != 0 { 4540fe15e0SLoGin page_flags = page_flags.set_user(true); 4640fe15e0SLoGin } 4740fe15e0SLoGin 4840fe15e0SLoGin let mut kernel_mapper = KernelMapper::lock(); 4940fe15e0SLoGin let mut kernel_mapper = kernel_mapper.as_mut(); 5040fe15e0SLoGin assert!(kernel_mapper.is_some()); 5140fe15e0SLoGin for _i in 0..count.data() { 5240fe15e0SLoGin let flusher = kernel_mapper 5340fe15e0SLoGin .as_mut() 5440fe15e0SLoGin .unwrap() 5540fe15e0SLoGin .map_phys(vaddr, paddr, page_flags) 5640fe15e0SLoGin .unwrap(); 5740fe15e0SLoGin 5840fe15e0SLoGin flusher.flush(); 5940fe15e0SLoGin 6040fe15e0SLoGin vaddr += MMArch::PAGE_SIZE; 6140fe15e0SLoGin paddr += MMArch::PAGE_SIZE; 6240fe15e0SLoGin } 6340fe15e0SLoGin } 6440fe15e0SLoGin 6540fe15e0SLoGin #[no_mangle] 6640fe15e0SLoGin pub unsafe extern "C" fn kzalloc(size: usize, _gfp: gfp_t) -> usize { 6740fe15e0SLoGin // kdebug!("kzalloc: size: {size}"); 6840fe15e0SLoGin return do_kmalloc(size, true); 6940fe15e0SLoGin } 7040fe15e0SLoGin 7140fe15e0SLoGin #[no_mangle] 7240fe15e0SLoGin pub unsafe extern "C" fn kmalloc(size: usize, _gfp: gfp_t) -> usize { 7340fe15e0SLoGin // kdebug!("kmalloc: size: {size}"); 7440fe15e0SLoGin // 由于C代码不规范,因此都全部清空 7540fe15e0SLoGin return do_kmalloc(size, true); 7640fe15e0SLoGin } 7740fe15e0SLoGin 787ae679ddSLoGin fn do_kmalloc(size: usize, _zero: bool) -> usize { 797ae679ddSLoGin let space: Vec<u8> = vec![0u8; size]; 8040fe15e0SLoGin 8140fe15e0SLoGin assert!(space.len() == size); 8240fe15e0SLoGin let (ptr, len, cap) = space.into_raw_parts(); 8340fe15e0SLoGin if !ptr.is_null() { 8440fe15e0SLoGin let vaddr = VirtAddr::new(ptr as usize); 8540fe15e0SLoGin let mut guard = C_ALLOCATION_MAP.lock(); 8640fe15e0SLoGin if unlikely(guard.contains_key(&vaddr)) { 8740fe15e0SLoGin drop(guard); 8840fe15e0SLoGin unsafe { 8940fe15e0SLoGin drop(Vec::from_raw_parts(vaddr.data() as *mut u8, len, cap)); 9040fe15e0SLoGin } 9140fe15e0SLoGin panic!( 927ae679ddSLoGin "do_kmalloc: vaddr {:?} already exists in C Allocation Map, query size: {size}, zero: {_zero}", 9340fe15e0SLoGin vaddr 9440fe15e0SLoGin ); 9540fe15e0SLoGin } 9640fe15e0SLoGin // 插入到C Allocation Map中 9740fe15e0SLoGin guard.insert(vaddr, (vaddr, len, cap)); 9840fe15e0SLoGin return vaddr.data(); 9940fe15e0SLoGin } else { 10040fe15e0SLoGin return SystemError::ENOMEM.to_posix_errno() as i64 as usize; 10140fe15e0SLoGin } 10240fe15e0SLoGin } 10340fe15e0SLoGin 10440fe15e0SLoGin #[no_mangle] 10540fe15e0SLoGin pub unsafe extern "C" fn kfree(vaddr: usize) -> usize { 10640fe15e0SLoGin let vaddr = VirtAddr::new(vaddr); 10740fe15e0SLoGin let mut guard = C_ALLOCATION_MAP.lock(); 10840fe15e0SLoGin let p = guard.remove(&vaddr); 10940fe15e0SLoGin drop(guard); 11040fe15e0SLoGin 11140fe15e0SLoGin if p.is_none() { 11240fe15e0SLoGin kerror!("kfree: vaddr {:?} not found in C Allocation Map", vaddr); 11340fe15e0SLoGin return SystemError::EINVAL.to_posix_errno() as i64 as usize; 11440fe15e0SLoGin } 11540fe15e0SLoGin let (vaddr, len, cap) = p.unwrap(); 11640fe15e0SLoGin drop(Vec::from_raw_parts(vaddr.data() as *mut u8, len, cap)); 11740fe15e0SLoGin return 0; 11840fe15e0SLoGin } 11940fe15e0SLoGin 1207eda31b2SLoGin /// @brief 创建一块mmio区域,并将vma绑定到initial_mm 1217eda31b2SLoGin /// 1227eda31b2SLoGin /// @param size mmio区域的大小(字节) 1237eda31b2SLoGin /// 1247eda31b2SLoGin /// @param vm_flags 要把vma设置成的标志 1257eda31b2SLoGin /// 1267eda31b2SLoGin /// @param res_vaddr 返回值-分配得到的虚拟地址 1277eda31b2SLoGin /// 1287eda31b2SLoGin /// @param res_length 返回值-分配的虚拟地址空间长度 1297eda31b2SLoGin /// 1307eda31b2SLoGin /// @return int 错误码 1317eda31b2SLoGin #[no_mangle] 1327eda31b2SLoGin unsafe extern "C" fn rs_mmio_create( 1337eda31b2SLoGin size: u32, 13446e234aeSLoGin _vm_flags: u64, 1357eda31b2SLoGin res_vaddr: *mut u64, 1367eda31b2SLoGin res_length: *mut u64, 1377eda31b2SLoGin ) -> i32 { 1387eda31b2SLoGin // kdebug!("mmio_create"); 1397eda31b2SLoGin let r = mmio_pool().create_mmio(size as usize); 140*b5b571e0SLoGin if let Err(e) = r { 141*b5b571e0SLoGin return e.to_posix_errno(); 1427eda31b2SLoGin } 1437eda31b2SLoGin let space_guard = r.unwrap(); 1447eda31b2SLoGin *res_vaddr = space_guard.vaddr().data() as u64; 1457eda31b2SLoGin *res_length = space_guard.size() as u64; 1467eda31b2SLoGin // 由于space_guard drop的时候会自动释放内存,所以这里要忽略它的释放 1477eda31b2SLoGin core::mem::forget(space_guard); 1487eda31b2SLoGin return 0; 1497eda31b2SLoGin } 1507eda31b2SLoGin 1517eda31b2SLoGin /// @brief 取消mmio的映射并将地址空间归还到buddy中 1527eda31b2SLoGin /// 1537eda31b2SLoGin /// @param vaddr 起始的虚拟地址 1547eda31b2SLoGin /// 1557eda31b2SLoGin /// @param length 要归还的地址空间的长度 1567eda31b2SLoGin /// 1577eda31b2SLoGin /// @return Ok(i32) 成功返回0 1587eda31b2SLoGin /// 1597eda31b2SLoGin /// @return Err(i32) 失败返回错误码 1607eda31b2SLoGin #[no_mangle] 1617eda31b2SLoGin pub unsafe extern "C" fn rs_mmio_release(vaddr: u64, length: u64) -> i32 { 1627eda31b2SLoGin return mmio_pool() 1637eda31b2SLoGin .release_mmio(VirtAddr::new(vaddr as usize), length as usize) 1647eda31b2SLoGin .unwrap_or_else(|err| err.to_posix_errno()); 1657eda31b2SLoGin } 166