fn unmap_single_internal(&mut self, vaddr: VirtAddr, frame: bool) {
        debug_assert!(vaddr.is_page_aligned());

        let p3 = unwrap_or_return!(self.p4.next_table_mut(vaddr.p4_index()));
        let p2 = unwrap_or_return!(p3.next_table_mut(vaddr.p3_index()));
        let p1 = unwrap_or_return!(p2.next_table_mut(vaddr.p2_index()));

        let e = &mut p1.entries[vaddr.p1_index()];
        if !e.flags().contains(EntryFlags::PRESENT) {
            return;
        }

        if frame {
            with_pmm(|pmm| {
                // The pmm wants to write to the page, so if it is read-only, we need to make it writable.
                let flags = e.flags();
                if !flags.contains(EntryFlags::WRITABLE) {
                    e.set_flags(flags | EntryFlags::WRITABLE | EntryFlags::NX);

                    // Sadly, we have to invalidate here too...
                    unsafe {
                        invalidate_page(vaddr.as_u64());
                    }
                }

                pmm.push_top(vaddr, e.phys_addr_unchecked())
            });
        }

        e.clear();
        unsafe {
            invalidate_page(vaddr.as_u64());
        }

        p1.decrease_used_count();

        // This will recursively free the page tables: p2 and p3 also if needed.
        if p1.used_count() == 0 {
            let vaddr = VirtAddr::new(p1 as *mut _ as usize);
            self.unmap_single_internal(vaddr, true);
        }
    }
/// Unmaps single page, if frame is true, also puts the physical frame on the stack. (internal use only).
Unmaps single page, if frame is true, also puts the physical frame on the stack. (internal use only).
Unmaps single page if frame is true also puts the physical frame on the stack . ( internal use only ) .
fn unmap_single_internal(&mut self, vaddr: VirtAddr, frame: bool) {
        debug_assert!(vaddr.is_page_aligned());
        let p3 = unwrap_or_return!(self.p4.next_table_mut(vaddr.p4_index()));
        let p2 = unwrap_or_return!(p3.next_table_mut(vaddr.p3_index()));
        let p1 = unwrap_or_return!(p2.next_table_mut(vaddr.p2_index()));
        let e = &mut p1.entries[vaddr.p1_index()];
        if !e.flags().contains(EntryFlags::PRESENT) {
            return;
        }
        if frame {
            with_pmm(|pmm| {
                // The pmm wants to write to the page, so if it is read-only, we need to make it writable.
                let flags = e.flags();
                if !flags.contains(EntryFlags::WRITABLE) {
                    e.set_flags(flags | EntryFlags::WRITABLE | EntryFlags::NX);
                    // Sadly, we have to invalidate here too...
                    unsafe {
                        invalidate_page(vaddr.as_u64());
                    }
                }
                pmm.push_top(vaddr, e.phys_addr_unchecked())
            });
        }
        e.clear();
        unsafe {
            invalidate_page(vaddr.as_u64());
        }
        p1.decrease_used_count();
        // This will recursively free the page tables: p2 and p3 also if needed.
        if p1.used_count() == 0 {
            let vaddr = VirtAddr::new(p1 as *mut _ as usize);
            self.unmap_single_internal(vaddr, true);
        }
    }
fn unmap_single_internal ( & mut self , vaddr : VirtAddr , frame : bool ) { debug_assert ! ( vaddr is_page_aligned ( ) ) ; let p3 = unwrap_or_return ! ( self p4 next_table_mut ( vaddr p4_index ( ) ) ) ; let p2 = unwrap_or_return ! ( p3 next_table_mut ( vaddr p3_index ( ) ) ) ; let p1 = unwrap_or_return ! ( p2 next_table_mut ( vaddr p2_index ( ) ) ) ; let e = & mut p1 . entries [ vaddr . p1_index ( ) ] ; if ! e . flags ( ) . contains ( EntryFlags :: PRESENT ) { return ; } if frame { with_pmm ( | pmm | { // The pmm wants to write to the page, so if it is read-only, we need to make it writable. let flags = e . flags ( ) ; if ! flags . contains ( EntryFlags :: WRITABLE ) { e . set_flags ( flags | EntryFlags :: WRITABLE | EntryFlags :: NX ) ; // Sadly, we have to invalidate here too... unsafe { invalidate_page ( vaddr . as_u64 ( ) ) ; } } pmm . push_top ( vaddr , e . phys_addr_unchecked ( ) ) } ) ; } e . clear ( ) ; unsafe { invalidate_page ( vaddr . as_u64 ( ) ) ; } p1 . decrease_used_count ( ) ; // This will recursively free the page tables: p2 and p3 also if needed. if p1 . used_count ( ) == 0 { let vaddr = VirtAddr :: new ( p1 as * mut _ as usize ) ; self . unmap_single_internal ( vaddr , true ) ; } }
Unmaps single page, if frame is true, also puts the physical frame on the stack.
Unmaps single page if frame is true also puts the physical frame on the stack .
&mut self
vaddr
VirtAddr
frame
bool
&mut self
vaddr
VirtAddr
frame
bool