xref: /DragonOS/kernel/src/mm/c_adapter.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
140fe15e0SLoGin //! 这是暴露给C的接口,用于在C语言中使用Rust的内存分配器。
240fe15e0SLoGin 
340fe15e0SLoGin use core::intrinsics::unlikely;
440fe15e0SLoGin 
540fe15e0SLoGin use alloc::vec::Vec;
640fe15e0SLoGin use hashbrown::HashMap;
7*2eab6dd7S曾俊 use log::error;
891e9d4abSLoGin use system_error::SystemError;
940fe15e0SLoGin 
1040fe15e0SLoGin use crate::{
1146e234aeSLoGin     include::bindings::bindings::{gfp_t, PAGE_U_S},
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);
41*2eab6dd7S曾俊     // debug!("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 {
67*2eab6dd7S曾俊     // debug!("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 {
73*2eab6dd7S曾俊     // debug!("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() {
112*2eab6dd7S曾俊         error!("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 {
138*2eab6dd7S曾俊     // debug!("mmio_create");
1397eda31b2SLoGin     let r = mmio_pool().create_mmio(size as usize);
140b5b571e0SLoGin     if let Err(e) = r {
141b5b571e0SLoGin         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