Map all physical memory in the long mode paging setup.
Since x86_64 has such a large virtual address space all available physical memory can be mapped in to it. The physical page mapper implementation for x86_64 will use this mapping. Also changed the mapping code to map kernel pages with the global flag.
This commit is contained in:
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "long.h"
|
#include "long.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
// Include the x86_64 version of descriptors.h
|
// Include the x86_64 version of descriptors.h
|
||||||
@@ -24,6 +26,12 @@
|
|||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const uint64 kTableMappingFlags = 0x3;
|
||||||
|
static const uint64 kLargePageMappingFlags = 0x183;
|
||||||
|
static const uint64 kPageMappingFlags = 0x103;
|
||||||
|
// Global, R/W, Present
|
||||||
|
|
||||||
|
|
||||||
/*! Convert a 32-bit address to a 64-bit address. */
|
/*! Convert a 32-bit address to a 64-bit address. */
|
||||||
static inline uint64
|
static inline uint64
|
||||||
fix_address(uint64 address)
|
fix_address(uint64 address)
|
||||||
@@ -87,36 +95,68 @@ long_idt_init()
|
|||||||
static void
|
static void
|
||||||
long_mmu_init()
|
long_mmu_init()
|
||||||
{
|
{
|
||||||
|
uint64* pml4;
|
||||||
|
uint64* pdpt;
|
||||||
|
uint64* pageDir;
|
||||||
|
uint64* pageTable;
|
||||||
addr_t physicalAddress;
|
addr_t physicalAddress;
|
||||||
|
|
||||||
// Allocate the top level PML4.
|
// Allocate the top level PML4.
|
||||||
uint64* pml4 = (uint64*)mmu_allocate_page(&gKernelArgs.arch_args.phys_pgdir);
|
pml4 = (uint64*)mmu_allocate_page(&gKernelArgs.arch_args.phys_pgdir);
|
||||||
memset(pml4, 0, B_PAGE_SIZE);
|
memset(pml4, 0, B_PAGE_SIZE);
|
||||||
gKernelArgs.arch_args.vir_pgdir = (uint64)(addr_t)pml4;
|
gKernelArgs.arch_args.vir_pgdir = (uint64)(addr_t)pml4;
|
||||||
|
|
||||||
// Identity map the first 1GB of memory, do so using large pages.
|
// 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.
|
||||||
|
uint64 maxAddress = 0;
|
||||||
|
for (uint32 i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) {
|
||||||
|
maxAddress = std::max(maxAddress,
|
||||||
|
gKernelArgs.physical_memory_range[i].start
|
||||||
|
+ gKernelArgs.physical_memory_range[i].size);
|
||||||
|
}
|
||||||
|
|
||||||
uint64* pdpt = (uint64*)mmu_allocate_page(&physicalAddress);
|
// Want to map at least 4GB, there may be stuff other than usable RAM that
|
||||||
|
// could be in the first 4GB of physical address space.
|
||||||
|
maxAddress = std::max(maxAddress, (uint64)0x100000000ll);
|
||||||
|
maxAddress = ROUNDUP(maxAddress, 0x40000000);
|
||||||
|
|
||||||
|
// Currently only use 1 PDPT (512GB). This will need to change if someone
|
||||||
|
// wants to use Haiku on a box with more than 512GB of RAM but that's
|
||||||
|
// probably not going to happen any time soon.
|
||||||
|
if (maxAddress / 0x40000000 > 512)
|
||||||
|
panic("Can't currently support more than 512GB of RAM!");
|
||||||
|
|
||||||
|
// Create page tables for the physical map area. Also map this PDPT
|
||||||
|
// temporarily at the bottom of the address space so that we are identity
|
||||||
|
// mapped.
|
||||||
|
|
||||||
|
pdpt = (uint64*)mmu_allocate_page(&physicalAddress);
|
||||||
memset(pdpt, 0, B_PAGE_SIZE);
|
memset(pdpt, 0, B_PAGE_SIZE);
|
||||||
pml4[0] = physicalAddress | 0x3;
|
pml4[510] = physicalAddress | kTableMappingFlags;
|
||||||
|
pml4[0] = physicalAddress | kTableMappingFlags;
|
||||||
|
|
||||||
uint64* pageDir = (uint64*)mmu_allocate_page(&physicalAddress);
|
for (uint64 i = 0; i < maxAddress; i += 0x40000000) {
|
||||||
memset(pageDir, 0, B_PAGE_SIZE);
|
dprintf("mapping %llu GB\n", i / 0x40000000);
|
||||||
pdpt[0] = physicalAddress | 0x3;
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < 512; i++) {
|
pageDir = (uint64*)mmu_allocate_page(&physicalAddress);
|
||||||
pageDir[i] = (i * 0x200000) | 0x83;
|
memset(pageDir, 0, B_PAGE_SIZE);
|
||||||
|
pdpt[i / 0x40000000] = physicalAddress | kTableMappingFlags;
|
||||||
|
|
||||||
|
for (uint64 j = 0; j < 0x40000000; j += 0x200000) {
|
||||||
|
pageDir[j / 0x200000] = (i + j) | kLargePageMappingFlags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate tables for the kernel mappings.
|
// Allocate tables for the kernel mappings.
|
||||||
|
|
||||||
pdpt = (uint64*)mmu_allocate_page(&physicalAddress);
|
pdpt = (uint64*)mmu_allocate_page(&physicalAddress);
|
||||||
memset(pdpt, 0, B_PAGE_SIZE);
|
memset(pdpt, 0, B_PAGE_SIZE);
|
||||||
pml4[511] = physicalAddress | 0x3;
|
pml4[511] = physicalAddress | kTableMappingFlags;
|
||||||
|
|
||||||
pageDir = (uint64*)mmu_allocate_page(&physicalAddress);
|
pageDir = (uint64*)mmu_allocate_page(&physicalAddress);
|
||||||
memset(pageDir, 0, B_PAGE_SIZE);
|
memset(pageDir, 0, B_PAGE_SIZE);
|
||||||
pdpt[510] = physicalAddress | 0x3;
|
pdpt[510] = physicalAddress | kTableMappingFlags;
|
||||||
|
|
||||||
// Store the virtual memory usage information.
|
// Store the virtual memory usage information.
|
||||||
gKernelArgs.virtual_allocated_range[0].start = KERNEL_BASE_64BIT;
|
gKernelArgs.virtual_allocated_range[0].start = KERNEL_BASE_64BIT;
|
||||||
@@ -125,13 +165,13 @@ long_mmu_init()
|
|||||||
|
|
||||||
// We can now allocate page tables and duplicate the mappings across from
|
// We can now allocate page tables and duplicate the mappings across from
|
||||||
// the 32-bit address space to them.
|
// the 32-bit address space to them.
|
||||||
uint64* pageTable = NULL;
|
pageTable = NULL;
|
||||||
for (uint32 i = 0; i < gKernelArgs.virtual_allocated_range[0].size
|
for (uint32 i = 0; i < gKernelArgs.virtual_allocated_range[0].size
|
||||||
/ B_PAGE_SIZE; i++) {
|
/ B_PAGE_SIZE; i++) {
|
||||||
if ((i % 512) == 0) {
|
if ((i % 512) == 0) {
|
||||||
pageTable = (uint64*)mmu_allocate_page(&physicalAddress);
|
pageTable = (uint64*)mmu_allocate_page(&physicalAddress);
|
||||||
memset(pageTable, 0, B_PAGE_SIZE);
|
memset(pageTable, 0, B_PAGE_SIZE);
|
||||||
pageDir[i / 512] = physicalAddress | 0x3;
|
pageDir[i / 512] = physicalAddress | kTableMappingFlags;
|
||||||
|
|
||||||
// Just performed another virtual allocation, account for it.
|
// Just performed another virtual allocation, account for it.
|
||||||
gKernelArgs.virtual_allocated_range[0].size += B_PAGE_SIZE;
|
gKernelArgs.virtual_allocated_range[0].size += B_PAGE_SIZE;
|
||||||
@@ -142,7 +182,7 @@ long_mmu_init()
|
|||||||
&physicalAddress))
|
&physicalAddress))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pageTable[i % 512] = physicalAddress | 0x3;
|
pageTable[i % 512] = physicalAddress | kPageMappingFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_BASE_64BIT
|
gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_BASE_64BIT
|
||||||
|
|||||||
Reference in New Issue
Block a user