@@ -21,7 +21,7 @@ use crate::{
2121 arch:: { self , virt:: get_page_size} ,
2222 boot:: { BootInfo , PhysMemoryUsage } ,
2323 memory:: virt:: { allocator:: VirtualAllocator , mmu:: PageTable } ,
24- util:: { align_down, align_up, mutex:: spin:: SpinMutex } ,
24+ util:: { align_down, align_up, divide_up , mutex:: spin:: SpinMutex } ,
2525} ;
2626use alloc:: sync:: Arc ;
2727use bump:: BumpAllocator ;
@@ -44,6 +44,10 @@ impl PhysAddr {
4444 pub fn as_hhdm < T > ( self ) -> * mut T {
4545 VirtAddr ( self . 0 + HHDM_START . get ( ) . 0 ) . as_ptr ( )
4646 }
47+
48+ pub ( crate ) fn zero_hhdm ( self , len : usize ) {
49+ unsafe { ptr:: write_bytes ( self . as_hhdm :: < u8 > ( ) , 0 , len) } ;
50+ }
4751}
4852
4953/// Represents a virtual address. It can't be directly read from or written to.
@@ -325,36 +329,28 @@ pub fn MEMORY_STAGE() {
325329 arch:: virt:: get_hhdm_base( ) . value( )
326330 ) ;
327331
328- // We record metadata for every single page of available memory in a large array.
329- // This array is contiguous in virtual memory, but is sparsely populated.
330- // Only those array entries which represent usable memory are mapped .
332+ // We record metadata for every single physical page in a large array.
333+ // This array is contiguous in virtual memory so it can be represented as
334+ // an ordinary Rust slice by the physical allocator .
331335
332336 // The offset where we start mapping the page array.
333337 log ! ( "Highest physical address is {:#018x}" , highest_phys. 0 ) ;
334338 let page_base = arch:: virt:: get_pfndb_base ( ) ;
335- let page_length = highest_phys. 0 / size_of :: < Page > ( ) ;
336339 let page_size = get_page_size ( ) ;
337-
338- memory_map
339- . iter ( )
340- . filter ( |x| x. length != 0 )
341- . for_each ( |entry| {
342- let length = align_up ( ( entry. length / page_size) * size_of :: < Page > ( ) , page_size) ;
343- let virt = align_down (
344- ( page_base + entry. address . 0 / page_size * size_of :: < Page > ( ) ) . value ( ) ,
345- page_size,
346- ) ;
347-
348- for page in ( 0 ..=length) . step_by ( page_size) {
349- table
350- . map_single :: < BumpAllocator > (
351- ( virt + page) . into ( ) ,
352- BumpAllocator :: alloc ( 1 , AllocFlags :: empty ( ) ) . unwrap ( ) ,
353- VmFlags :: Read | VmFlags :: Write ,
354- )
355- . unwrap ( ) ;
356- }
357- } ) ;
340+ let page_length = divide_up ( highest_phys. 0 , page_size) ;
341+ let page_array_len = align_up ( page_length * size_of :: < Page > ( ) , page_size) ;
342+
343+ // The physical allocator keeps the PFN database as a Rust slice, which
344+ // requires the whole range to be mapped and backed by memory.
345+ for page in ( 0 ..page_array_len) . step_by ( page_size) {
346+ table
347+ . map_single :: < BumpAllocator > (
348+ ( page_base. value ( ) + page) . into ( ) ,
349+ BumpAllocator :: alloc ( 1 , AllocFlags :: empty ( ) ) . unwrap ( ) ,
350+ VmFlags :: Read | VmFlags :: Write ,
351+ )
352+ . unwrap ( ) ;
353+ }
358354
359355 log ! (
360356 "Initalized page array region at {:#018x}" ,
@@ -386,7 +382,8 @@ pub fn MEMORY_STAGE() {
386382 // ----------------------------------------
387383
388384 // Initialize the physical memory allocator.
389- pmm:: init ( & memory_map, ( page_base. as_ptr ( ) , page_length) ) ;
385+ let page_db = unsafe { core:: slice:: from_raw_parts_mut ( page_base. as_ptr ( ) , page_length) } ;
386+ pmm:: init ( & memory_map, page_db) ;
390387
391388 // Save the page table.
392389 unsafe { virt:: KERNEL_PAGE_TABLE . init ( Arc :: new ( table) ) } ;
0 commit comments