xref: /DragonOS/kernel/src/mm/c_adapter.rs (revision 2b7818e80e00fcfe4d03533f587cc125ea5e4bec)
140fe15e0SLoGin //! 这是暴露给C的接口,用于在C语言中使用Rust的内存分配器。
240fe15e0SLoGin 
340fe15e0SLoGin use core::intrinsics::unlikely;
440fe15e0SLoGin 
540fe15e0SLoGin use alloc::vec::Vec;
640fe15e0SLoGin use hashbrown::HashMap;
72eab6dd7S曾俊 use log::error;
891e9d4abSLoGin use system_error::SystemError;
940fe15e0SLoGin 
10*2b7818e8SLoGin use crate::libs::spinlock::SpinLock;
1140fe15e0SLoGin 
12*2b7818e8SLoGin use super::{mmio_buddy::mmio_pool, VirtAddr};
1340fe15e0SLoGin 
1440fe15e0SLoGin lazy_static! {
1540fe15e0SLoGin     // 用于记录内核分配给C的空间信息
1640fe15e0SLoGin     static ref C_ALLOCATION_MAP: SpinLock<HashMap<VirtAddr, (VirtAddr, usize, usize)>> = SpinLock::new(HashMap::new());
1740fe15e0SLoGin }
1840fe15e0SLoGin 
1940fe15e0SLoGin #[no_mangle]
kzalloc(size: usize, _gfp: u64) -> usize20*2b7818e8SLoGin pub unsafe extern "C" fn kzalloc(size: usize, _gfp: u64) -> usize {
212eab6dd7S曾俊     // debug!("kzalloc: size: {size}");
2240fe15e0SLoGin     return do_kmalloc(size, true);
2340fe15e0SLoGin }
2440fe15e0SLoGin 
2540fe15e0SLoGin #[no_mangle]
kmalloc(size: usize, _gfp: u64) -> usize26*2b7818e8SLoGin pub unsafe extern "C" fn kmalloc(size: usize, _gfp: u64) -> usize {
272eab6dd7S曾俊     // debug!("kmalloc: size: {size}");
2840fe15e0SLoGin     // 由于C代码不规范,因此都全部清空
2940fe15e0SLoGin     return do_kmalloc(size, true);
3040fe15e0SLoGin }
3140fe15e0SLoGin 
do_kmalloc(size: usize, _zero: bool) -> usize327ae679ddSLoGin fn do_kmalloc(size: usize, _zero: bool) -> usize {
337ae679ddSLoGin     let space: Vec<u8> = vec![0u8; size];
3440fe15e0SLoGin 
3540fe15e0SLoGin     assert!(space.len() == size);
3640fe15e0SLoGin     let (ptr, len, cap) = space.into_raw_parts();
3740fe15e0SLoGin     if !ptr.is_null() {
3840fe15e0SLoGin         let vaddr = VirtAddr::new(ptr as usize);
3940fe15e0SLoGin         let mut guard = C_ALLOCATION_MAP.lock();
4040fe15e0SLoGin         if unlikely(guard.contains_key(&vaddr)) {
4140fe15e0SLoGin             drop(guard);
4240fe15e0SLoGin             unsafe {
4340fe15e0SLoGin                 drop(Vec::from_raw_parts(vaddr.data() as *mut u8, len, cap));
4440fe15e0SLoGin             }
4540fe15e0SLoGin             panic!(
467ae679ddSLoGin                 "do_kmalloc: vaddr {:?} already exists in C Allocation Map, query size: {size}, zero: {_zero}",
4740fe15e0SLoGin                 vaddr
4840fe15e0SLoGin             );
4940fe15e0SLoGin         }
5040fe15e0SLoGin         // 插入到C Allocation Map中
5140fe15e0SLoGin         guard.insert(vaddr, (vaddr, len, cap));
5240fe15e0SLoGin         return vaddr.data();
5340fe15e0SLoGin     } else {
5440fe15e0SLoGin         return SystemError::ENOMEM.to_posix_errno() as i64 as usize;
5540fe15e0SLoGin     }
5640fe15e0SLoGin }
5740fe15e0SLoGin 
5840fe15e0SLoGin #[no_mangle]
kfree(vaddr: usize) -> usize5940fe15e0SLoGin pub unsafe extern "C" fn kfree(vaddr: usize) -> usize {
6040fe15e0SLoGin     let vaddr = VirtAddr::new(vaddr);
6140fe15e0SLoGin     let mut guard = C_ALLOCATION_MAP.lock();
6240fe15e0SLoGin     let p = guard.remove(&vaddr);
6340fe15e0SLoGin     drop(guard);
6440fe15e0SLoGin 
6540fe15e0SLoGin     if p.is_none() {
662eab6dd7S曾俊         error!("kfree: vaddr {:?} not found in C Allocation Map", vaddr);
6740fe15e0SLoGin         return SystemError::EINVAL.to_posix_errno() as i64 as usize;
6840fe15e0SLoGin     }
6940fe15e0SLoGin     let (vaddr, len, cap) = p.unwrap();
7040fe15e0SLoGin     drop(Vec::from_raw_parts(vaddr.data() as *mut u8, len, cap));
7140fe15e0SLoGin     return 0;
7240fe15e0SLoGin }
7340fe15e0SLoGin 
747eda31b2SLoGin /// @brief 创建一块mmio区域,并将vma绑定到initial_mm
757eda31b2SLoGin ///
767eda31b2SLoGin /// @param size mmio区域的大小(字节)
777eda31b2SLoGin ///
787eda31b2SLoGin /// @param vm_flags 要把vma设置成的标志
797eda31b2SLoGin ///
807eda31b2SLoGin /// @param res_vaddr 返回值-分配得到的虚拟地址
817eda31b2SLoGin ///
827eda31b2SLoGin /// @param res_length 返回值-分配的虚拟地址空间长度
837eda31b2SLoGin ///
847eda31b2SLoGin /// @return int 错误码
857eda31b2SLoGin #[no_mangle]
rs_mmio_create( size: u32, _vm_flags: u64, res_vaddr: *mut u64, res_length: *mut u64, ) -> i32867eda31b2SLoGin unsafe extern "C" fn rs_mmio_create(
877eda31b2SLoGin     size: u32,
8846e234aeSLoGin     _vm_flags: u64,
897eda31b2SLoGin     res_vaddr: *mut u64,
907eda31b2SLoGin     res_length: *mut u64,
917eda31b2SLoGin ) -> i32 {
922eab6dd7S曾俊     // debug!("mmio_create");
937eda31b2SLoGin     let r = mmio_pool().create_mmio(size as usize);
94b5b571e0SLoGin     if let Err(e) = r {
95b5b571e0SLoGin         return e.to_posix_errno();
967eda31b2SLoGin     }
977eda31b2SLoGin     let space_guard = r.unwrap();
987eda31b2SLoGin     *res_vaddr = space_guard.vaddr().data() as u64;
997eda31b2SLoGin     *res_length = space_guard.size() as u64;
1007eda31b2SLoGin     // 由于space_guard drop的时候会自动释放内存,所以这里要忽略它的释放
1017eda31b2SLoGin     core::mem::forget(space_guard);
1027eda31b2SLoGin     return 0;
1037eda31b2SLoGin }
1047eda31b2SLoGin 
1057eda31b2SLoGin /// @brief 取消mmio的映射并将地址空间归还到buddy中
1067eda31b2SLoGin ///
1077eda31b2SLoGin /// @param vaddr 起始的虚拟地址
1087eda31b2SLoGin ///
1097eda31b2SLoGin /// @param length 要归还的地址空间的长度
1107eda31b2SLoGin ///
1117eda31b2SLoGin /// @return Ok(i32) 成功返回0
1127eda31b2SLoGin ///
1137eda31b2SLoGin /// @return Err(i32) 失败返回错误码
1147eda31b2SLoGin #[no_mangle]
rs_mmio_release(vaddr: u64, length: u64) -> i321157eda31b2SLoGin pub unsafe extern "C" fn rs_mmio_release(vaddr: u64, length: u64) -> i32 {
1167eda31b2SLoGin     return mmio_pool()
1177eda31b2SLoGin         .release_mmio(VirtAddr::new(vaddr as usize), length as usize)
1187eda31b2SLoGin         .unwrap_or_else(|err| err.to_posix_errno());
1197eda31b2SLoGin }
120