Fixed a bug resulting from a mistake in the boot 64-bit paging setup.
This was an interesting bug to find. Was getting spurious triple faults in the slab allocator. The problem was that the boot paging setup code was mapping all page tables it created into the virtual address space, but in the kernel no areas were being created to cover them, so during arch_vm_init_end() the pages for them ended up being freed and then overwritten later on. Fixed by unmapping page tables after populating them in long_mmu_init().
This commit is contained in:
@@ -106,6 +106,13 @@ long_mmu_init()
|
||||
memset(pml4, 0, B_PAGE_SIZE);
|
||||
gKernelArgs.arch_args.vir_pgdir = fix_address((uint64)(addr_t)pml4);
|
||||
|
||||
// Store the virtual memory usage information.
|
||||
gKernelArgs.virtual_allocated_range[0].start = KERNEL_LOAD_BASE_64BIT;
|
||||
gKernelArgs.virtual_allocated_range[0].size = mmu_get_virtual_usage();
|
||||
gKernelArgs.num_virtual_allocated_ranges = 1;
|
||||
gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_LOAD_BASE_64BIT
|
||||
+ gKernelArgs.virtual_allocated_range[0].size, 0x200000);
|
||||
|
||||
// Find the highest physical memory address. We map all physical memory
|
||||
// into the kernel address space, so we want to make sure we map everything
|
||||
// we have available.
|
||||
@@ -144,8 +151,12 @@ long_mmu_init()
|
||||
for (uint64 j = 0; j < 0x40000000; j += 0x200000) {
|
||||
pageDir[j / 0x200000] = (i + j) | kLargePageMappingFlags;
|
||||
}
|
||||
|
||||
mmu_free(pageDir, B_PAGE_SIZE);
|
||||
}
|
||||
|
||||
mmu_free(pdpt, B_PAGE_SIZE);
|
||||
|
||||
// Allocate tables for the kernel mappings.
|
||||
|
||||
pdpt = (uint64*)mmu_allocate_page(&physicalAddress);
|
||||
@@ -156,23 +167,18 @@ long_mmu_init()
|
||||
memset(pageDir, 0, B_PAGE_SIZE);
|
||||
pdpt[510] = physicalAddress | kTableMappingFlags;
|
||||
|
||||
// Store the virtual memory usage information.
|
||||
gKernelArgs.virtual_allocated_range[0].start = KERNEL_LOAD_BASE_64BIT;
|
||||
gKernelArgs.virtual_allocated_range[0].size = mmu_get_virtual_usage();
|
||||
gKernelArgs.num_virtual_allocated_ranges = 1;
|
||||
|
||||
// We can now allocate page tables and duplicate the mappings across from
|
||||
// the 32-bit address space to them.
|
||||
pageTable = NULL;
|
||||
for (uint32 i = 0; i < gKernelArgs.virtual_allocated_range[0].size
|
||||
/ B_PAGE_SIZE; i++) {
|
||||
if ((i % 512) == 0) {
|
||||
if (pageTable)
|
||||
mmu_free(pageTable, B_PAGE_SIZE);
|
||||
|
||||
pageTable = (uint64*)mmu_allocate_page(&physicalAddress);
|
||||
memset(pageTable, 0, B_PAGE_SIZE);
|
||||
pageDir[i / 512] = physicalAddress | kTableMappingFlags;
|
||||
|
||||
// Just performed another virtual allocation, account for it.
|
||||
gKernelArgs.virtual_allocated_range[0].size += B_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// Get the physical address to map.
|
||||
@@ -183,8 +189,10 @@ long_mmu_init()
|
||||
pageTable[i % 512] = physicalAddress | kPageMappingFlags;
|
||||
}
|
||||
|
||||
gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_LOAD_BASE_64BIT
|
||||
+ gKernelArgs.virtual_allocated_range[0].size, 0x200000);
|
||||
if (pageTable)
|
||||
mmu_free(pageTable, B_PAGE_SIZE);
|
||||
mmu_free(pageDir, B_PAGE_SIZE);
|
||||
mmu_free(pdpt, B_PAGE_SIZE);
|
||||
|
||||
// Sort the address ranges.
|
||||
sort_address_ranges(gKernelArgs.physical_memory_range,
|
||||
|
||||
@@ -324,7 +324,7 @@ arch_system_info_init(struct kernel_args *args)
|
||||
status_t
|
||||
arch_thread_init(struct kernel_args *args)
|
||||
{
|
||||
return B_OK;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4,
|
||||
vm_page_reservation* reservation,
|
||||
TranslationMapPhysicalPageMapper* pageMapper, int32& mapCount)
|
||||
{
|
||||
TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(%#" B_PRIxADDR ", "
|
||||
TRACE("X86PagingMethod64Bit::PageTableForAddress(%#" B_PRIxADDR ", "
|
||||
"%d)\n", virtualAddress, allocateTables);
|
||||
|
||||
// Get the PDPT.
|
||||
@@ -215,7 +215,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4,
|
||||
phys_addr_t physicalPDPT
|
||||
= (phys_addr_t)page->physical_page_number * B_PAGE_SIZE;
|
||||
|
||||
TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(): creating PDPT "
|
||||
TRACE("X86PagingMethod64Bit::PageTableForAddress(): creating PDPT "
|
||||
"for va %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n", virtualAddress,
|
||||
physicalPDPT);
|
||||
|
||||
@@ -245,7 +245,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4,
|
||||
phys_addr_t physicalPageDir
|
||||
= (phys_addr_t)page->physical_page_number * B_PAGE_SIZE;
|
||||
|
||||
TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(): creating page "
|
||||
TRACE("X86PagingMethod64Bit::PageTableForAddress(): creating page "
|
||||
"directory for va %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n",
|
||||
virtualAddress, physicalPageDir);
|
||||
|
||||
@@ -275,7 +275,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4,
|
||||
phys_addr_t physicalPageTable
|
||||
= (phys_addr_t)page->physical_page_number * B_PAGE_SIZE;
|
||||
|
||||
TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(): creating page "
|
||||
TRACE("X86PagingMethod64Bit::PageTableForAddress(): creating page "
|
||||
"table for va %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n",
|
||||
virtualAddress, physicalPageTable);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user