Find the starting address of an available chunk of pages Returns the index and virtual address of the start of the chunk or None if no chunks available
(
level_4_physaddr: u64
)
| 490 | /// Returns the index and virtual address of the start of the chunk |
| 491 | /// or None if no chunks available |
| 492 | pub fn find_available_page_chunk( |
| 493 | level_4_physaddr: u64 |
| 494 | ) -> Option<VirtAddr> { |
| 495 | |
| 496 | let memory_info = unsafe {MEMORY_INFO.as_mut().unwrap()}; |
| 497 | |
| 498 | let l4_table: &mut PageTable = unsafe { |
| 499 | &mut *(memory_info.physical_memory_offset |
| 500 | + level_4_physaddr).as_mut_ptr()}; |
| 501 | let l4_entry = &mut l4_table[MEMORY_CHUNK_L4_ENTRY]; |
| 502 | |
| 503 | if l4_entry.is_unused() { |
| 504 | // L3 table not allocated -> Create |
| 505 | let (_new_table_ptr, new_table_physaddr) = create_empty_pagetable(); |
| 506 | l4_entry.set_addr(PhysAddr::new(new_table_physaddr), |
| 507 | PageTableFlags::PRESENT | |
| 508 | PageTableFlags::WRITABLE | |
| 509 | PageTableFlags::USER_ACCESSIBLE); |
| 510 | } |
| 511 | let l3_table: &PageTable = unsafe { |
| 512 | & *(memory_info.physical_memory_offset |
| 513 | + l4_entry.addr().as_u64()).as_ptr()}; |
| 514 | |
| 515 | // Each entry in l3_table from FIRST to LAST inclusive |
| 516 | // is a separate chunk |
| 517 | for ind in MEMORY_CHUNK_L3_FIRST..=MEMORY_CHUNK_L3_LAST { |
| 518 | let entry = &l3_table[ind]; |
| 519 | if entry.is_unused() { |
| 520 | // Found an empty chunk |
| 521 | // Convert L4 and L3 index into virtual address |
| 522 | return Some(VirtAddr::new(((MEMORY_CHUNK_L4_ENTRY as u64) << 39) | |
| 523 | (ind << 30) as u64)); |
| 524 | } |
| 525 | } |
| 526 | None |
| 527 | } |
| 528 | |
| 529 | /// Free a memory chunk, releasing the pages back to the frame allocator |
| 530 | pub fn free_page_chunk( |
no test coverage detected