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