10102d69fSLoGin use crate::libs::align::{page_align_down, page_align_up};
2a7eb62a4Shoumkh use crate::libs::spinlock::{SpinLock, SpinLockGuard};
340fe15e0SLoGin use crate::mm::kernel_mapper::KernelMapper;
423ef2b33SLoGin use crate::mm::page::{PAGE_1G_SHIFT, PAGE_4K_SHIFT};
52eab6dd7S曾俊 use crate::mm::{MMArch, MemoryManagementArch};
61496ba7bSLoGin use crate::process::ProcessManager;
72eab6dd7S曾俊
840fe15e0SLoGin use alloc::{collections::LinkedList, vec::Vec};
940fe15e0SLoGin use core::mem;
1040fe15e0SLoGin use core::mem::MaybeUninit;
1123ef2b33SLoGin use core::sync::atomic::{AtomicBool, Ordering};
122eab6dd7S曾俊 use log::{debug, error, info, warn};
1391e9d4abSLoGin use system_error::SystemError;
1440fe15e0SLoGin
15cf7f801eSMemoryShore use super::page::{EntryFlags, PAGE_4K_SIZE};
162dd9f0c7SLoGin use super::{PhysAddr, VirtAddr};
17c2481452Shoumkh
18c2481452Shoumkh // 最大的伙伴块的幂
1923ef2b33SLoGin const MMIO_BUDDY_MAX_EXP: u32 = PAGE_1G_SHIFT as u32;
20c2481452Shoumkh // 最小的伙伴块的幂
2123ef2b33SLoGin const MMIO_BUDDY_MIN_EXP: u32 = PAGE_4K_SHIFT as u32;
22c2481452Shoumkh // 内存池数组的范围
23c2481452Shoumkh const MMIO_BUDDY_REGION_COUNT: u32 = MMIO_BUDDY_MAX_EXP - MMIO_BUDDY_MIN_EXP + 1;
24c2481452Shoumkh
2540fe15e0SLoGin const PAGE_1G_SIZE: usize = 1 << 30;
2640fe15e0SLoGin
2740fe15e0SLoGin static mut __MMIO_POOL: Option<MmioBuddyMemPool> = None;
2840fe15e0SLoGin
mmio_pool() -> &'static MmioBuddyMemPool297ae679ddSLoGin pub fn mmio_pool() -> &'static MmioBuddyMemPool {
307ae679ddSLoGin unsafe { __MMIO_POOL.as_ref().unwrap() }
31c2481452Shoumkh }
32c2481452Shoumkh
33c2481452Shoumkh pub enum MmioResult {
34c2481452Shoumkh SUCCESS,
35c2481452Shoumkh EINVAL,
36c2481452Shoumkh ENOFOUND,
37c2481452Shoumkh WRONGEXP,
38c2481452Shoumkh ISEMPTY,
39c2481452Shoumkh }
40c2481452Shoumkh
41c2481452Shoumkh /// @brief buddy内存池
4240fe15e0SLoGin #[derive(Debug)]
43c2481452Shoumkh pub struct MmioBuddyMemPool {
4440fe15e0SLoGin pool_start_addr: VirtAddr,
4540fe15e0SLoGin pool_size: usize,
46c2481452Shoumkh free_regions: [SpinLock<MmioFreeRegionList>; MMIO_BUDDY_REGION_COUNT as usize],
47c2481452Shoumkh }
4840fe15e0SLoGin
49c2481452Shoumkh impl MmioBuddyMemPool {
50453452ccSLoGin #[inline(never)]
new() -> Self51c2481452Shoumkh fn new() -> Self {
5240fe15e0SLoGin let mut free_regions: [MaybeUninit<SpinLock<MmioFreeRegionList>>;
5340fe15e0SLoGin MMIO_BUDDY_REGION_COUNT as usize] = unsafe { MaybeUninit::uninit().assume_init() };
5440fe15e0SLoGin for i in 0..MMIO_BUDDY_REGION_COUNT {
5540fe15e0SLoGin free_regions[i as usize] = MaybeUninit::new(SpinLock::new(MmioFreeRegionList::new()));
5640fe15e0SLoGin }
5740fe15e0SLoGin let free_regions = unsafe {
58bd70d2d1SLoGin mem::transmute::<
59bd70d2d1SLoGin [core::mem::MaybeUninit<
60bd70d2d1SLoGin crate::libs::spinlock::SpinLock<crate::mm::mmio_buddy::MmioFreeRegionList>,
61bd70d2d1SLoGin >; MMIO_BUDDY_REGION_COUNT as usize],
62bd70d2d1SLoGin [SpinLock<MmioFreeRegionList>; MMIO_BUDDY_REGION_COUNT as usize],
63bd70d2d1SLoGin >(free_regions)
64c2481452Shoumkh };
6540fe15e0SLoGin
6640fe15e0SLoGin let pool = MmioBuddyMemPool {
6723ef2b33SLoGin pool_start_addr: MMArch::MMIO_BASE,
6823ef2b33SLoGin pool_size: MMArch::MMIO_SIZE,
6940fe15e0SLoGin free_regions,
7040fe15e0SLoGin };
7123ef2b33SLoGin
7223ef2b33SLoGin assert!(pool.pool_start_addr.data() % PAGE_1G_SIZE == 0);
732eab6dd7S曾俊 debug!("MMIO buddy pool init: created");
7440fe15e0SLoGin
7523ef2b33SLoGin let mut vaddr_base = MMArch::MMIO_BASE;
7623ef2b33SLoGin let mut remain_size = MMArch::MMIO_SIZE;
772eab6dd7S曾俊 debug!(
7823ef2b33SLoGin "BASE: {:?}, TOP: {:?}, size: {:?}",
7923ef2b33SLoGin MMArch::MMIO_BASE,
8023ef2b33SLoGin MMArch::MMIO_TOP,
8123ef2b33SLoGin MMArch::MMIO_SIZE
8223ef2b33SLoGin );
8323ef2b33SLoGin
8423ef2b33SLoGin for shift in (PAGE_4K_SHIFT..=PAGE_1G_SHIFT).rev() {
8523ef2b33SLoGin if remain_size & (1 << shift) != 0 {
8623ef2b33SLoGin let ok = pool.give_back_block(vaddr_base, shift as u32).is_ok();
8723ef2b33SLoGin if ok {
8823ef2b33SLoGin vaddr_base += 1 << shift;
8923ef2b33SLoGin remain_size -= 1 << shift;
9023ef2b33SLoGin } else {
9140fe15e0SLoGin panic!("MMIO buddy pool init failed");
9240fe15e0SLoGin }
9340fe15e0SLoGin }
9440fe15e0SLoGin }
9523ef2b33SLoGin
962eab6dd7S曾俊 debug!("MMIO buddy pool init success");
9740fe15e0SLoGin return pool;
98c2481452Shoumkh }
99c2481452Shoumkh
100c2481452Shoumkh /// @brief 创建新的地址区域结构体
101c2481452Shoumkh ///
102c2481452Shoumkh /// @param vaddr 虚拟地址
103c2481452Shoumkh ///
104c2481452Shoumkh /// @return 创建好的地址区域结构体
create_region(&self, vaddr: VirtAddr) -> MmioBuddyAddrRegion10540fe15e0SLoGin fn create_region(&self, vaddr: VirtAddr) -> MmioBuddyAddrRegion {
1062eab6dd7S曾俊 // debug!("create_region for vaddr: {vaddr:?}");
10740fe15e0SLoGin
10840fe15e0SLoGin let region: MmioBuddyAddrRegion = MmioBuddyAddrRegion::new(vaddr);
10940fe15e0SLoGin
1102eab6dd7S曾俊 // debug!("create_region for vaddr: {vaddr:?} OK!!!");
111c2481452Shoumkh return region;
112c2481452Shoumkh }
113c2481452Shoumkh
114c2481452Shoumkh /// @brief 将内存块归还给buddy
115c2481452Shoumkh ///
116c2481452Shoumkh /// @param vaddr 虚拟地址
117c2481452Shoumkh ///
118c2481452Shoumkh /// @param exp 内存空间的大小(2^exp)
119c2481452Shoumkh ///
120c2481452Shoumkh /// @param list_guard 【exp】对应的链表
121c2481452Shoumkh ///
122c2481452Shoumkh /// @return Ok(i32) 返回0
123c2481452Shoumkh ///
124676b8ef6SMork /// @return Err(SystemError) 返回错误码
give_back_block(&self, vaddr: VirtAddr, exp: u32) -> Result<i32, SystemError>12540fe15e0SLoGin fn give_back_block(&self, vaddr: VirtAddr, exp: u32) -> Result<i32, SystemError> {
126c2481452Shoumkh // 确保内存对齐,低位都要为0
12740fe15e0SLoGin if (vaddr.data() & ((1 << exp) - 1)) != 0 {
128676b8ef6SMork return Err(SystemError::EINVAL);
129c2481452Shoumkh }
13040fe15e0SLoGin let region: MmioBuddyAddrRegion = self.create_region(vaddr);
131c2481452Shoumkh // 加入buddy
13240fe15e0SLoGin let mut list_guard = self.free_regions[exp2index(exp)].lock();
13340fe15e0SLoGin
13440fe15e0SLoGin self.push_block(region, &mut list_guard);
135c2481452Shoumkh return Ok(0);
136c2481452Shoumkh }
137c2481452Shoumkh
138c2481452Shoumkh /// @brief 将给定大小为2^{exp}的内存块一分为二,并插入内存块大小为2^{exp-1}的链表中
139c2481452Shoumkh ///
140c2481452Shoumkh /// @param region 要被分割的地址区域结构体(保证其已经从链表中取出)
141c2481452Shoumkh ///
142c2481452Shoumkh /// @param exp 要被分割的地址区域的大小的幂
143c2481452Shoumkh ///
144c2481452Shoumkh /// @param list_guard 【exp-1】对应的链表
split_block( &self, region: MmioBuddyAddrRegion, exp: u32, low_list_guard: &mut SpinLockGuard<MmioFreeRegionList>, )145a7eb62a4Shoumkh fn split_block(
146c2481452Shoumkh &self,
14740fe15e0SLoGin region: MmioBuddyAddrRegion,
148c2481452Shoumkh exp: u32,
149c2481452Shoumkh low_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
150c2481452Shoumkh ) {
15140fe15e0SLoGin let vaddr = self.calculate_block_vaddr(region.vaddr, exp - 1);
15240fe15e0SLoGin let new_region: MmioBuddyAddrRegion = self.create_region(vaddr);
153a7eb62a4Shoumkh self.push_block(region, low_list_guard);
154a7eb62a4Shoumkh self.push_block(new_region, low_list_guard);
155c2481452Shoumkh }
156c2481452Shoumkh
157c2481452Shoumkh /// @brief 从buddy中申请一块指定大小的内存区域
158c2481452Shoumkh ///
159c2481452Shoumkh /// @param exp 要申请的内存块的大小的幂(2^exp)
160c2481452Shoumkh ///
161c2481452Shoumkh /// @param list_guard exp对应的链表
162c2481452Shoumkh ///
16340fe15e0SLoGin /// @return Ok(MmioBuddyAddrRegion) 符合要求的内存区域。
164c2481452Shoumkh ///
165c2481452Shoumkh /// @return Err(MmioResult)
166c2481452Shoumkh /// - 没有满足要求的内存块时,返回ENOFOUND
167c2481452Shoumkh /// - 申请的内存块大小超过合法范围,返回WRONGEXP
168c2481452Shoumkh /// - 调用函数出错时,返回出错函数对应错误码
query_addr_region( &self, exp: u32, list_guard: &mut SpinLockGuard<MmioFreeRegionList>, ) -> Result<MmioBuddyAddrRegion, MmioResult>169a7eb62a4Shoumkh fn query_addr_region(
170c2481452Shoumkh &self,
171c2481452Shoumkh exp: u32,
172c2481452Shoumkh list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
17340fe15e0SLoGin ) -> Result<MmioBuddyAddrRegion, MmioResult> {
174c2481452Shoumkh // 申请范围错误
175b5b571e0SLoGin if !(MMIO_BUDDY_MIN_EXP..=MMIO_BUDDY_MAX_EXP).contains(&exp) {
1762eab6dd7S曾俊 debug!("query_addr_region: exp wrong");
177c2481452Shoumkh return Err(MmioResult::WRONGEXP);
178c2481452Shoumkh }
179c2481452Shoumkh // 没有恰好符合要求的内存块
180c2481452Shoumkh // 注意:exp对应的链表list_guard已上锁【注意避免死锁问题】
181c2481452Shoumkh if list_guard.num_free == 0 {
182c2481452Shoumkh // 找到最小符合申请范围的内存块
183c2481452Shoumkh // 将大的内存块依次分成小块内存,直到能够满足exp大小,即将exp+1分成两块exp
184c2481452Shoumkh for e in exp + 1..MMIO_BUDDY_MAX_EXP + 1 {
185ef9f9732Shoumkh let pop_list: &mut SpinLockGuard<MmioFreeRegionList> =
186b5b571e0SLoGin &mut self.free_regions[exp2index(e)].lock();
187ef9f9732Shoumkh if pop_list.num_free == 0 {
188c2481452Shoumkh continue;
189c2481452Shoumkh }
190ef9f9732Shoumkh
191c2481452Shoumkh for e2 in (exp + 1..e + 1).rev() {
192ef9f9732Shoumkh if e2 == e {
193ef9f9732Shoumkh match self.pop_block(pop_list) {
194ef9f9732Shoumkh Ok(region) => {
195ef9f9732Shoumkh if e2 != exp + 1 {
196ef9f9732Shoumkh // 要将分裂后的内存块插入到更小的链表中
197ef9f9732Shoumkh let low_list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
198b5b571e0SLoGin &mut self.free_regions[exp2index(e2 - 1)].lock();
199ef9f9732Shoumkh self.split_block(region, e2, low_list_guard);
200ef9f9732Shoumkh } else {
201ef9f9732Shoumkh // 由于exp对应的链表list_guard已经被锁住了 不能再加锁
202ef9f9732Shoumkh // 所以直接将list_guard传入
203ef9f9732Shoumkh self.split_block(region, e2, list_guard);
204ef9f9732Shoumkh }
205ef9f9732Shoumkh }
206ef9f9732Shoumkh Err(err) => {
2072eab6dd7S曾俊 debug!("buddy_pop_region get wrong");
208ef9f9732Shoumkh return Err(err);
209ef9f9732Shoumkh }
210ef9f9732Shoumkh }
211ef9f9732Shoumkh } else {
212b5b571e0SLoGin match self.pop_block(&mut self.free_regions[exp2index(e2)].lock()) {
213c2481452Shoumkh Ok(region) => {
214c2481452Shoumkh if e2 != exp + 1 {
215c2481452Shoumkh // 要将分裂后的内存块插入到更小的链表中
216c2481452Shoumkh let low_list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
217b5b571e0SLoGin &mut self.free_regions[exp2index(e2 - 1)].lock();
218a7eb62a4Shoumkh self.split_block(region, e2, low_list_guard);
219c2481452Shoumkh } else {
220c2481452Shoumkh // 由于exp对应的链表list_guard已经被锁住了 不能再加锁
221c2481452Shoumkh // 所以直接将list_guard传入
222a7eb62a4Shoumkh self.split_block(region, e2, list_guard);
223c2481452Shoumkh }
224c2481452Shoumkh }
225c2481452Shoumkh Err(err) => {
2262eab6dd7S曾俊 debug!("buddy_pop_region get wrong");
227c2481452Shoumkh return Err(err);
228c2481452Shoumkh }
229c2481452Shoumkh }
230c2481452Shoumkh }
231ef9f9732Shoumkh }
232c2481452Shoumkh break;
233c2481452Shoumkh }
234c2481452Shoumkh // 判断是否获得了exp大小的内存块
235c2481452Shoumkh if list_guard.num_free > 0 {
236ef9f9732Shoumkh match self.pop_block(list_guard) {
237ef9f9732Shoumkh Ok(ret) => return Ok(ret),
238ef9f9732Shoumkh Err(err) => return Err(err),
239ef9f9732Shoumkh }
240c2481452Shoumkh }
241c2481452Shoumkh // 拆分大内存块无法获得exp大小内存块
242c2481452Shoumkh // 尝试用小内存块合成
243c2481452Shoumkh // 即将两块exp合成一块exp+1
244ef9f9732Shoumkh
245ef9f9732Shoumkh // TODO:修改下一个循环的冗余代码,请不要删除此处的注释
246ef9f9732Shoumkh // let merge = |high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>, exp: u32| {
247ef9f9732Shoumkh // if let Err(err) = self.merge_all_exp(
248ef9f9732Shoumkh // exp,
249ef9f9732Shoumkh // &mut self.free_regions[exp2index(exp) as usize].lock(),
250ef9f9732Shoumkh // high_list_guard,
251ef9f9732Shoumkh // ) {
252ef9f9732Shoumkh // return err;
253ef9f9732Shoumkh // } else {
254ef9f9732Shoumkh // return MmioResult::SUCCESS;
255ef9f9732Shoumkh // }
256ef9f9732Shoumkh // };
257c2481452Shoumkh for e in MMIO_BUDDY_MIN_EXP..exp {
258c2481452Shoumkh if e != exp - 1 {
259a7eb62a4Shoumkh match self.merge_all_exp(
260ef9f9732Shoumkh exp,
261b5b571e0SLoGin &mut self.free_regions[exp2index(exp)].lock(),
262ef9f9732Shoumkh &mut self.free_regions[exp2index(exp + 1)].lock(),
263c2481452Shoumkh ) {
264c2481452Shoumkh Ok(_) => continue,
265c2481452Shoumkh Err(err) => {
2662eab6dd7S曾俊 debug!("merge_all_exp get wrong");
267c2481452Shoumkh return Err(err);
268c2481452Shoumkh }
269c2481452Shoumkh }
270c2481452Shoumkh } else {
271a7eb62a4Shoumkh match self.merge_all_exp(
272ef9f9732Shoumkh exp,
273b5b571e0SLoGin &mut self.free_regions[exp2index(exp)].lock(),
274c2481452Shoumkh list_guard,
275c2481452Shoumkh ) {
276c2481452Shoumkh Ok(_) => continue,
277c2481452Shoumkh Err(err) => {
2782eab6dd7S曾俊 debug!("merge_all_exp get wrong");
279c2481452Shoumkh return Err(err);
280c2481452Shoumkh }
281c2481452Shoumkh }
282c2481452Shoumkh }
283c2481452Shoumkh }
284c2481452Shoumkh
285c2481452Shoumkh //判断是否获得了exp大小的内存块
286c2481452Shoumkh if list_guard.num_free > 0 {
287ef9f9732Shoumkh match self.pop_block(list_guard) {
288ef9f9732Shoumkh Ok(ret) => return Ok(ret),
289ef9f9732Shoumkh Err(err) => return Err(err),
290ef9f9732Shoumkh }
291c2481452Shoumkh }
292c2481452Shoumkh return Err(MmioResult::ENOFOUND);
293c2481452Shoumkh } else {
294ef9f9732Shoumkh match self.pop_block(list_guard) {
295ef9f9732Shoumkh Ok(ret) => return Ok(ret),
296ef9f9732Shoumkh Err(err) => return Err(err),
297ef9f9732Shoumkh }
298c2481452Shoumkh }
299c2481452Shoumkh }
300c2481452Shoumkh
301c2481452Shoumkh /// @brief 对query_addr_region进行封装
302c2481452Shoumkh ///
303c2481452Shoumkh /// @param exp 内存区域的大小(2^exp)
304c2481452Shoumkh ///
30540fe15e0SLoGin /// @return Ok(MmioBuddyAddrRegion)符合要求的内存块信息结构体。
306c2481452Shoumkh /// @return Err(MmioResult) 没有满足要求的内存块时,返回__query_addr_region的错误码。
mmio_buddy_query_addr_region(&self, exp: u32) -> Result<MmioBuddyAddrRegion, MmioResult>30740fe15e0SLoGin fn mmio_buddy_query_addr_region(&self, exp: u32) -> Result<MmioBuddyAddrRegion, MmioResult> {
30823ef2b33SLoGin let mut list_guard: SpinLockGuard<MmioFreeRegionList> =
30923ef2b33SLoGin self.free_regions[exp2index(exp)].lock();
31023ef2b33SLoGin match self.query_addr_region(exp, &mut list_guard) {
311c2481452Shoumkh Ok(ret) => return Ok(ret),
312c2481452Shoumkh Err(err) => {
3132eab6dd7S曾俊 debug!("mmio_buddy_query_addr_region failed");
314c2481452Shoumkh return Err(err);
315c2481452Shoumkh }
316c2481452Shoumkh }
317c2481452Shoumkh }
318c2481452Shoumkh /// @brief 往指定的地址空间链表中添加一个地址区域
319c2481452Shoumkh ///
320c2481452Shoumkh /// @param region 要被添加的地址结构体
321c2481452Shoumkh ///
322c2481452Shoumkh /// @param list_guard 目标链表
push_block( &self, region: MmioBuddyAddrRegion, list_guard: &mut SpinLockGuard<MmioFreeRegionList>, )323a7eb62a4Shoumkh fn push_block(
324c2481452Shoumkh &self,
32540fe15e0SLoGin region: MmioBuddyAddrRegion,
326c2481452Shoumkh list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
327c2481452Shoumkh ) {
328c2481452Shoumkh list_guard.list.push_back(region);
329c2481452Shoumkh list_guard.num_free += 1;
330c2481452Shoumkh }
331c2481452Shoumkh
332c2481452Shoumkh /// @brief 根据地址和内存块大小,计算伙伴块虚拟内存的地址
333c2481452Shoumkh #[inline(always)]
calculate_block_vaddr(&self, vaddr: VirtAddr, exp: u32) -> VirtAddr33440fe15e0SLoGin fn calculate_block_vaddr(&self, vaddr: VirtAddr, exp: u32) -> VirtAddr {
33540fe15e0SLoGin return VirtAddr::new(vaddr.data() ^ (1 << exp as usize));
336c2481452Shoumkh }
337c2481452Shoumkh
338c2481452Shoumkh /// @brief 寻找并弹出指定内存块的伙伴块
339c2481452Shoumkh ///
340c2481452Shoumkh /// @param region 对应内存块的信息
341c2481452Shoumkh ///
342c2481452Shoumkh /// @param exp 内存块大小
343c2481452Shoumkh ///
344c2481452Shoumkh /// @param list_guard 【exp】对应的链表
345c2481452Shoumkh ///
346c2481452Shoumkh /// @return Ok(Box<MmioBuddyAddrRegion) 返回伙伴块的引用
347c2481452Shoumkh /// @return Err(MmioResult)
348c2481452Shoumkh /// - 当链表为空,返回ISEMPTY
349c2481452Shoumkh /// - 没有找到伙伴块,返回ENOFOUND
pop_buddy_block( &self, vaddr: VirtAddr, exp: u32, list_guard: &mut SpinLockGuard<MmioFreeRegionList>, ) -> Result<MmioBuddyAddrRegion, MmioResult>350a7eb62a4Shoumkh fn pop_buddy_block(
351c2481452Shoumkh &self,
35240fe15e0SLoGin vaddr: VirtAddr,
353c2481452Shoumkh exp: u32,
354c2481452Shoumkh list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
35540fe15e0SLoGin ) -> Result<MmioBuddyAddrRegion, MmioResult> {
356b5b571e0SLoGin if list_guard.list.is_empty() {
357c2481452Shoumkh return Err(MmioResult::ISEMPTY);
358c2481452Shoumkh } else {
359c2481452Shoumkh //计算伙伴块的地址
360a7eb62a4Shoumkh let buddy_vaddr = self.calculate_block_vaddr(vaddr, exp);
361c2481452Shoumkh
362c2481452Shoumkh // element 只会有一个元素
36340fe15e0SLoGin let mut element: Vec<MmioBuddyAddrRegion> = list_guard
364c2481452Shoumkh .list
3651a72a751SLoGin .extract_if(|x| x.vaddr == buddy_vaddr)
366c2481452Shoumkh .collect();
367c2481452Shoumkh if element.len() == 1 {
368c2481452Shoumkh list_guard.num_free -= 1;
369c2481452Shoumkh return Ok(element.pop().unwrap());
370c2481452Shoumkh }
371c2481452Shoumkh
372c2481452Shoumkh //没有找到对应的伙伴块
373c2481452Shoumkh return Err(MmioResult::ENOFOUND);
374c2481452Shoumkh }
375c2481452Shoumkh }
376c2481452Shoumkh
377c2481452Shoumkh /// @brief 从指定空闲链表中取出内存区域
378c2481452Shoumkh ///
379c2481452Shoumkh /// @param list_guard 【exp】对应的链表
380c2481452Shoumkh ///
38140fe15e0SLoGin /// @return Ok(MmioBuddyAddrRegion) 内存块信息结构体的引用。
382c2481452Shoumkh ///
383c2481452Shoumkh /// @return Err(MmioResult) 当链表为空,无法删除时,返回ISEMPTY
pop_block( &self, list_guard: &mut SpinLockGuard<MmioFreeRegionList>, ) -> Result<MmioBuddyAddrRegion, MmioResult>384a7eb62a4Shoumkh fn pop_block(
385c2481452Shoumkh &self,
386c2481452Shoumkh list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
38740fe15e0SLoGin ) -> Result<MmioBuddyAddrRegion, MmioResult> {
388c2481452Shoumkh if !list_guard.list.is_empty() {
389c2481452Shoumkh list_guard.num_free -= 1;
390c2481452Shoumkh return Ok(list_guard.list.pop_back().unwrap());
391c2481452Shoumkh }
392c2481452Shoumkh return Err(MmioResult::ISEMPTY);
393c2481452Shoumkh }
394c2481452Shoumkh
395c2481452Shoumkh /// @brief 合并所有2^{exp}大小的内存块
396c2481452Shoumkh ///
397c2481452Shoumkh /// @param exp 内存块大小的幂(2^exp)
398c2481452Shoumkh ///
399c2481452Shoumkh /// @param list_guard exp对应的链表
400c2481452Shoumkh ///
401c2481452Shoumkh /// @param high_list_guard exp+1对应的链表
402c2481452Shoumkh ///
403c2481452Shoumkh /// @return Ok(MmioResult) 合并成功返回SUCCESS
404c2481452Shoumkh /// @return Err(MmioResult)
405c2481452Shoumkh /// - 内存块过少,无法合并,返回EINVAL
406a7eb62a4Shoumkh /// - pop_buddy_block调用出错,返回其错误码
407a7eb62a4Shoumkh /// - merge_blocks调用出错,返回其错误码
merge_all_exp( &self, exp: u32, list_guard: &mut SpinLockGuard<MmioFreeRegionList>, high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>, ) -> Result<MmioResult, MmioResult>408a7eb62a4Shoumkh fn merge_all_exp(
409c2481452Shoumkh &self,
410c2481452Shoumkh exp: u32,
411c2481452Shoumkh list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
412c2481452Shoumkh high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
413c2481452Shoumkh ) -> Result<MmioResult, MmioResult> {
414c2481452Shoumkh // 至少要两个内存块才能合并
415c2481452Shoumkh if list_guard.num_free <= 1 {
416c2481452Shoumkh return Err(MmioResult::EINVAL);
417c2481452Shoumkh }
418c2481452Shoumkh loop {
419c2481452Shoumkh if list_guard.num_free <= 1 {
420c2481452Shoumkh break;
421c2481452Shoumkh }
422c2481452Shoumkh // 获取内存块
42340fe15e0SLoGin let vaddr: VirtAddr = list_guard.list.back().unwrap().vaddr;
424c2481452Shoumkh // 获取伙伴内存块
425a7eb62a4Shoumkh match self.pop_buddy_block(vaddr, exp, list_guard) {
426c2481452Shoumkh Err(err) => {
427c2481452Shoumkh return Err(err);
428c2481452Shoumkh }
429c2481452Shoumkh Ok(buddy_region) => {
43040fe15e0SLoGin let region: MmioBuddyAddrRegion = list_guard.list.pop_back().unwrap();
43140fe15e0SLoGin let copy_region = region.clone();
432c2481452Shoumkh // 在两块内存都被取出之后才进行合并
433a7eb62a4Shoumkh match self.merge_blocks(region, buddy_region, exp, high_list_guard) {
434c2481452Shoumkh Err(err) => {
435c2481452Shoumkh // 如果合并失败了要将取出来的元素放回去
436a7eb62a4Shoumkh self.push_block(copy_region, list_guard);
4372eab6dd7S曾俊 debug!("merge_all_exp: merge_blocks failed");
438c2481452Shoumkh return Err(err);
439c2481452Shoumkh }
440c2481452Shoumkh Ok(_) => continue,
441c2481452Shoumkh }
442c2481452Shoumkh }
443c2481452Shoumkh }
444c2481452Shoumkh }
445c2481452Shoumkh return Ok(MmioResult::SUCCESS);
446c2481452Shoumkh }
447c2481452Shoumkh
448c2481452Shoumkh /// @brief 合并两个【已经从链表中取出】的内存块
449c2481452Shoumkh ///
450c2481452Shoumkh /// @param region_1 第一个内存块
451c2481452Shoumkh ///
452c2481452Shoumkh /// @param region_2 第二个内存
453c2481452Shoumkh ///
454c2481452Shoumkh /// @return Ok(MmioResult) 成功返回SUCCESS
455c2481452Shoumkh ///
456c2481452Shoumkh /// @return Err(MmioResult) 两个内存块不是伙伴块,返回EINVAL
merge_blocks( &self, region_1: MmioBuddyAddrRegion, region_2: MmioBuddyAddrRegion, exp: u32, high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>, ) -> Result<MmioResult, MmioResult>457a7eb62a4Shoumkh fn merge_blocks(
458c2481452Shoumkh &self,
45940fe15e0SLoGin region_1: MmioBuddyAddrRegion,
46040fe15e0SLoGin region_2: MmioBuddyAddrRegion,
461c2481452Shoumkh exp: u32,
462c2481452Shoumkh high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>,
463c2481452Shoumkh ) -> Result<MmioResult, MmioResult> {
464c2481452Shoumkh // 判断是否为伙伴块
465a7eb62a4Shoumkh if region_1.vaddr != self.calculate_block_vaddr(region_2.vaddr, exp) {
466c2481452Shoumkh return Err(MmioResult::EINVAL);
467c2481452Shoumkh }
468c2481452Shoumkh // 将大的块放进下一级链表
469a7eb62a4Shoumkh self.push_block(region_1, high_list_guard);
470c2481452Shoumkh return Ok(MmioResult::SUCCESS);
471c2481452Shoumkh }
472c2481452Shoumkh
473c2481452Shoumkh /// @brief 创建一块mmio区域,并将vma绑定到initial_mm
474c2481452Shoumkh ///
475c2481452Shoumkh /// @param size mmio区域的大小(字节)
476c2481452Shoumkh ///
477c2481452Shoumkh /// @param vm_flags 要把vma设置成的标志
478c2481452Shoumkh ///
479c2481452Shoumkh /// @param res_vaddr 返回值-分配得到的虚拟地址
480c2481452Shoumkh ///
481c2481452Shoumkh /// @param res_length 返回值-分配的虚拟地址空间长度
482c2481452Shoumkh ///
483a7eb62a4Shoumkh /// @return Ok(i32) 成功返回0
484a7eb62a4Shoumkh ///
485676b8ef6SMork /// @return Err(SystemError) 失败返回错误码
create_mmio(&self, size: usize) -> Result<MMIOSpaceGuard, SystemError>4862dd9f0c7SLoGin pub fn create_mmio(&self, size: usize) -> Result<MMIOSpaceGuard, SystemError> {
487c2481452Shoumkh if size > PAGE_1G_SIZE || size == 0 {
488676b8ef6SMork return Err(SystemError::EPERM);
489c2481452Shoumkh }
490c2481452Shoumkh // 计算前导0
4914fda81ceSLoGin #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
49240fe15e0SLoGin let mut size_exp: u32 = 63 - size.leading_zeros();
4932eab6dd7S曾俊 // debug!("create_mmio: size_exp: {}", size_exp);
494c2481452Shoumkh // 记录最终申请的空间大小
49540fe15e0SLoGin let mut new_size = size;
496c2481452Shoumkh // 对齐要申请的空间大小
497c2481452Shoumkh // 如果要申请的空间大小小于4k,则分配4k
49823ef2b33SLoGin if size_exp < PAGE_4K_SHIFT as u32 {
499370472f7SLoGin new_size = PAGE_4K_SIZE;
50023ef2b33SLoGin size_exp = PAGE_4K_SHIFT as u32;
501c2481452Shoumkh } else if (new_size & (!(1 << size_exp))) != 0 {
502c2481452Shoumkh // 向左对齐空间大小
503c2481452Shoumkh size_exp += 1;
504c2481452Shoumkh new_size = 1 << size_exp;
505c2481452Shoumkh }
50640fe15e0SLoGin match self.mmio_buddy_query_addr_region(size_exp) {
507c2481452Shoumkh Ok(region) => {
5082dd9f0c7SLoGin let space_guard =
5092dd9f0c7SLoGin unsafe { MMIOSpaceGuard::from_raw(region.vaddr, new_size, false) };
5102dd9f0c7SLoGin return Ok(space_guard);
511c2481452Shoumkh }
512c2481452Shoumkh Err(_) => {
5132eab6dd7S曾俊 error!(
5141496ba7bSLoGin "failed to create mmio. pid = {:?}",
5151496ba7bSLoGin ProcessManager::current_pcb().pid()
5161496ba7bSLoGin );
517676b8ef6SMork return Err(SystemError::ENOMEM);
518c2481452Shoumkh }
519c2481452Shoumkh }
520c2481452Shoumkh }
521c2481452Shoumkh
522c2481452Shoumkh /// @brief 取消mmio的映射并将地址空间归还到buddy中
523c2481452Shoumkh ///
524c2481452Shoumkh /// @param vaddr 起始的虚拟地址
525c2481452Shoumkh ///
526c2481452Shoumkh /// @param length 要归还的地址空间的长度
527c2481452Shoumkh ///
528c2481452Shoumkh /// @return Ok(i32) 成功返回0
529c2481452Shoumkh ///
530676b8ef6SMork /// @return Err(SystemError) 失败返回错误码
release_mmio(&self, vaddr: VirtAddr, length: usize) -> Result<i32, SystemError>5317eda31b2SLoGin pub fn release_mmio(&self, vaddr: VirtAddr, length: usize) -> Result<i32, SystemError> {
53240fe15e0SLoGin assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
53340fe15e0SLoGin assert!(length & (MMArch::PAGE_SIZE - 1) == 0);
53440fe15e0SLoGin if vaddr < self.pool_start_addr
53540fe15e0SLoGin || vaddr.data() >= self.pool_start_addr.data() + self.pool_size
53640fe15e0SLoGin {
537676b8ef6SMork return Err(SystemError::EINVAL);
538c2481452Shoumkh }
53940fe15e0SLoGin // todo: 重构MMIO管理机制,创建类似全局的manager之类的,管理MMIO的空间?
54040fe15e0SLoGin
54140fe15e0SLoGin // 暂时认为传入的vaddr都是正确的
54240fe15e0SLoGin let page_count = length / MMArch::PAGE_SIZE;
54340fe15e0SLoGin // 取消映射
54440fe15e0SLoGin let mut bindings = KernelMapper::lock();
54540fe15e0SLoGin let mut kernel_mapper = bindings.as_mut();
54640fe15e0SLoGin if kernel_mapper.is_none() {
5472eab6dd7S曾俊 warn!("release_mmio: kernel_mapper is read only");
54840fe15e0SLoGin return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
549c2481452Shoumkh }
55040fe15e0SLoGin
55140fe15e0SLoGin for i in 0..page_count {
552c2481452Shoumkh unsafe {
5537ae679ddSLoGin let x: Option<(
5547ae679ddSLoGin PhysAddr,
555cf7f801eSMemoryShore EntryFlags<MMArch>,
5567ae679ddSLoGin crate::mm::page::PageFlush<MMArch>,
5577ae679ddSLoGin )> = kernel_mapper
55840fe15e0SLoGin .as_mut()
55940fe15e0SLoGin .unwrap()
5607ae679ddSLoGin .unmap_phys(vaddr + i * MMArch::PAGE_SIZE, false);
5617ae679ddSLoGin if let Some((_, _, flush)) = x {
5627ae679ddSLoGin flush.flush();
5637ae679ddSLoGin }
56440fe15e0SLoGin };
565c2481452Shoumkh }
56640fe15e0SLoGin
5677ae679ddSLoGin // 归还到buddy
5687ae679ddSLoGin mmio_pool()
569b5b571e0SLoGin .give_back_block(vaddr, length.trailing_zeros())
5707ae679ddSLoGin .unwrap_or_else(|err| {
5717ae679ddSLoGin panic!("MMIO release failed: self: {self:?}, err msg: {:?}", err);
5727ae679ddSLoGin });
57340fe15e0SLoGin
574a7eb62a4Shoumkh return Ok(0);
575a7eb62a4Shoumkh }
576a7eb62a4Shoumkh }
577a7eb62a4Shoumkh
578a7eb62a4Shoumkh /// @brief mmio伙伴系统内部的地址区域结构体
57940fe15e0SLoGin #[derive(Debug, Clone)]
58040fe15e0SLoGin struct MmioBuddyAddrRegion {
58140fe15e0SLoGin vaddr: VirtAddr,
582a7eb62a4Shoumkh }
583a7eb62a4Shoumkh impl MmioBuddyAddrRegion {
new(vaddr: VirtAddr) -> Self58440fe15e0SLoGin pub fn new(vaddr: VirtAddr) -> Self {
58540fe15e0SLoGin return MmioBuddyAddrRegion { vaddr };
586a7eb62a4Shoumkh }
58740fe15e0SLoGin
58840fe15e0SLoGin #[allow(dead_code)]
vaddr(&self) -> VirtAddr58940fe15e0SLoGin pub fn vaddr(&self) -> VirtAddr {
59040fe15e0SLoGin return self.vaddr;
591a7eb62a4Shoumkh }
592a7eb62a4Shoumkh }
593a7eb62a4Shoumkh
594a7eb62a4Shoumkh /// @brief 空闲页数组结构体
595b5b571e0SLoGin #[derive(Debug, Default)]
596a7eb62a4Shoumkh pub struct MmioFreeRegionList {
597a7eb62a4Shoumkh /// 存储mmio_buddy的地址链表
59840fe15e0SLoGin list: LinkedList<MmioBuddyAddrRegion>,
599a7eb62a4Shoumkh /// 空闲块的数量
600a7eb62a4Shoumkh num_free: i64,
601a7eb62a4Shoumkh }
602a7eb62a4Shoumkh impl MmioFreeRegionList {
60364aea4b3SGou Ngai #[allow(dead_code)]
new() -> Self604a7eb62a4Shoumkh fn new() -> Self {
605a7eb62a4Shoumkh return MmioFreeRegionList {
606a7eb62a4Shoumkh ..Default::default()
607a7eb62a4Shoumkh };
608a7eb62a4Shoumkh }
609a7eb62a4Shoumkh }
610a7eb62a4Shoumkh
611a7eb62a4Shoumkh /// @brief 将内存对象大小的幂转换成内存池中的数组的下标
612a7eb62a4Shoumkh ///
613a7eb62a4Shoumkh /// @param exp内存大小
614a7eb62a4Shoumkh ///
615a7eb62a4Shoumkh /// @return 内存池数组下标
616a7eb62a4Shoumkh #[inline(always)]
exp2index(exp: u32) -> usize617a7eb62a4Shoumkh fn exp2index(exp: u32) -> usize {
618a7eb62a4Shoumkh return (exp - 12) as usize;
619a7eb62a4Shoumkh }
620a7eb62a4Shoumkh
6212dd9f0c7SLoGin #[derive(Debug)]
6222dd9f0c7SLoGin pub struct MMIOSpaceGuard {
6232dd9f0c7SLoGin vaddr: VirtAddr,
6242dd9f0c7SLoGin size: usize,
6252dd9f0c7SLoGin mapped: AtomicBool,
6262dd9f0c7SLoGin }
6272dd9f0c7SLoGin
6282dd9f0c7SLoGin impl MMIOSpaceGuard {
from_raw(vaddr: VirtAddr, size: usize, mapped: bool) -> Self6292dd9f0c7SLoGin pub unsafe fn from_raw(vaddr: VirtAddr, size: usize, mapped: bool) -> Self {
6302dd9f0c7SLoGin // check size
6312dd9f0c7SLoGin assert!(
6322dd9f0c7SLoGin size & (MMArch::PAGE_SIZE - 1) == 0,
6332dd9f0c7SLoGin "MMIO space size must be page aligned"
6342dd9f0c7SLoGin );
6352dd9f0c7SLoGin assert!(size.is_power_of_two(), "MMIO space size must be power of 2");
6362dd9f0c7SLoGin assert!(
6372dd9f0c7SLoGin vaddr.check_aligned(size),
6382dd9f0c7SLoGin "MMIO space vaddr must be aligned with size"
6392dd9f0c7SLoGin );
6402dd9f0c7SLoGin assert!(
64123ef2b33SLoGin vaddr.data() >= MMArch::MMIO_BASE.data()
64223ef2b33SLoGin && vaddr.data() + size <= MMArch::MMIO_TOP.data(),
6432dd9f0c7SLoGin "MMIO space must be in MMIO region"
6442dd9f0c7SLoGin );
6452dd9f0c7SLoGin
6462dd9f0c7SLoGin // 人工创建的MMIO空间,认为已经映射
6472dd9f0c7SLoGin MMIOSpaceGuard {
6482dd9f0c7SLoGin vaddr,
6492dd9f0c7SLoGin size,
6502dd9f0c7SLoGin mapped: AtomicBool::new(mapped),
6512dd9f0c7SLoGin }
6522dd9f0c7SLoGin }
6532dd9f0c7SLoGin
vaddr(&self) -> VirtAddr6542dd9f0c7SLoGin pub fn vaddr(&self) -> VirtAddr {
6552dd9f0c7SLoGin self.vaddr
6562dd9f0c7SLoGin }
6572dd9f0c7SLoGin
size(&self) -> usize6582dd9f0c7SLoGin pub fn size(&self) -> usize {
6592dd9f0c7SLoGin self.size
6602dd9f0c7SLoGin }
6612dd9f0c7SLoGin
6622dd9f0c7SLoGin /// 将物理地址填写到虚拟地址空间中
6632dd9f0c7SLoGin ///
6642dd9f0c7SLoGin /// ## Safety
6652dd9f0c7SLoGin ///
6662dd9f0c7SLoGin /// 传入的物理地址【一定要是设备的物理地址】。
6672dd9f0c7SLoGin /// 如果物理地址是从内存分配器中分配的,那么会造成内存泄露。因为mmio_release的时候,只取消映射,不会释放内存。
map_phys(&self, paddr: PhysAddr, length: usize) -> Result<(), SystemError>6687ae679ddSLoGin pub unsafe fn map_phys(&self, paddr: PhysAddr, length: usize) -> Result<(), SystemError> {
6692dd9f0c7SLoGin if length > self.size {
6707ae679ddSLoGin return Err(SystemError::EINVAL);
6712dd9f0c7SLoGin }
6722dd9f0c7SLoGin
6732dd9f0c7SLoGin let check = self
6742dd9f0c7SLoGin .mapped
6752dd9f0c7SLoGin .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst);
6762dd9f0c7SLoGin if check.is_err() {
6777ae679ddSLoGin return Err(SystemError::EINVAL);
6782dd9f0c7SLoGin }
6792dd9f0c7SLoGin
680cf7f801eSMemoryShore let flags = EntryFlags::mmio_flags();
681731bc2b3SLoGin
6822dd9f0c7SLoGin let mut kernel_mapper = KernelMapper::lock();
6832dd9f0c7SLoGin let r = kernel_mapper.map_phys_with_size(self.vaddr, paddr, length, flags, true);
6847ae679ddSLoGin return r;
6852dd9f0c7SLoGin }
6867ae679ddSLoGin
687*2b7818e8SLoGin /// 将物理地址填写到虚拟地址空间中
688*2b7818e8SLoGin ///
689*2b7818e8SLoGin /// ## Safety
690*2b7818e8SLoGin ///
691*2b7818e8SLoGin /// 传入的物理地址【一定要是设备的物理地址】。
692*2b7818e8SLoGin /// 如果物理地址是从内存分配器中分配的,那么会造成内存泄露。因为mmio_release的时候,只取消映射,不会释放内存。
map_phys_with_flags( &self, paddr: PhysAddr, length: usize, flags: EntryFlags<MMArch>, ) -> Result<(), SystemError>693*2b7818e8SLoGin pub unsafe fn map_phys_with_flags(
694*2b7818e8SLoGin &self,
695*2b7818e8SLoGin paddr: PhysAddr,
696*2b7818e8SLoGin length: usize,
697*2b7818e8SLoGin flags: EntryFlags<MMArch>,
698*2b7818e8SLoGin ) -> Result<(), SystemError> {
699*2b7818e8SLoGin if length > self.size {
700*2b7818e8SLoGin return Err(SystemError::EINVAL);
701*2b7818e8SLoGin }
702*2b7818e8SLoGin
703*2b7818e8SLoGin let check = self
704*2b7818e8SLoGin .mapped
705*2b7818e8SLoGin .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst);
706*2b7818e8SLoGin if check.is_err() {
707*2b7818e8SLoGin return Err(SystemError::EINVAL);
708*2b7818e8SLoGin }
709*2b7818e8SLoGin
710*2b7818e8SLoGin let mut kernel_mapper = KernelMapper::lock();
711*2b7818e8SLoGin let r = kernel_mapper.map_phys_with_size(self.vaddr, paddr, length, flags, true);
712*2b7818e8SLoGin return r;
713*2b7818e8SLoGin }
714*2b7818e8SLoGin
7150102d69fSLoGin /// # map_any_phys - 将任意物理地址映射到虚拟地址
7160102d69fSLoGin ///
7170102d69fSLoGin /// 将指定的物理地址和长度映射到虚拟地址空间。
7180102d69fSLoGin ///
7190102d69fSLoGin /// ## 参数
7200102d69fSLoGin ///
7210102d69fSLoGin /// - `paddr`: 物理地址,需要被映射的起始地址。
7220102d69fSLoGin /// - `length`: 要映射的物理地址长度。
7230102d69fSLoGin ///
7240102d69fSLoGin /// ## 返回值
7250102d69fSLoGin /// - `Ok(VirtAddr)`: 映射成功,返回虚拟地址的起始地址。
7260102d69fSLoGin /// - `Err(SystemError)`: 映射失败,返回系统错误。
7270102d69fSLoGin ///
7280102d69fSLoGin /// ## 副作用
7290102d69fSLoGin ///
7300102d69fSLoGin /// 该函数会修改虚拟地址空间,将物理地址映射到虚拟地址。
7310102d69fSLoGin ///
7320102d69fSLoGin /// ## Safety
7330102d69fSLoGin ///
7340102d69fSLoGin /// 由于该函数涉及到内存操作,因此它是非安全的。确保在调用该函数时,你传入的物理地址是正确的。
7350102d69fSLoGin #[allow(dead_code)]
map_any_phys( &self, paddr: PhysAddr, length: usize, ) -> Result<VirtAddr, SystemError>7360102d69fSLoGin pub unsafe fn map_any_phys(
7370102d69fSLoGin &self,
7380102d69fSLoGin paddr: PhysAddr,
7390102d69fSLoGin length: usize,
7400102d69fSLoGin ) -> Result<VirtAddr, SystemError> {
7410102d69fSLoGin let paddr_base = PhysAddr::new(page_align_down(paddr.data()));
7420102d69fSLoGin let offset = paddr - paddr_base;
7430102d69fSLoGin let vaddr_base = self.vaddr;
7440102d69fSLoGin let vaddr = vaddr_base + offset;
7450102d69fSLoGin
7460102d69fSLoGin self.map_phys(paddr_base, page_align_up(length + offset))?;
7470102d69fSLoGin return Ok(vaddr);
7480102d69fSLoGin }
7490102d69fSLoGin
7507ae679ddSLoGin /// 泄露一个MMIO space guard,不会释放映射的空间
leak(self)7517ae679ddSLoGin pub unsafe fn leak(self) {
7527ae679ddSLoGin core::mem::forget(self);
7532dd9f0c7SLoGin }
7542dd9f0c7SLoGin }
7552dd9f0c7SLoGin
7562dd9f0c7SLoGin impl Drop for MMIOSpaceGuard {
drop(&mut self)7572dd9f0c7SLoGin fn drop(&mut self) {
7582dd9f0c7SLoGin let _ = mmio_pool()
7592dd9f0c7SLoGin .release_mmio(self.vaddr, self.size)
7602dd9f0c7SLoGin .unwrap_or_else(|err| {
7612dd9f0c7SLoGin panic!("MMIO release failed: self: {self:?}, err msg: {:?}", err);
7622dd9f0c7SLoGin });
7632dd9f0c7SLoGin }
7642dd9f0c7SLoGin }
7652dd9f0c7SLoGin
mmio_init()76640fe15e0SLoGin pub fn mmio_init() {
7672eab6dd7S曾俊 debug!("Initializing MMIO buddy memory pool...");
76840fe15e0SLoGin // 初始化mmio内存池
76940fe15e0SLoGin unsafe {
77040fe15e0SLoGin __MMIO_POOL = Some(MmioBuddyMemPool::new());
77140fe15e0SLoGin }
77240fe15e0SLoGin
7732eab6dd7S曾俊 info!("MMIO buddy memory pool init done");
77440fe15e0SLoGin }
775