/// A pretty generic map function, it puts the physical memory range
/// `pregion` with base and size into the virtual base at address `vbase`.
///
/// The function will try to allocate memory for page-tables as needed by
/// using the supplied `pager`.
///
/// The function tries to allocate the biggest possible pages for the allocations
/// (1 GiB, 2 MiB, 4 KiB). We require that `vbase` and `pregion` values are all aligned
/// to a base-page.
///
/// Will return an error in case a existing mapping already exists (and is not the same)
/// at a given location we're trying to map.
A pretty generic map function, it puts the physical memory range
`pregion` with base and size into the virtual base at address `vbase`.

The function will try to allocate memory for page-tables as needed by
using the supplied `pager`.

The function tries to allocate the biggest possible pages for the allocations
(1 GiB, 2 MiB, 4 KiB). We require that `vbase` and `pregion` values are all aligned
to a base-page.

Will return an error in case a existing mapping already exists (and is not the same)
at a given location we're trying to map.
A pretty generic map function it puts the physical memory range ` pregion ` with base and size into the virtual base at address ` vbase ` . The function will try to allocate memory for page - tables as needed by using the supplied ` pager ` . The function tries to allocate the biggest possible pages for the allocations ( 1 GiB 2 MiB 4 KiB ) . We require that ` vbase ` and ` pregion ` values are all aligned to a base - page . Will return an error in case a existing mapping already exists ( and is not the same ) at a given location we ' re trying to map .
pub(crate) fn map_generic(
        &mut self,
        vbase: VAddr,
        pregion: (PAddr, usize),
        rights: MapAction,
        insert_mapping: bool,
    ) -> Result<(), KError> {
        let (pbase, psize) = pregion;
        assert!(pbase.is_base_page_aligned());
        assert!(vbase.is_base_page_aligned());
        assert_eq!(psize % BASE_PAGE_SIZE, 0);
        debug!(
            "map_generic {:#x} -- {:#x} -> {:#x} -- {:#x} {}",
            vbase,
            vbase + psize,
            pbase,
            pbase + psize,
            rights
        );
        let pml4_idx = pml4_index(vbase);
        let pdpt = self.get_or_alloc_pdpt(vbase);
        let pdpt_idx = pdpt_index(vbase);
        let pdpt_entry = pdpt[pdpt_idx];
        drop(pdpt);
        let pml4_entry = self.pml4[pml4_idx];
        if self.can_map_as_huge_page(pml4_entry, pbase, psize, vbase, rights) {
            // Start inserting mappings here in case we can map something as 1 GiB pages
            return self.insert_huge_mappings(
                pdpt_idx,
                vbase,
                pbase,
                psize,
                rights,
                insert_mapping,
            );
        } else if !pdpt_entry.is_present() {
            trace!(
                "Mapping 0x{:x} -- 0x{:x} is smaller than 1 GiB, going deeper.",
                vbase,
                vbase + psize
            );
            let pd = self.new_pd();
            let pdpt = self.get_pdpt_mut(pml4_entry);
            pdpt[pdpt_idx] = pd;
        }
        let pdpt = self.get_pdpt(pml4_entry);
        let pdpt_entry = pdpt[pdpt_idx];
        drop(pdpt);
        assert!(
            pdpt[pdpt_idx].is_present(),
            "The PDPT entry we're relying on is not allocated?"
        );
        if pdpt[pdpt_idx].is_page() {
            if !insert_mapping {
                // Check if we could map in theory (no overlap)
                return Err(KError::AlreadyMapped { base: vbase });
            } else {
                panic!(
                    "An existing mapping already covers the 1 GiB range we're trying to map in (vbase:{:#x} -> pbase:{:#x})", vbase, pbase
                );
            }
        }
        let pd = self.get_pd_mut(pdpt_entry);
        let pd_idx = pd_index(vbase);
        let pd_entry = pd[pd_idx];
        drop(pd);
        // In case we can map something at a 2 MiB granularity and
        // we still have at least 2 MiB to map create large-page mappings
        if self.can_map_as_large_page(pdpt_entry, pbase, psize, vbase, rights) {
            return self.insert_large_mappings(
                pdpt_entry,
                vbase,
                pbase,
                psize,
                rights,
                insert_mapping,
            );
        } else if !pd_entry.is_present() {
            trace!(
                "Mapping 0x{:x} -- 0x{:x} is smaller than 2 MiB, going deeper.",
                vbase,
                vbase + psize
            );
            let pt = self.new_pt();
            let pd = self.get_pd_mut(pdpt_entry);
            pd[pd_idx] = pt;
        }
        let pd = self.get_pd_mut(pdpt_entry);
        assert!(
            pd[pd_idx].is_present(),
            "The PD entry we're relying on is not allocated?"
        );
        if pd[pd_idx].is_page() {
            if !insert_mapping {
                return Err(KError::AlreadyMapped { base: vbase });
            } else {
                panic!(
                    "An existing mapping already covers the 2 MiB range we're trying to map in?"
                );
            }
        }
        let pd_entry = pd[pd_idx];
        drop(pd);
        self.insert_base_mappings(pd_entry, vbase, pbase, psize, rights, insert_mapping)
    }
