c_adapter.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //! 这是暴露给C的接口,用于在C语言中使用Rust的内存分配器。
  2. use core::intrinsics::unlikely;
  3. use alloc::vec::Vec;
  4. use hashbrown::HashMap;
  5. use system_error::SystemError;
  6. use crate::{
  7. include::bindings::bindings::{gfp_t, PAGE_U_S},
  8. kerror,
  9. libs::{align::page_align_up, spinlock::SpinLock},
  10. mm::MMArch,
  11. };
  12. use super::{
  13. allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, mmio_buddy::mmio_pool,
  14. no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
  15. };
  16. lazy_static! {
  17. // 用于记录内核分配给C的空间信息
  18. static ref C_ALLOCATION_MAP: SpinLock<HashMap<VirtAddr, (VirtAddr, usize, usize)>> = SpinLock::new(HashMap::new());
  19. }
  20. /// [EXTERN TO C] Use pseudo mapper to map physical memory to virtual memory.
  21. #[no_mangle]
  22. pub unsafe extern "C" fn rs_pseudo_map_phys(vaddr: usize, paddr: usize, size: usize) {
  23. let vaddr = VirtAddr::new(vaddr);
  24. let paddr = PhysAddr::new(paddr);
  25. let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
  26. pseudo_map_phys(vaddr, paddr, count);
  27. }
  28. /// [EXTERN TO C] Use kernel mapper to map physical memory to virtual memory.
  29. #[no_mangle]
  30. pub unsafe extern "C" fn rs_map_phys(vaddr: usize, paddr: usize, size: usize, flags: usize) {
  31. let mut vaddr = VirtAddr::new(vaddr);
  32. let mut paddr = PhysAddr::new(paddr);
  33. let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
  34. // kdebug!("rs_map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}");
  35. let mut page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true);
  36. if flags & PAGE_U_S as usize != 0 {
  37. page_flags = page_flags.set_user(true);
  38. }
  39. let mut kernel_mapper = KernelMapper::lock();
  40. let mut kernel_mapper = kernel_mapper.as_mut();
  41. assert!(kernel_mapper.is_some());
  42. for _i in 0..count.data() {
  43. let flusher = kernel_mapper
  44. .as_mut()
  45. .unwrap()
  46. .map_phys(vaddr, paddr, page_flags)
  47. .unwrap();
  48. flusher.flush();
  49. vaddr += MMArch::PAGE_SIZE;
  50. paddr += MMArch::PAGE_SIZE;
  51. }
  52. }
  53. #[no_mangle]
  54. pub unsafe extern "C" fn kzalloc(size: usize, _gfp: gfp_t) -> usize {
  55. // kdebug!("kzalloc: size: {size}");
  56. return do_kmalloc(size, true);
  57. }
  58. #[no_mangle]
  59. pub unsafe extern "C" fn kmalloc(size: usize, _gfp: gfp_t) -> usize {
  60. // kdebug!("kmalloc: size: {size}");
  61. // 由于C代码不规范,因此都全部清空
  62. return do_kmalloc(size, true);
  63. }
  64. fn do_kmalloc(size: usize, _zero: bool) -> usize {
  65. let space: Vec<u8> = vec![0u8; size];
  66. assert!(space.len() == size);
  67. let (ptr, len, cap) = space.into_raw_parts();
  68. if !ptr.is_null() {
  69. let vaddr = VirtAddr::new(ptr as usize);
  70. let len = len as usize;
  71. let cap = cap as usize;
  72. let mut guard = C_ALLOCATION_MAP.lock();
  73. if unlikely(guard.contains_key(&vaddr)) {
  74. drop(guard);
  75. unsafe {
  76. drop(Vec::from_raw_parts(vaddr.data() as *mut u8, len, cap));
  77. }
  78. panic!(
  79. "do_kmalloc: vaddr {:?} already exists in C Allocation Map, query size: {size}, zero: {_zero}",
  80. vaddr
  81. );
  82. }
  83. // 插入到C Allocation Map中
  84. guard.insert(vaddr, (vaddr, len, cap));
  85. return vaddr.data();
  86. } else {
  87. return SystemError::ENOMEM.to_posix_errno() as i64 as usize;
  88. }
  89. }
  90. #[no_mangle]
  91. pub unsafe extern "C" fn kfree(vaddr: usize) -> usize {
  92. let vaddr = VirtAddr::new(vaddr);
  93. let mut guard = C_ALLOCATION_MAP.lock();
  94. let p = guard.remove(&vaddr);
  95. drop(guard);
  96. if p.is_none() {
  97. kerror!("kfree: vaddr {:?} not found in C Allocation Map", vaddr);
  98. return SystemError::EINVAL.to_posix_errno() as i64 as usize;
  99. }
  100. let (vaddr, len, cap) = p.unwrap();
  101. drop(Vec::from_raw_parts(vaddr.data() as *mut u8, len, cap));
  102. return 0;
  103. }
  104. /// @brief 创建一块mmio区域,并将vma绑定到initial_mm
  105. ///
  106. /// @param size mmio区域的大小(字节)
  107. ///
  108. /// @param vm_flags 要把vma设置成的标志
  109. ///
  110. /// @param res_vaddr 返回值-分配得到的虚拟地址
  111. ///
  112. /// @param res_length 返回值-分配的虚拟地址空间长度
  113. ///
  114. /// @return int 错误码
  115. #[no_mangle]
  116. unsafe extern "C" fn rs_mmio_create(
  117. size: u32,
  118. _vm_flags: u64,
  119. res_vaddr: *mut u64,
  120. res_length: *mut u64,
  121. ) -> i32 {
  122. // kdebug!("mmio_create");
  123. let r = mmio_pool().create_mmio(size as usize);
  124. if r.is_err() {
  125. return r.unwrap_err().to_posix_errno();
  126. }
  127. let space_guard = r.unwrap();
  128. *res_vaddr = space_guard.vaddr().data() as u64;
  129. *res_length = space_guard.size() as u64;
  130. // 由于space_guard drop的时候会自动释放内存,所以这里要忽略它的释放
  131. core::mem::forget(space_guard);
  132. return 0;
  133. }
  134. /// @brief 取消mmio的映射并将地址空间归还到buddy中
  135. ///
  136. /// @param vaddr 起始的虚拟地址
  137. ///
  138. /// @param length 要归还的地址空间的长度
  139. ///
  140. /// @return Ok(i32) 成功返回0
  141. ///
  142. /// @return Err(i32) 失败返回错误码
  143. #[no_mangle]
  144. pub unsafe extern "C" fn rs_mmio_release(vaddr: u64, length: u64) -> i32 {
  145. return mmio_pool()
  146. .release_mmio(VirtAddr::new(vaddr as usize), length as usize)
  147. .unwrap_or_else(|err| err.to_posix_errno());
  148. }