1 //! 这是暴露给C的接口,用于在C语言中使用Rust的内存分配器。
2
3 use core::intrinsics::unlikely;
4
5 use alloc::vec::Vec;
6 use hashbrown::HashMap;
7
8 use crate::{
9 arch::mm::LowAddressRemapping,
10 include::bindings::bindings::{gfp_t, PAGE_U_S},
11 kerror,
12 libs::{align::page_align_up, spinlock::SpinLock},
13 mm::MMArch,
14 syscall::SystemError,
15 };
16
17 use super::{
18 allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, no_init::pseudo_map_phys,
19 page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
20 };
21
22 lazy_static! {
23 // 用于记录内核分配给C的空间信息
24 static ref C_ALLOCATION_MAP: SpinLock<HashMap<VirtAddr, (VirtAddr, usize, usize)>> = SpinLock::new(HashMap::new());
25 }
26
27 /// [EXTERN TO C] Use pseudo mapper to map physical memory to virtual memory.
28 #[no_mangle]
rs_pseudo_map_phys(vaddr: usize, paddr: usize, size: usize)29 pub unsafe extern "C" fn rs_pseudo_map_phys(vaddr: usize, paddr: usize, size: usize) {
30 let vaddr = VirtAddr::new(vaddr);
31 let paddr = PhysAddr::new(paddr);
32 let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
33 pseudo_map_phys(vaddr, paddr, count);
34 }
35
36 /// [EXTERN TO C] Use kernel mapper to map physical memory to virtual memory.
37 #[no_mangle]
rs_map_phys(vaddr: usize, paddr: usize, size: usize, flags: usize)38 pub unsafe extern "C" fn rs_map_phys(vaddr: usize, paddr: usize, size: usize, flags: usize) {
39 let mut vaddr = VirtAddr::new(vaddr);
40 let mut paddr = PhysAddr::new(paddr);
41 let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
42 // kdebug!("rs_map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}");
43
44 let mut page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true);
45 if flags & PAGE_U_S as usize != 0 {
46 page_flags = page_flags.set_user(true);
47 }
48
49 let mut kernel_mapper = KernelMapper::lock();
50 let mut kernel_mapper = kernel_mapper.as_mut();
51 assert!(kernel_mapper.is_some());
52 for _i in 0..count.data() {
53 let flusher = kernel_mapper
54 .as_mut()
55 .unwrap()
56 .map_phys(vaddr, paddr, page_flags)
57 .unwrap();
58
59 flusher.flush();
60
61 vaddr += MMArch::PAGE_SIZE;
62 paddr += MMArch::PAGE_SIZE;
63 }
64 }
65
66 #[no_mangle]
kzalloc(size: usize, _gfp: gfp_t) -> usize67 pub unsafe extern "C" fn kzalloc(size: usize, _gfp: gfp_t) -> usize {
68 // kdebug!("kzalloc: size: {size}");
69 return do_kmalloc(size, true);
70 }
71
72 #[no_mangle]
kmalloc(size: usize, _gfp: gfp_t) -> usize73 pub unsafe extern "C" fn kmalloc(size: usize, _gfp: gfp_t) -> usize {
74 // kdebug!("kmalloc: size: {size}");
75 // 由于C代码不规范,因此都全部清空
76 return do_kmalloc(size, true);
77 }
78
do_kmalloc(size: usize, zero: bool) -> usize79 fn do_kmalloc(size: usize, zero: bool) -> usize {
80 let space: Vec<u8> = if zero {
81 vec![0u8; size]
82 } else {
83 let mut v = Vec::with_capacity(size);
84 unsafe {
85 v.set_len(size);
86 }
87 v
88 };
89
90 assert!(space.len() == size);
91 let (ptr, len, cap) = space.into_raw_parts();
92 if !ptr.is_null() {
93 let vaddr = VirtAddr::new(ptr as usize);
94 let len = len as usize;
95 let cap = cap as usize;
96 let mut guard = C_ALLOCATION_MAP.lock();
97 if unlikely(guard.contains_key(&vaddr)) {
98 drop(guard);
99 unsafe {
100 drop(Vec::from_raw_parts(vaddr.data() as *mut u8, len, cap));
101 }
102 panic!(
103 "do_kmalloc: vaddr {:?} already exists in C Allocation Map, query size: {size}, zero: {zero}",
104 vaddr
105 );
106 }
107 // 插入到C Allocation Map中
108 guard.insert(vaddr, (vaddr, len, cap));
109 return vaddr.data();
110 } else {
111 return SystemError::ENOMEM.to_posix_errno() as i64 as usize;
112 }
113 }
114
115 #[no_mangle]
kfree(vaddr: usize) -> usize116 pub unsafe extern "C" fn kfree(vaddr: usize) -> usize {
117 let vaddr = VirtAddr::new(vaddr);
118 let mut guard = C_ALLOCATION_MAP.lock();
119 let p = guard.remove(&vaddr);
120 drop(guard);
121
122 if p.is_none() {
123 kerror!("kfree: vaddr {:?} not found in C Allocation Map", vaddr);
124 return SystemError::EINVAL.to_posix_errno() as i64 as usize;
125 }
126 let (vaddr, len, cap) = p.unwrap();
127 drop(Vec::from_raw_parts(vaddr.data() as *mut u8, len, cap));
128 return 0;
129 }
130
131 #[no_mangle]
rs_unmap_at_low_addr() -> usize132 pub unsafe extern "C" fn rs_unmap_at_low_addr() -> usize {
133 LowAddressRemapping::unmap_at_low_address(true);
134 return 0;
135 }
136