/// Changes a mapping in the PageTable
///
/// # Arguments
///  - `addr`: Identifies the mapping to be changed (can be anywhere in the mapped region)
///  - `action`: What action to perform: remove / update
///
/// # Returns
/// The affected virtual address region [`VAddr`, `VAddr` + usize), the underlying mapped
/// physical address, and the old flags (or current flags if modify operation didn't change
/// the flags).
Changes a mapping in the PageTable
Changes a mapping in the PageTable
fn modify_generic<'a>(
        &'a mut self,
        addr: VAddr,
        action: Modify,
    ) -> Result<(VAddr, PAddr, usize, MapAction), KError> {
        let pml4_idx = pml4_index(addr);
        if self.pml4[pml4_idx].is_present() {
            let pdpt_idx = pdpt_index(addr);
            let pdpt = self.get_pdpt_mut(self.pml4[pml4_idx]);
            if pdpt[pdpt_idx].is_present() {
                if pdpt[pdpt_idx].is_page() {
                    // Page is a 1 GiB mapping, we have to return here
                    let vaddr_start = addr.align_down_to_huge_page();
                    let paddr_start = pdpt[pdpt_idx].address();
                    let old_flags: MapAction = pdpt[pdpt_idx].flags().into();
                    match action {
                        Modify::Unmap => {
                            pdpt[pdpt_idx] = PDPTEntry::new(PAddr::zero(), PDPTFlags::empty());
                        }
                        Modify::UpdateRights(new_rights) => {
                            let flags = PDPTFlags::P | PDPTFlags::PS | new_rights.to_pdpt_rights();
                            pdpt[pdpt_idx] = PDPTEntry::new(paddr_start, flags);
                        }
                    };
                    return Ok((vaddr_start, paddr_start, HUGE_PAGE_SIZE, old_flags));
                } else {
                    let pd_idx = pd_index(addr);
                    let pdpt_entry = pdpt[pdpt_idx];
                    drop(pdpt);
                    let pd = self.get_pd_mut(pdpt_entry);
                    if pd[pd_idx].is_present() {
                        if pd[pd_idx].is_page() {
                            // Encountered a 2 MiB mapping, we have to return here
                            let vaddr_start = addr.align_down_to_large_page();
                            let paddr_start = pd[pd_idx].address();
                            let old_flags: MapAction = pd[pd_idx].flags().into();
                            match action {
                                Modify::Unmap => {
                                    pd[pd_idx] = PDEntry::new(PAddr::zero(), PDFlags::empty());
                                }
                                Modify::UpdateRights(new_rights) => {
                                    let flags =
                                        PDFlags::P | PDFlags::PS | new_rights.to_pd_rights();
                                    pd[pd_idx] = PDEntry::new(paddr_start, flags);
                                }
                            };
                            return Ok((vaddr_start, paddr_start, LARGE_PAGE_SIZE, old_flags));
                        } else {
                            let pt_idx = pt_index(addr);
                            let pd_entry = pd[pd_idx];
                            drop(pd);
                            let pt = self.get_pt_mut(pd_entry);
                            if pt[pt_idx].is_present() {
                                // Encountered a 2 MiB mapping, we have to return here
                                let vaddr_start = addr.align_down_to_base_page();
                                let paddr_start = pt[pt_idx].address();
                                let old_flags: MapAction = pt[pt_idx].flags().into();
                                match action {
                                    Modify::Unmap => {
                                        pt[pt_idx] = PTEntry::new(PAddr::zero(), PTFlags::empty());
                                    }
                                    Modify::UpdateRights(new_rights) => {
                                        let flags = PTFlags::P | new_rights.to_pt_rights();
                                        pt[pt_idx] = PTEntry::new(paddr_start, flags);
                                    }
                                };
                                return Ok((vaddr_start, paddr_start, BASE_PAGE_SIZE, old_flags));
                            }
                        }
                    }
                }
            }
        }
        // else:
        Err(KError::NotMapped)
    }
