Remove a page chunk from a page table Doesn't free any of the pages Returns physical address and level of the page table that it points to
(
level_4_physaddr: u64,
address: VirtAddr,
take: bool
)
| 549 | /// |
| 550 | /// Returns physical address and level of the page table that it points to |
| 551 | pub fn get_page_chunk( |
| 552 | level_4_physaddr: u64, |
| 553 | address: VirtAddr, |
| 554 | take: bool |
| 555 | ) -> Result<(PhysAddr, u16), usize> { |
| 556 | let memory_info = unsafe {MEMORY_INFO.as_mut().unwrap()}; |
| 557 | |
| 558 | // Check that the p4 and p3 index is in range |
| 559 | if usize::from(address.p4_index()) != MEMORY_CHUNK_L4_ENTRY { |
| 560 | // Incorrect P4 entry |
| 561 | return Err(syscalls::SYSCALL_ERROR_PARAM); |
| 562 | } |
| 563 | if (usize::from(address.p3_index()) < MEMORY_CHUNK_L3_FIRST) || |
| 564 | (usize::from(address.p3_index()) > MEMORY_CHUNK_L3_LAST) { |
| 565 | // P3 out of range |
| 566 | return Err(syscalls::SYSCALL_ERROR_PARAM); |
| 567 | } |
| 568 | |
| 569 | // Follow page table addresses |
| 570 | let l4_table: &PageTable = unsafe { |
| 571 | & *(memory_info.physical_memory_offset |
| 572 | + level_4_physaddr).as_mut_ptr()}; |
| 573 | let l4_entry = &l4_table[MEMORY_CHUNK_L4_ENTRY]; |
| 574 | |
| 575 | if l4_entry.is_unused() { |
| 576 | // No chunks allocated |
| 577 | return Err(syscalls::SYSCALL_ERROR_MEMORY); |
| 578 | } |
| 579 | |
| 580 | let l3_table: &mut PageTable = unsafe { |
| 581 | &mut *(memory_info.physical_memory_offset |
| 582 | + l4_entry.addr().as_u64()).as_mut_ptr()}; |
| 583 | let l3_entry = &mut l3_table[address.p3_index()]; |
| 584 | |
| 585 | if l3_entry.is_unused() { |
| 586 | // Not allocated => Double free? |
| 587 | return Err(syscalls::SYSCALL_ERROR_DOUBLEFREE); |
| 588 | } |
| 589 | |
| 590 | let physaddr = l3_entry.addr(); |
| 591 | |
| 592 | if take { |
| 593 | // Mark entry as empty |
| 594 | l3_entry.set_unused(); |
| 595 | } |
| 596 | |
| 597 | // Return address of level 2 page table |
| 598 | Ok((physaddr, 2)) |
| 599 | } |
| 600 | |
| 601 | /// Finds an available page chunk entry, stores the physical address |
| 602 | /// in the page table and returns the virtual address. |
no test coverage detected