pub ( crate ) fn map_generic ( & mut self , vbase : VAddr , pregion : ( PAddr , usize ) , rights : MapAction , insert_mapping : bool , ) -> Result < ( ) , KError > { let ( pbase , psize ) = pregion ; assert ! ( pbase is_base_page_aligned ( ) ) ; assert ! ( vbase is_base_page_aligned ( ) ) ; assert_eq ! ( psize BASE_PAGE_SIZE 0 ) ; debug ! ( " " vbase vbase psize pbase pbase psize rights ) ; let pml4_idx = pml4_index ( vbase ) ; let pdpt = self . get_or_alloc_pdpt ( vbase ) ; let pdpt_idx = pdpt_index ( vbase ) ; let pdpt_entry = pdpt [ pdpt_idx ] ; drop ( pdpt ) ; let pml4_entry = self . pml4 [ pml4_idx ] ; if self . can_map_as_huge_page ( pml4_entry , pbase , psize , vbase , rights ) { // Start inserting mappings here in case we can map something as 1 GiB pages return self . insert_huge_mappings ( pdpt_idx , vbase , pbase , psize , rights , insert_mapping , ) ; } else if ! pdpt_entry . is_present ( ) { trace ! ( " " vbase vbase psize ) ; let pd = self . new_pd ( ) ; let pdpt = self . get_pdpt_mut ( pml4_entry ) ; pdpt [ pdpt_idx ] = pd ; } let pdpt = self . get_pdpt ( pml4_entry ) ; let pdpt_entry = pdpt [ pdpt_idx ] ; drop ( pdpt ) ; assert ! ( pdpt [ pdpt_idx ] is_present ( ) " " ) ; if pdpt [ pdpt_idx ] . is_page ( ) { if ! insert_mapping { // Check if we could map in theory (no overlap) return Err ( KError :: AlreadyMapped { base : vbase } ) ; } else { panic ! ( " " vbase pbase ) ; } } let pd = self . get_pd_mut ( pdpt_entry ) ; let pd_idx = pd_index ( vbase ) ; let pd_entry = pd [ pd_idx ] ; drop ( pd ) ; // In case we can map something at a 2 MiB granularity and // we still have at least 2 MiB to map create large-page mappings if self . can_map_as_large_page ( pdpt_entry , pbase , psize , vbase , rights ) { return self . insert_large_mappings ( pdpt_entry , vbase , pbase , psize , rights , insert_mapping , ) ; } else if ! pd_entry . is_present ( ) { trace ! ( " " vbase vbase psize ) ; let pt = self . new_pt ( ) ; let pd = self . get_pd_mut ( pdpt_entry ) ; pd [ pd_idx ] = pt ; } let pd = self . get_pd_mut ( pdpt_entry ) ; assert ! ( pd [ pd_idx ] is_present ( ) " " ) ; if pd [ pd_idx ] . is_page ( ) { if ! insert_mapping { return Err ( KError :: AlreadyMapped { base : vbase } ) ; } else { panic ! ( " " ) ; } } let pd_entry = pd [ pd_idx ] ; drop ( pd ) ; self . insert_base_mappings ( pd_entry , vbase , pbase , psize , rights , insert_mapping ) }
A pretty generic map function, it puts the physical memory range
`pregion` with base and size into the virtual base at address `vbase`.
A pretty generic map function it puts the physical memory range ` pregion ` with base and size into the virtual base at address ` vbase ` .
&mut self
vbase
VAddr
pregion
(PAddr, usize)
rights
MapAction
insert_mapping
bool