fn modify_generic < ' a > ( & ' a mut self , addr : VAddr , action : Modify , ) -> Result < ( VAddr , PAddr , usize , MapAction ) , KError > { let pml4_idx = pml4_index ( addr ) ; if self . pml4 [ pml4_idx ] . is_present ( ) { let pdpt_idx = pdpt_index ( addr ) ; let pdpt = self . get_pdpt_mut ( self . pml4 [ pml4_idx ] ) ; if pdpt [ pdpt_idx ] . is_present ( ) { if pdpt [ pdpt_idx ] . is_page ( ) { // Page is a 1 GiB mapping, we have to return here let vaddr_start = addr . align_down_to_huge_page ( ) ; let paddr_start = pdpt [ pdpt_idx ] . address ( ) ; let old_flags : MapAction = pdpt [ pdpt_idx ] . flags ( ) . into ( ) ; match action { Modify :: Unmap => { pdpt [ pdpt_idx ] = PDPTEntry :: new ( PAddr :: zero ( ) , PDPTFlags :: empty ( ) ) ; } Modify :: UpdateRights ( new_rights ) => { let flags = PDPTFlags :: P | PDPTFlags :: PS | new_rights . to_pdpt_rights ( ) ; pdpt [ pdpt_idx ] = PDPTEntry :: new ( paddr_start , flags ) ; } } ; return Ok ( ( vaddr_start , paddr_start , HUGE_PAGE_SIZE , old_flags ) ) ; } else { let pd_idx = pd_index ( addr ) ; let pdpt_entry = pdpt [ pdpt_idx ] ; drop ( pdpt ) ; let pd = self . get_pd_mut ( pdpt_entry ) ; if pd [ pd_idx ] . is_present ( ) { if pd [ pd_idx ] . is_page ( ) { // Encountered a 2 MiB mapping, we have to return here let vaddr_start = addr . align_down_to_large_page ( ) ; let paddr_start = pd [ pd_idx ] . address ( ) ; let old_flags : MapAction = pd [ pd_idx ] . flags ( ) . into ( ) ; match action { Modify :: Unmap => { pd [ pd_idx ] = PDEntry :: new ( PAddr :: zero ( ) , PDFlags :: empty ( ) ) ; } Modify :: UpdateRights ( new_rights ) => { let flags = PDFlags :: P | PDFlags :: PS | new_rights . to_pd_rights ( ) ; pd [ pd_idx ] = PDEntry :: new ( paddr_start , flags ) ; } } ; return Ok ( ( vaddr_start , paddr_start , LARGE_PAGE_SIZE , old_flags ) ) ; } else { let pt_idx = pt_index ( addr ) ; let pd_entry = pd [ pd_idx ] ; drop ( pd ) ; let pt = self . get_pt_mut ( pd_entry ) ; if pt [ pt_idx ] . is_present ( ) { // Encountered a 2 MiB mapping, we have to return here let vaddr_start = addr . align_down_to_base_page ( ) ; let paddr_start = pt [ pt_idx ] . address ( ) ; let old_flags : MapAction = pt [ pt_idx ] . flags ( ) . into ( ) ; match action { Modify :: Unmap => { pt [ pt_idx ] = PTEntry :: new ( PAddr :: zero ( ) , PTFlags :: empty ( ) ) ; } Modify :: UpdateRights ( new_rights ) => { let flags = PTFlags :: P | new_rights . to_pt_rights ( ) ; pt [ pt_idx ] = PTEntry :: new ( paddr_start , flags ) ; } } ; return Ok ( ( vaddr_start , paddr_start , BASE_PAGE_SIZE , old_flags ) ) ; } } } } } } // else: Err ( KError :: NotMapped ) }
Changes a mapping in the PageTable
Changes a mapping in the PageTable
The affected virtual address region [`VAddr`, `VAddr` + usize), the underlying mapped
physical address, and the old flags (or current flags if modify operation didn't change
the flags).
The affected virtual address region [ ` VAddr ` ` VAddr ` + usize ) the underlying mapped physical address and the old flags ( or current flags if modify operation didn ' t change the flags ) .
&'a mut self
addr
VAddr
action
Modify