1 use crate::libs::spinlock::{SpinLock, SpinLockGuard}; 2 use crate::{ 3 arch::asm::current::current_pcb, 4 include::bindings::bindings::{ 5 initial_mm, mm_create_vma, mm_unmap, vm_area_del, vm_area_free, vm_area_struct, vm_flags_t, 6 vma_find, EINVAL, ENOMEM, EPERM, MMIO_BASE, MMIO_TOP, PAGE_1G_SHIFT, PAGE_1G_SIZE, 7 PAGE_2M_SIZE, PAGE_4K_SHIFT, PAGE_4K_SIZE, VM_DONTCOPY, VM_IO, 8 }, 9 kdebug, kerror, 10 }; 11 use alloc::{boxed::Box, collections::LinkedList, vec::Vec}; 12 use core::{mem, ptr::null_mut}; 13 14 // 最大的伙伴块的幂 15 const MMIO_BUDDY_MAX_EXP: u32 = PAGE_1G_SHIFT; 16 // 最小的伙伴块的幂 17 const MMIO_BUDDY_MIN_EXP: u32 = PAGE_4K_SHIFT; 18 // 内存池数组的范围 19 const MMIO_BUDDY_REGION_COUNT: u32 = MMIO_BUDDY_MAX_EXP - MMIO_BUDDY_MIN_EXP + 1; 20 21 lazy_static! { 22 pub static ref MMIO_POOL: MmioBuddyMemPool = MmioBuddyMemPool::new(); 23 } 24 25 pub enum MmioResult { 26 SUCCESS, 27 EINVAL, 28 ENOFOUND, 29 WRONGEXP, 30 ISEMPTY, 31 } 32 33 /// @brief buddy内存池 34 pub struct MmioBuddyMemPool { 35 pool_start_addr: u64, 36 pool_size: u64, 37 free_regions: [SpinLock<MmioFreeRegionList>; MMIO_BUDDY_REGION_COUNT as usize], 38 } 39 impl Default for MmioBuddyMemPool { 40 fn default() -> Self { 41 MmioBuddyMemPool { 42 pool_start_addr: MMIO_BASE as u64, 43 pool_size: (MMIO_TOP - MMIO_BASE) as u64, 44 free_regions: unsafe { mem::zeroed() }, 45 } 46 } 47 } 48 impl MmioBuddyMemPool { 49 fn new() -> Self { 50 return MmioBuddyMemPool { 51 ..Default::default() 52 }; 53 } 54 55 /// @brief 创建新的地址区域结构体 56 /// 57 /// @param vaddr 虚拟地址 58 /// 59 /// @return 创建好的地址区域结构体 60 fn create_region(&self, vaddr: u64) -> Box<MmioBuddyAddrRegion> { 61 let mut region: Box<MmioBuddyAddrRegion> = Box::new(MmioBuddyAddrRegion::new()); 62 region.vaddr = vaddr; 63 return region; 64 } 65 66 /// @brief 将内存块归还给buddy 67 /// 68 /// @param vaddr 虚拟地址 69 /// 70 /// @param exp 内存空间的大小(2^exp) 71 /// 72 /// @param list_guard 【exp】对应的链表 73 /// 74 /// @return Ok(i32) 返回0 75 /// 76 /// @return Err(i32) 返回错误码 77 fn give_back_block(&self, vaddr: u64, exp: u32) -> Result<i32, i32> { 78 // 确保内存对齐,低位都要为0 79 if (vaddr & ((1 << exp) - 1)) != 0 { 80 return Err(-(EINVAL as i32)); 81 } 82 let region: Box<MmioBuddyAddrRegion> = self.create_region(vaddr); 83 // 加入buddy 84 let list_guard: &mut SpinLockGuard<MmioFreeRegionList> = 85 &mut self.free_regions[exp2index(exp)].lock(); 86 self.push_block(region, list_guard); 87 return Ok(0); 88 } 89 90 /// @brief 将给定大小为2^{exp}的内存块一分为二,并插入内存块大小为2^{exp-1}的链表中 91 /// 92 /// @param region 要被分割的地址区域结构体(保证其已经从链表中取出) 93 /// 94 /// @param exp 要被分割的地址区域的大小的幂 95 /// 96 /// @param list_guard 【exp-1】对应的链表 97 fn split_block( 98 &self, 99 region: Box<MmioBuddyAddrRegion>, 100 exp: u32, 101 low_list_guard: &mut SpinLockGuard<MmioFreeRegionList>, 102 ) { 103 let vaddr: u64 = self.calculate_block_vaddr(region.vaddr, exp - 1); 104 let new_region: Box<MmioBuddyAddrRegion> = self.create_region(vaddr); 105 self.push_block(region, low_list_guard); 106 self.push_block(new_region, low_list_guard); 107 } 108 109 /// @brief 从buddy中申请一块指定大小的内存区域 110 /// 111 /// @param exp 要申请的内存块的大小的幂(2^exp) 112 /// 113 /// @param list_guard exp对应的链表 114 /// 115 /// @return Ok(Box<MmioBuddyAddrRegion>) 符合要求的内存区域。 116 /// 117 /// @return Err(MmioResult) 118 /// - 没有满足要求的内存块时,返回ENOFOUND 119 /// - 申请的内存块大小超过合法范围,返回WRONGEXP 120 /// - 调用函数出错时,返回出错函数对应错误码 121 fn query_addr_region( 122 &self, 123 exp: u32, 124 list_guard: &mut SpinLockGuard<MmioFreeRegionList>, 125 ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> { 126 // 申请范围错误 127 if exp < MMIO_BUDDY_MIN_EXP || exp > MMIO_BUDDY_MAX_EXP { 128 kdebug!("query_addr_region: exp wrong"); 129 return Err(MmioResult::WRONGEXP); 130 } 131 // 没有恰好符合要求的内存块 132 // 注意:exp对应的链表list_guard已上锁【注意避免死锁问题】 133 if list_guard.num_free == 0 { 134 // 找到最小符合申请范围的内存块 135 // 将大的内存块依次分成小块内存,直到能够满足exp大小,即将exp+1分成两块exp 136 for e in exp + 1..MMIO_BUDDY_MAX_EXP + 1 { 137 let pop_list: &mut SpinLockGuard<MmioFreeRegionList> = 138 &mut self.free_regions[exp2index(e) as usize].lock(); 139 if pop_list.num_free == 0 { 140 continue; 141 } 142 143 for e2 in (exp + 1..e + 1).rev() { 144 if e2 == e { 145 match self.pop_block(pop_list) { 146 Ok(region) => { 147 if e2 != exp + 1 { 148 // 要将分裂后的内存块插入到更小的链表中 149 let low_list_guard: &mut SpinLockGuard<MmioFreeRegionList> = 150 &mut self.free_regions[exp2index(e2 - 1) as usize].lock(); 151 self.split_block(region, e2, low_list_guard); 152 } else { 153 // 由于exp对应的链表list_guard已经被锁住了 不能再加锁 154 // 所以直接将list_guard传入 155 self.split_block(region, e2, list_guard); 156 } 157 } 158 Err(err) => { 159 kdebug!("buddy_pop_region get wrong"); 160 return Err(err); 161 } 162 } 163 } else { 164 match self.pop_block(&mut self.free_regions[exp2index(e2) as usize].lock()) 165 { 166 Ok(region) => { 167 if e2 != exp + 1 { 168 // 要将分裂后的内存块插入到更小的链表中 169 let low_list_guard: &mut SpinLockGuard<MmioFreeRegionList> = 170 &mut self.free_regions[exp2index(e2 - 1) as usize].lock(); 171 self.split_block(region, e2, low_list_guard); 172 } else { 173 // 由于exp对应的链表list_guard已经被锁住了 不能再加锁 174 // 所以直接将list_guard传入 175 self.split_block(region, e2, list_guard); 176 } 177 } 178 Err(err) => { 179 kdebug!("buddy_pop_region get wrong"); 180 return Err(err); 181 } 182 } 183 } 184 } 185 break; 186 } 187 // 判断是否获得了exp大小的内存块 188 if list_guard.num_free > 0 { 189 match self.pop_block(list_guard) { 190 Ok(ret) => return Ok(ret), 191 Err(err) => return Err(err), 192 } 193 } 194 // 拆分大内存块无法获得exp大小内存块 195 // 尝试用小内存块合成 196 // 即将两块exp合成一块exp+1 197 198 // TODO:修改下一个循环的冗余代码,请不要删除此处的注释 199 // let merge = |high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>, exp: u32| { 200 // if let Err(err) = self.merge_all_exp( 201 // exp, 202 // &mut self.free_regions[exp2index(exp) as usize].lock(), 203 // high_list_guard, 204 // ) { 205 // return err; 206 // } else { 207 // return MmioResult::SUCCESS; 208 // } 209 // }; 210 for e in MMIO_BUDDY_MIN_EXP..exp { 211 if e != exp - 1 { 212 match self.merge_all_exp( 213 exp, 214 &mut self.free_regions[exp2index(exp) as usize].lock(), 215 &mut self.free_regions[exp2index(exp + 1)].lock(), 216 ) { 217 Ok(_) => continue, 218 Err(err) => { 219 kdebug!("merge_all_exp get wrong"); 220 return Err(err); 221 } 222 } 223 } else { 224 match self.merge_all_exp( 225 exp, 226 &mut self.free_regions[exp2index(exp) as usize].lock(), 227 list_guard, 228 ) { 229 Ok(_) => continue, 230 Err(err) => { 231 kdebug!("merge_all_exp get wrong"); 232 return Err(err); 233 } 234 } 235 } 236 } 237 238 //判断是否获得了exp大小的内存块 239 if list_guard.num_free > 0 { 240 match self.pop_block(list_guard) { 241 Ok(ret) => return Ok(ret), 242 Err(err) => return Err(err), 243 } 244 } 245 return Err(MmioResult::ENOFOUND); 246 } else { 247 match self.pop_block(list_guard) { 248 Ok(ret) => return Ok(ret), 249 Err(err) => return Err(err), 250 } 251 } 252 } 253 254 /// @brief 对query_addr_region进行封装 255 /// 256 /// @param exp 内存区域的大小(2^exp) 257 /// 258 /// @return Ok(Box<MmioBuddyAddrRegion>)符合要求的内存块信息结构体。 259 /// @return Err(MmioResult) 没有满足要求的内存块时,返回__query_addr_region的错误码。 260 fn mmio_buddy_query_addr_region( 261 &self, 262 exp: u32, 263 ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> { 264 let list_guard: &mut SpinLockGuard<MmioFreeRegionList> = 265 &mut self.free_regions[exp2index(exp)].lock(); 266 match self.query_addr_region(exp, list_guard) { 267 Ok(ret) => return Ok(ret), 268 Err(err) => { 269 kdebug!("mmio_buddy_query_addr_region failed"); 270 return Err(err); 271 } 272 } 273 } 274 /// @brief 往指定的地址空间链表中添加一个地址区域 275 /// 276 /// @param region 要被添加的地址结构体 277 /// 278 /// @param list_guard 目标链表 279 fn push_block( 280 &self, 281 region: Box<MmioBuddyAddrRegion>, 282 list_guard: &mut SpinLockGuard<MmioFreeRegionList>, 283 ) { 284 list_guard.list.push_back(region); 285 list_guard.num_free += 1; 286 } 287 288 /// @brief 根据地址和内存块大小,计算伙伴块虚拟内存的地址 289 #[inline(always)] 290 fn calculate_block_vaddr(&self, vaddr: u64, exp: u32) -> u64 { 291 return vaddr ^ (1 << exp); 292 } 293 294 /// @brief 寻找并弹出指定内存块的伙伴块 295 /// 296 /// @param region 对应内存块的信息 297 /// 298 /// @param exp 内存块大小 299 /// 300 /// @param list_guard 【exp】对应的链表 301 /// 302 /// @return Ok(Box<MmioBuddyAddrRegion) 返回伙伴块的引用 303 /// @return Err(MmioResult) 304 /// - 当链表为空,返回ISEMPTY 305 /// - 没有找到伙伴块,返回ENOFOUND 306 fn pop_buddy_block( 307 &self, 308 vaddr: u64, 309 exp: u32, 310 list_guard: &mut SpinLockGuard<MmioFreeRegionList>, 311 ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> { 312 if list_guard.list.len() == 0 { 313 return Err(MmioResult::ISEMPTY); 314 } else { 315 //计算伙伴块的地址 316 let buddy_vaddr = self.calculate_block_vaddr(vaddr, exp); 317 318 // element 只会有一个元素 319 let mut element: Vec<Box<MmioBuddyAddrRegion>> = list_guard 320 .list 321 .drain_filter(|x| x.vaddr == buddy_vaddr) 322 .collect(); 323 if element.len() == 1 { 324 list_guard.num_free -= 1; 325 return Ok(element.pop().unwrap()); 326 } 327 328 //没有找到对应的伙伴块 329 return Err(MmioResult::ENOFOUND); 330 } 331 } 332 333 /// @brief 从指定空闲链表中取出内存区域 334 /// 335 /// @param list_guard 【exp】对应的链表 336 /// 337 /// @return Ok(Box<MmioBuddyAddrRegion>) 内存块信息结构体的引用。 338 /// 339 /// @return Err(MmioResult) 当链表为空,无法删除时,返回ISEMPTY 340 fn pop_block( 341 &self, 342 list_guard: &mut SpinLockGuard<MmioFreeRegionList>, 343 ) -> Result<Box<MmioBuddyAddrRegion>, MmioResult> { 344 if !list_guard.list.is_empty() { 345 list_guard.num_free -= 1; 346 return Ok(list_guard.list.pop_back().unwrap()); 347 } 348 return Err(MmioResult::ISEMPTY); 349 } 350 351 /// @brief 合并所有2^{exp}大小的内存块 352 /// 353 /// @param exp 内存块大小的幂(2^exp) 354 /// 355 /// @param list_guard exp对应的链表 356 /// 357 /// @param high_list_guard exp+1对应的链表 358 /// 359 /// @return Ok(MmioResult) 合并成功返回SUCCESS 360 /// @return Err(MmioResult) 361 /// - 内存块过少,无法合并,返回EINVAL 362 /// - pop_buddy_block调用出错,返回其错误码 363 /// - merge_blocks调用出错,返回其错误码 364 fn merge_all_exp( 365 &self, 366 exp: u32, 367 list_guard: &mut SpinLockGuard<MmioFreeRegionList>, 368 high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>, 369 ) -> Result<MmioResult, MmioResult> { 370 // 至少要两个内存块才能合并 371 if list_guard.num_free <= 1 { 372 return Err(MmioResult::EINVAL); 373 } 374 loop { 375 if list_guard.num_free <= 1 { 376 break; 377 } 378 // 获取内存块 379 let vaddr: u64 = list_guard.list.back().unwrap().vaddr; 380 // 获取伙伴内存块 381 match self.pop_buddy_block(vaddr, exp, list_guard) { 382 Err(err) => { 383 return Err(err); 384 } 385 Ok(buddy_region) => { 386 let region: Box<MmioBuddyAddrRegion> = list_guard.list.pop_back().unwrap(); 387 let copy_region: Box<MmioBuddyAddrRegion> = Box::new(MmioBuddyAddrRegion { 388 vaddr: region.vaddr, 389 }); 390 // 在两块内存都被取出之后才进行合并 391 match self.merge_blocks(region, buddy_region, exp, high_list_guard) { 392 Err(err) => { 393 // 如果合并失败了要将取出来的元素放回去 394 self.push_block(copy_region, list_guard); 395 kdebug!("merge_all_exp: merge_blocks failed"); 396 return Err(err); 397 } 398 Ok(_) => continue, 399 } 400 } 401 } 402 } 403 return Ok(MmioResult::SUCCESS); 404 } 405 406 /// @brief 合并两个【已经从链表中取出】的内存块 407 /// 408 /// @param region_1 第一个内存块 409 /// 410 /// @param region_2 第二个内存 411 /// 412 /// @return Ok(MmioResult) 成功返回SUCCESS 413 /// 414 /// @return Err(MmioResult) 两个内存块不是伙伴块,返回EINVAL 415 fn merge_blocks( 416 &self, 417 region_1: Box<MmioBuddyAddrRegion>, 418 region_2: Box<MmioBuddyAddrRegion>, 419 exp: u32, 420 high_list_guard: &mut SpinLockGuard<MmioFreeRegionList>, 421 ) -> Result<MmioResult, MmioResult> { 422 // 判断是否为伙伴块 423 if region_1.vaddr != self.calculate_block_vaddr(region_2.vaddr, exp) { 424 return Err(MmioResult::EINVAL); 425 } 426 // 将大的块放进下一级链表 427 self.push_block(region_1, high_list_guard); 428 return Ok(MmioResult::SUCCESS); 429 } 430 431 /// @brief 创建一块mmio区域,并将vma绑定到initial_mm 432 /// 433 /// @param size mmio区域的大小(字节) 434 /// 435 /// @param vm_flags 要把vma设置成的标志 436 /// 437 /// @param res_vaddr 返回值-分配得到的虚拟地址 438 /// 439 /// @param res_length 返回值-分配的虚拟地址空间长度 440 /// 441 /// @return Ok(i32) 成功返回0 442 /// 443 /// @return Err(i32) 失败返回错误码 444 pub fn create_mmio( 445 &self, 446 size: u32, 447 vm_flags: vm_flags_t, 448 res_vaddr: *mut u64, 449 res_length: *mut u64, 450 ) -> Result<i32, i32> { 451 if size > PAGE_1G_SIZE || size == 0 { 452 return Err(-(EPERM as i32)); 453 } 454 let mut retval: i32 = 0; 455 // 计算前导0 456 let mut size_exp: u32 = 31 - size.leading_zeros(); 457 // 记录最终申请的空间大小 458 let mut new_size: u32 = size; 459 // 对齐要申请的空间大小 460 // 如果要申请的空间大小小于4k,则分配4k 461 if size_exp < PAGE_4K_SHIFT { 462 new_size = PAGE_4K_SIZE; 463 size_exp = PAGE_4K_SHIFT; 464 } else if (new_size & (!(1 << size_exp))) != 0 { 465 // 向左对齐空间大小 466 size_exp += 1; 467 new_size = 1 << size_exp; 468 } 469 match MMIO_POOL.mmio_buddy_query_addr_region(size_exp) { 470 Ok(region) => { 471 unsafe { 472 *res_vaddr = region.vaddr; 473 *res_length = new_size as u64; 474 } 475 // 创建vma 476 let flags: u64 = vm_flags | (VM_IO | VM_DONTCOPY) as u64; 477 let len_4k: u64 = (new_size % PAGE_2M_SIZE) as u64; 478 let len_2m: u64 = new_size as u64 - len_4k; 479 let mut loop_i: u64 = 0; 480 // 先分配2M的vma 481 loop { 482 if loop_i >= len_2m { 483 break; 484 } 485 let vma: *mut *mut vm_area_struct = null_mut(); 486 retval = unsafe { 487 mm_create_vma( 488 &mut initial_mm, 489 region.vaddr + loop_i, 490 PAGE_2M_SIZE.into(), 491 flags, 492 null_mut(), 493 vma, 494 ) 495 }; 496 if retval != 0 { 497 kdebug!( 498 "failed to create mmio 2m vma. pid = {:?}", 499 current_pcb().pid 500 ); 501 unsafe { 502 vm_area_del(*vma); 503 vm_area_free(*vma); 504 } 505 return Err(retval); 506 } 507 loop_i += PAGE_2M_SIZE as u64; 508 } 509 // 分配4K的vma 510 loop_i = len_2m; 511 loop { 512 if loop_i >= size as u64 { 513 break; 514 } 515 let vma: *mut *mut vm_area_struct = null_mut(); 516 retval = unsafe { 517 mm_create_vma( 518 &mut initial_mm, 519 region.vaddr + loop_i, 520 PAGE_4K_SIZE.into(), 521 flags, 522 null_mut(), 523 vma, 524 ) 525 }; 526 if retval != 0 { 527 kdebug!( 528 "failed to create mmio 4k vma. pid = {:?}", 529 current_pcb().pid 530 ); 531 unsafe { 532 vm_area_del(*vma); 533 vm_area_free(*vma); 534 } 535 return Err(retval); 536 } 537 loop_i += PAGE_4K_SIZE as u64; 538 } 539 } 540 Err(_) => { 541 kdebug!("failed to create mmio vma.pid = {:?}", current_pcb().pid); 542 return Err(-(ENOMEM as i32)); 543 } 544 } 545 return Ok(retval); 546 } 547 548 /// @brief 取消mmio的映射并将地址空间归还到buddy中 549 /// 550 /// @param vaddr 起始的虚拟地址 551 /// 552 /// @param length 要归还的地址空间的长度 553 /// 554 /// @return Ok(i32) 成功返回0 555 /// 556 /// @return Err(i32) 失败返回错误码 557 pub fn release_mmio(&self, vaddr: u64, length: u64) -> Result<i32, i32> { 558 //先将要释放的空间取消映射 559 unsafe { 560 mm_unmap(&mut initial_mm, vaddr, length, false); 561 } 562 let mut loop_i: u64 = 0; 563 loop { 564 if loop_i >= length { 565 break; 566 } 567 // 获取要释放的vma的结构体 568 let vma: *mut vm_area_struct = unsafe { vma_find(&mut initial_mm, vaddr + loop_i) }; 569 if vma == null_mut() { 570 kdebug!( 571 "mmio_release failed: vma not found. At address: {:?}, pid = {:?}", 572 vaddr + loop_i, 573 current_pcb().pid 574 ); 575 return Err(-(EINVAL as i32)); 576 } 577 // 检查vma起始地址是否正确 578 if unsafe { (*vma).vm_start != (vaddr + loop_i) } { 579 kdebug!( 580 "mmio_release failed: addr_start is not equal to current: {:?}. pid = {:?}", 581 vaddr + loop_i, 582 current_pcb().pid 583 ); 584 return Err(-(EINVAL as i32)); 585 } 586 // 将vma对应空间归还 587 match MMIO_POOL.give_back_block(unsafe { (*vma).vm_start }, unsafe { 588 31 - ((*vma).vm_end - (*vma).vm_start).leading_zeros() 589 }) { 590 Ok(_) => { 591 loop_i += unsafe { (*vma).vm_end - (*vma).vm_start }; 592 unsafe { 593 vm_area_del(vma); 594 vm_area_free(vma); 595 } 596 } 597 Err(err) => { 598 // vma对应空间没有成功归还的话,就不删除vma 599 kdebug!( 600 "mmio_release give_back failed: pid = {:?}", 601 current_pcb().pid 602 ); 603 return Err(err); 604 } 605 } 606 } 607 return Ok(0); 608 } 609 } 610 611 /// @brief mmio伙伴系统内部的地址区域结构体 612 pub struct MmioBuddyAddrRegion { 613 vaddr: u64, 614 } 615 impl MmioBuddyAddrRegion { 616 pub fn new() -> Self { 617 return MmioBuddyAddrRegion { 618 ..Default::default() 619 }; 620 } 621 } 622 impl Default for MmioBuddyAddrRegion { 623 fn default() -> Self { 624 MmioBuddyAddrRegion { 625 vaddr: Default::default(), 626 } 627 } 628 } 629 630 /// @brief 空闲页数组结构体 631 pub struct MmioFreeRegionList { 632 /// 存储mmio_buddy的地址链表 633 list: LinkedList<Box<MmioBuddyAddrRegion>>, 634 /// 空闲块的数量 635 num_free: i64, 636 } 637 impl MmioFreeRegionList { 638 fn new() -> Self { 639 return MmioFreeRegionList { 640 ..Default::default() 641 }; 642 } 643 } 644 impl Default for MmioFreeRegionList { 645 fn default() -> Self { 646 MmioFreeRegionList { 647 list: Default::default(), 648 num_free: 0, 649 } 650 } 651 } 652 653 /// @brief 初始化mmio的伙伴系统 654 #[no_mangle] 655 pub extern "C" fn __mmio_buddy_init() { 656 // 创建一堆1GB的地址块 657 let cnt_1g_blocks: u32 = ((MMIO_TOP - MMIO_BASE) / PAGE_1G_SIZE as i64) as u32; 658 let mut vaddr_base: u64 = MMIO_BASE as u64; 659 for _ in 0..cnt_1g_blocks { 660 match MMIO_POOL.give_back_block(vaddr_base, PAGE_1G_SHIFT) { 661 Ok(_) => { 662 vaddr_base += PAGE_1G_SIZE as u64; 663 } 664 Err(_) => { 665 kerror!("__mmio_buddy_init failed"); 666 return; 667 } 668 } 669 } 670 } 671 672 /// @brief 将内存对象大小的幂转换成内存池中的数组的下标 673 /// 674 /// @param exp内存大小 675 /// 676 /// @return 内存池数组下标 677 #[inline(always)] 678 fn exp2index(exp: u32) -> usize { 679 return (exp - 12) as usize; 680 } 681 682 /// @brief 创建一块mmio区域,并将vma绑定到initial_mm 683 /// 684 /// @param size mmio区域的大小(字节) 685 /// 686 /// @param vm_flags 要把vma设置成的标志 687 /// 688 /// @param res_vaddr 返回值-分配得到的虚拟地址 689 /// 690 /// @param res_length 返回值-分配的虚拟地址空间长度 691 /// 692 /// @return int 错误码 693 #[no_mangle] 694 pub extern "C" fn mmio_create( 695 size: u32, 696 vm_flags: vm_flags_t, 697 res_vaddr: *mut u64, 698 res_length: *mut u64, 699 ) -> i32 { 700 if let Err(err) = MMIO_POOL.create_mmio(size, vm_flags, res_vaddr, res_length) { 701 return err; 702 } else { 703 return 0; 704 } 705 } 706 707 /// @brief 取消mmio的映射并将地址空间归还到buddy中 708 /// 709 /// @param vaddr 起始的虚拟地址 710 /// 711 /// @param length 要归还的地址空间的长度 712 /// 713 /// @return Ok(i32) 成功返回0 714 /// 715 /// @return Err(i32) 失败返回错误码 716 #[no_mangle] 717 pub extern "C" fn mmio_release(vaddr: u64, length: u64) -> i32 { 718 if let Err(err) = MMIO_POOL.release_mmio(vaddr, length) { 719 return err; 720 } else { 721 return 0; 722 } 723 } 724