@@ -66,11 +66,12 @@ static void add_remappings(vMemory& memory,
6666 throw MachineException (" Invalid remapping address" , remapping.virt );
6767 if (remapping.size % vMemory::PageSize () != 0 )
6868 throw MachineException (" Invalid remapping size" , remapping.size );
69- const auto virt_tera_page = (remapping.virt >> 39UL ) & 511 ;
70- const auto virt_giga_page = (remapping.virt >> 30UL ) & 511 ;
69+ const auto virt_tera_page = (remapping.virt >> 39U ) & 511 ;
70+ auto virt_giga_page = (remapping.virt >> 30U ) & 511 ;
7171
7272 uint64_t paddr_base = remapping.phys ;
73- if (paddr_base == 0x0 ) {
73+ // Blackout remappings are used to reserve/create unmapped virtual memory space
74+ if (paddr_base == 0x0 && !remapping.blackout ) {
7475 constexpr auto PD_ALIGN_MASK = (1ULL << 21U ) - 1 ;
7576 // Over-allocate rounding up to nearest 2MB
7677 paddr_base = memory.machine .mmap_allocate (remapping.size + PD_ALIGN_MASK);
@@ -89,25 +90,33 @@ static void add_remappings(vMemory& memory,
8990 auto pdpt_addr = pml4[virt_tera_page] & PDE64_ADDR_MASK;
9091 auto * pdpt = memory.page_at (pdpt_addr);
9192
92- // Allocate the gigapage with 512x 2MB entries
93- if (pdpt[virt_giga_page] == 0 ) {
94- const auto giga_page = free_page;
95- free_page += 0x1000 ;
96- pdpt[virt_giga_page] = PDE64_PRESENT | PDE64_USER | PDE64_RW | giga_page;
97- }
93+ constexpr auto PDPT_ALIGN_MASK = (1ULL << 30U ) - 1 ;
94+ const auto n_pd_pages = ((remapping.size + PDPT_ALIGN_MASK) >> 30UL ) & 511 ;
95+ for (uint64_t n_pd = 0 ; n_pd < n_pd_pages; n_pd++)
96+ {
97+ // Allocate the gigapage with 512x 2MB entries
98+ if (pdpt[virt_giga_page] == 0 ) {
99+ const auto giga_page = free_page;
100+ free_page += 0x1000 ;
101+ pdpt[virt_giga_page] = PDE64_PRESENT | PDE64_USER | PDE64_RW | giga_page;
102+ }
98103
99- auto pd_addr = pdpt[virt_giga_page] & PDE64_ADDR_MASK;
100- auto * pd = memory.page_at (pd_addr);
104+ auto pd_addr = pdpt[virt_giga_page] & PDE64_ADDR_MASK;
105+ auto * pd = memory.page_at (pd_addr);
101106
102- // Create 2MB entries for remapping size
103- const auto n_2mb_pages = (remapping.size >> 21UL ) & 511 ;
104- for (uint64_t i = 0 ; i < 512 ; i++)
105- {
106- const auto paddr = paddr_base + (i << 21UL );
107- if (i < n_2mb_pages)
108- pd[i] = PDE64_PRESENT | flags | PDE64_PS | paddr;
109- else
110- pd[i] = 0 ;
107+ // Create 2MB entries for remapping size
108+ constexpr auto PD_ALIGN_MASK = (1ULL << 21U ) - 1 ;
109+ const auto n_2mb_pages = ((remapping.size + PD_ALIGN_MASK) >> 21UL ) & 511 ;
110+ for (uint64_t i = 0 ; i < 512 ; i++)
111+ {
112+ if (i < n_2mb_pages && !remapping.blackout ) {
113+ const auto paddr = paddr_base + (i << 21UL );
114+ pd[i] = PDE64_PRESENT | flags | PDE64_PS | paddr;
115+ }
116+ else pd[i] = 0 ; // Unmapped 2MB page (remainder or blackout)
117+ }
118+
119+ virt_giga_page++; // Next gigapage
111120 }
112121
113122 // Track the first seen executable mapping, allowing mmap to use it for
@@ -306,6 +315,11 @@ uint64_t setup_amd64_paging(vMemory& memory,
306315 uint64_t flags = PDE64_USER | PDE64_NX;
307316 if (vmem.writable ) flags |= PDE64_RW;
308317 if (vmem.executable ) flags &= ~PDE64_NX;
318+ if (vmem.blackout ) flags = 0 ;
319+ if constexpr (true ) {
320+ printf (" * Remapping 0x%lX -> 0x%lX size 0x%lX write=%d exec=%d blackout=%d\n " ,
321+ vmem.virt , vmem.phys , vmem.size , vmem.writable , vmem.executable , vmem.blackout );
322+ }
309323 add_remappings (memory, vmem, pml4, flags, free_page);
310324 }
311325
0 commit comments