2020-04-11 21:59:39 +00:00
|
|
|
#include <kernel/chroma.h>
|
|
|
|
|
2020-07-07 23:38:59 +00:00
|
|
|
//__attribute__((aligned(4096))) static size_t Pagetable[512] = {0};
|
2020-04-11 21:59:39 +00:00
|
|
|
|
|
|
|
#define LAST_ENTRY 0xFF8
|
|
|
|
|
|
|
|
#define SET_ADDRESS(a,b) ((*(size_t*) (a)) = (size_t) b)
|
|
|
|
|
|
|
|
#define KiB 1 * 1024
|
|
|
|
#define MiB 1 * 1024 * KiB
|
|
|
|
|
|
|
|
#define USERWRITEABLE_FLAGS(a) ((a & 0xFFFFFF00) + 0x83)
|
|
|
|
|
|
|
|
#define PAGE_PRESENT 1
|
|
|
|
#define PAGE_RW 2
|
|
|
|
|
|
|
|
|
|
|
|
void InitPaging() {
|
|
|
|
|
|
|
|
size_t* PML4 = (size_t*) 0xFFA000; // Layer 4
|
|
|
|
size_t* PDPE_RAM = (size_t*) 0xFFE000; // Layer 3, contains map for the first 4GB of RAM
|
|
|
|
size_t* PDE_RAM = (size_t*) 0xFFF000;
|
|
|
|
|
|
|
|
size_t* PDPE_KERNEL = (size_t*) 0xFFB000; // Layer 3, contains map for the Kernel and everything it needs to run.
|
|
|
|
size_t* PDE_KERNEL_FB = (size_t*) 0xFFC000; // Layer 2, contains map for the linear framebuffer.
|
|
|
|
|
|
|
|
size_t* PT_KERNEL = (size_t*) 0xFFD000; // Layer 1, the page table for the kernel itself.
|
|
|
|
|
|
|
|
size_t fb_ptr = (size_t) &fb;
|
|
|
|
|
|
|
|
SET_ADDRESS(PML4, PDPE_RAM); // 3rd Layer entry for RAM
|
|
|
|
SET_ADDRESS(PML4 + LAST_ENTRY, PDPE_KERNEL); // 3rd Layer entry for Kernel
|
|
|
|
|
|
|
|
SET_ADDRESS(PDPE_KERNEL + LAST_ENTRY, PDE_KERNEL_FB); // 2nd Layer entry for the framebuffer
|
|
|
|
|
|
|
|
// Set the 480th entry (PDE_KERNEL_FB + (480 * 8))
|
|
|
|
// To the framebuffer + flags
|
|
|
|
SET_ADDRESS(PDE_KERNEL_FB + 3840, USERWRITEABLE_FLAGS(fb_ptr));
|
|
|
|
|
|
|
|
// In 4 byte increments, we're gonna map 3840 (the framebuffer)
|
|
|
|
// Up to (4096 - 8) in the PDE_KERNEL_FB with 2MB paging.
|
|
|
|
size_t MappingIterations = 1;
|
|
|
|
for(size_t i = 3844; i < 4088; i += 4) {
|
|
|
|
SET_ADDRESS(PDE_KERNEL_FB + i, USERWRITEABLE_FLAGS(fb_ptr) + (MappingIterations * (2 * MiB)));
|
|
|
|
MappingIterations++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we map the last entry of PDE_KERNEL_FB to our Page Table
|
|
|
|
SET_ADDRESS(PDE_KERNEL_FB + LAST_ENTRY, PT_KERNEL);
|
|
|
|
|
|
|
|
// Mapping the kernel into the page tables....
|
|
|
|
|
|
|
|
SET_ADDRESS(PT_KERNEL, 0xFF8001); // bootldr, bootinfo
|
|
|
|
SET_ADDRESS(PT_KERNEL + 8, 0xFF9001); // environment
|
|
|
|
|
|
|
|
// Map the kernel itself
|
|
|
|
SET_ADDRESS(PT_KERNEL + 16, KernelAddr + 1);
|
|
|
|
|
|
|
|
// Iterate through the pages, identity mapping each one
|
|
|
|
MappingIterations = 1;
|
|
|
|
size_t MappingOffset = 0x14;
|
|
|
|
for(size_t i = 0; i < ((KernelEnd - KernelAddr) >> 12); i++) {
|
|
|
|
// Page Table + (0x10 increasing by 0x04 each time) = x * 4KiB
|
|
|
|
SET_ADDRESS(PT_KERNEL + MappingOffset, (MappingIterations * (4 * KiB)));
|
|
|
|
MappingOffset += 4;
|
|
|
|
MappingIterations++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we need to map the core stacks. Top-down, from 0xDFF8
|
|
|
|
// There's always at least one core, so we do that one fixed.
|
|
|
|
// TODO: Account for 0-core CPUs
|
|
|
|
SET_ADDRESS(PT_KERNEL + LAST_ENTRY, 0xF14003);
|
|
|
|
MappingIterations = 1;
|
|
|
|
// For every core:
|
2020-07-07 23:38:59 +00:00
|
|
|
for(size_t i = 0; i < (bootldr.numcores + 3U) >> 2; i++) {
|
2020-04-11 21:59:39 +00:00
|
|
|
// PT_KERNEL[512 - (iterations + 1)] = 0x14003 + (iterations * page-width)
|
|
|
|
SET_ADDRESS(PT_KERNEL + LAST_ENTRY - (MappingIterations * 8), 0xF14003 + (4096 * MappingIterations));
|
|
|
|
MappingIterations++;
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_ADDRESS(PDPE_RAM, PDE_RAM + PAGE_PRESENT + PAGE_RW);
|
|
|
|
SET_ADDRESS(PDPE_RAM + 8, 0xF10000 + PAGE_PRESENT + PAGE_RW);
|
|
|
|
SET_ADDRESS(PDPE_RAM + 16, 0xF11000 + PAGE_PRESENT + PAGE_RW);
|
|
|
|
SET_ADDRESS(PDPE_RAM + 24, 0xF12000 + PAGE_PRESENT + PAGE_RW);
|
|
|
|
|
|
|
|
// Identity map 4GB of ram
|
|
|
|
// Each page table can only hold 512 entries, but we
|
|
|
|
// just set up 4 of them - overflowing PDE_RAM (0xF000)
|
|
|
|
// will take us into 0x10000, into 0x11000, into 0x120000.
|
|
|
|
for(size_t i = 0; i < 512 * 4/*GB*/; i++) {
|
|
|
|
// add PDE_RAM, 4
|
|
|
|
// mov eax, 0x83
|
|
|
|
// add eax, 2*1024*1024
|
|
|
|
SET_ADDRESS(PDE_RAM + (i * 4), USERWRITEABLE_FLAGS(i * (2 * MiB)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Map first 2MB of memory
|
|
|
|
SET_ADDRESS(PDE_RAM, 0xF13000 + PAGE_PRESENT + PAGE_RW);
|
|
|
|
|
|
|
|
for(size_t i = 0; i < 512; i++) {
|
|
|
|
SET_ADDRESS(0xF13000 + i * 4, i * (4 * KiB) + PAGE_PRESENT + PAGE_RW);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0xA000 should now contain our memory map.
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void InitPagingOldImpl() {
|
|
|
|
|
|
|
|
// Disable paging so that we can work with the pagetable
|
|
|
|
//size_t registerTemp = ReadControlRegister(0);
|
|
|
|
//UNSET_PGBIT(registerTemp);
|
|
|
|
//WriteControlRegister(0, registerTemp);
|
|
|
|
|
|
|
|
// Clear space for our pagetable
|
|
|
|
size_t PagetableDest = 0x1000;
|
2020-07-07 23:38:59 +00:00
|
|
|
memset((char*)PagetableDest, 0, 4096);
|
2020-04-11 21:59:39 +00:00
|
|
|
|
|
|
|
// Start setting pagetable indexes
|
|
|
|
*((size_t*)PagetableDest) = 0x2003; // PDP at 0x2000, present & r/w
|
|
|
|
*((size_t*)PagetableDest + 0x1000) = 0x3003; // PDT at 0x3000, present & r/w
|
|
|
|
*((size_t*)PagetableDest + 0x2000) = 0x4003; // PT at 0x4000, present & r/w
|
|
|
|
|
|
|
|
size_t value = 0x3;
|
|
|
|
size_t offset = 8;
|
|
|
|
for(size_t i = 0; i < 512; i++) { // 512 iterations (entries into the page table)
|
|
|
|
*((size_t*) PagetableDest + offset) = value; // We're setting 512 bytes with x003
|
|
|
|
// (identity mapping the first 4 megabytes of memory)
|
|
|
|
// (mapping the page table to itself)
|
|
|
|
value += 4096; // Point to start of next page
|
|
|
|
offset += 8; // + 8 bytes (next entry in list)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enable PAE paging
|
|
|
|
size_t reg = ReadControlRegister(4);
|
|
|
|
SET_PAEBIT(reg);
|
|
|
|
WriteControlRegister(4, reg);
|
|
|
|
|
|
|
|
WriteControlRegister(3, PagetableDest);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* size_t registerTemp = ReadControlRegister(4);
|
|
|
|
if(registerTemp & (1 << 7)) {
|
|
|
|
TOGGLE_PGEBIT(registerTemp);
|
|
|
|
WriteControlRegister(4, registerTemp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(registerTemp & (1 << 7))
|
|
|
|
WriteControlRegister(4, registerTemp ^ (1 << 7));
|
|
|
|
|
|
|
|
size_t CPUIDReturn;
|
|
|
|
asm volatile("cpuid" : "=d" (CPUIDReturn) : "a" (0x80000001) : "%rbx", "%rcx");
|
|
|
|
|
|
|
|
if(CPUIDReturn & (1 << 26)) {
|
|
|
|
SerialPrintf("System supports 1GB pages.\r\n");
|
|
|
|
|
|
|
|
if(registerTemp & (1 << 12)) {
|
|
|
|
SerialPrintf("PML5 paging available - using that instead.\r\n");
|
|
|
|
|
|
|
|
if(MemorySize > (1ULL << 57))
|
|
|
|
SerialPrintf("System has over 128Petabytes of RAM. Please consider upgrading the OS on your supercomputer.\r\n");
|
|
|
|
|
|
|
|
size_t MaxPML5 = 1;
|
|
|
|
size_t MaxPML4 = 1;
|
|
|
|
size_t MaxPDP = 512;
|
|
|
|
|
|
|
|
size_t LastPML4Entry = 512;
|
|
|
|
size_t LastPDPEntry = 512;
|
|
|
|
|
|
|
|
size_t MemorySearchDepth = MemorySize;
|
|
|
|
|
|
|
|
while(MemorySearchDepth > (256ULL << 30)) {
|
|
|
|
MaxPML5++;
|
|
|
|
MemorySearchDepth -= (256ULL << 30);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(MaxPML5 > 512)
|
|
|
|
MaxPML5 = 512;
|
|
|
|
|
|
|
|
if(MemorySearchDepth) {
|
|
|
|
LastPDPEntry = ( (MemorySearchDepth + ((1 << 30) - 1)) & (~0ULL << 30)) >> 30;
|
|
|
|
|
|
|
|
if(MaxPML5 > 512)
|
|
|
|
MaxPML5 = 512;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t PML4Size = PAGETABLE_SIZE * MaxPML5;
|
|
|
|
size_t PDPSize = PML4Size * MaxPML4;
|
|
|
|
|
|
|
|
size_t PML4Base = AllocatePagetable(PML4Size + PDPSize);
|
|
|
|
size_t PDPBase = PML4Base + PML4Size;
|
|
|
|
|
|
|
|
for(size_t PML5Entry = 0; PML5Entry < MaxPML5; PML5Entry++) {
|
|
|
|
Pagetable[PML5Entry] = PML4Base + (PML5Entry << 12);
|
|
|
|
|
|
|
|
if(PML5Entry == (MaxPML5 - 1))
|
|
|
|
MaxPML4 = LastPML4Entry;
|
|
|
|
|
|
|
|
for(size_t PML4Entry = 0; PML4Entry < MaxPML4; PML4Entry++) {
|
|
|
|
|
|
|
|
((size_t*) Pagetable[PML5Entry])[PML4Entry] = PDPBase + (((PML5Entry << 9) + PML5Entry) << 12);
|
|
|
|
|
|
|
|
if( (PML5Entry == (MaxPML5 - 1)) && (PML4Entry == (MaxPML4 -1)) )
|
|
|
|
MaxPDP = LastPDPEntry;
|
|
|
|
|
|
|
|
for(size_t PDPEntry = 0; PDPEntry < MaxPDP; PDPEntry++) {
|
|
|
|
((size_t* ) ((size_t* ) Pagetable[PML5Entry])[PML4Entry])[PDPEntry] = ( ((PML5Entry << 18) + (PML4Entry << 9) + PDPEntry) << 30) | (0x83);
|
|
|
|
}
|
|
|
|
|
|
|
|
((size_t* ) Pagetable[PML5Entry])[PML4Entry] |= 0x3;
|
|
|
|
}
|
|
|
|
|
|
|
|
Pagetable[PML5Entry] |= 0x3;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SerialPrintf("PML4 available - using that instead.\r\n");
|
|
|
|
size_t MemorySearchDepth = MemorySize;
|
|
|
|
|
|
|
|
if(MemorySearchDepth > (1ULL << 48))
|
|
|
|
SerialPrintf("RAM limited to 256TB.\r\n");
|
|
|
|
|
|
|
|
size_t MaxPML4 = 1;
|
|
|
|
size_t MaxPDP = 512;
|
|
|
|
|
|
|
|
size_t LastPDPEntry = 512;
|
|
|
|
|
|
|
|
while(MemorySearchDepth > (512ULL << 30)) {
|
|
|
|
MaxPML4++;
|
|
|
|
MemorySearchDepth -= (512ULL << 30);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(MaxPML4 > 512)
|
|
|
|
MaxPML4 = 512;
|
|
|
|
|
|
|
|
if(MemorySearchDepth) {
|
|
|
|
LastPDPEntry = ( (MemorySearchDepth + ((1 << 30) - 1)) & (~0ULL << 30)) >> 30;
|
|
|
|
|
|
|
|
if(LastPDPEntry > 512)
|
|
|
|
LastPDPEntry = 512;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t PDPSize = PAGETABLE_SIZE * MaxPML4;
|
|
|
|
size_t PDPBase = AllocatePagetable(PDPSize);
|
|
|
|
|
|
|
|
for(size_t PML4Entry = 0; PML4Entry < MaxPML4; PML4Entry++) {
|
|
|
|
Pagetable[PML4Entry] = PDPBase + (PML4Entry << 12);
|
|
|
|
|
|
|
|
if(PML4Entry == (MaxPML4 - 1)) {
|
|
|
|
MaxPDP = LastPDPEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(size_t PDPEntry = 0; PDPEntry < MaxPDP; PDPEntry++) {
|
|
|
|
((size_t* ) Pagetable[PML4Entry])[PDPEntry] = (((PML4Entry << 9) + PDPEntry) << 30) | 0x83;
|
|
|
|
}
|
|
|
|
|
|
|
|
Pagetable[PML4Entry] |= 0x3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SerialPrintf("System does not support 1GB pages - using 2MiB paging instead.\r\n");
|
|
|
|
|
|
|
|
size_t MemorySearchDepth = MemorySize;
|
|
|
|
|
|
|
|
if(MemorySearchDepth > (1ULL << 48)) {
|
|
|
|
SerialPrintf("Usable RAM is limited to 256TB, and the page table alone will use 1GB of space in memory.\r\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t MaxPML4 = 1, MaxPDP = 512, MaxPD = 512, LastPDPEntry = 1;
|
|
|
|
|
|
|
|
while(MemorySearchDepth > (512ULL << 30)) {
|
|
|
|
MaxPML4++;
|
|
|
|
MemorySearchDepth -= (512ULL << 30);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(MaxPML4 > 512)
|
|
|
|
MaxPML4 = 512;
|
|
|
|
|
|
|
|
if(MemorySearchDepth) {
|
|
|
|
LastPDPEntry = ((MemorySearchDepth + ((1 << 30) - 1)) & (~0ULL << 30)) >> 30;
|
|
|
|
|
|
|
|
if(LastPDPEntry > 512)
|
|
|
|
LastPDPEntry = 512;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t PDPSize = PAGETABLE_SIZE * MaxPML4;
|
|
|
|
size_t PDSize = PDPSize * MaxPDP;
|
|
|
|
|
|
|
|
size_t PDPBase = AllocatePagetable(PDPSize + PDSize);
|
|
|
|
size_t PDBase = PDPBase + PDSize;
|
|
|
|
|
|
|
|
for(size_t PML4Entry = 0; PML4Entry < MaxPML4; PML4Entry++) {
|
|
|
|
Pagetable[PML4Entry] = PDBase + (PML4Entry << 12);
|
|
|
|
|
|
|
|
if(PML4Entry == (MaxPML4 - 1)) {
|
|
|
|
MaxPDP = LastPDPEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(size_t PDPEntry = 0; PDPEntry < MaxPDP; PDPEntry++) {
|
|
|
|
( (size_t* ) Pagetable[PML4Entry])[PDPEntry] = PDBase + (((PML4Entry << 9) + PDPEntry) << 12);
|
|
|
|
|
|
|
|
for(size_t PDEntry = 0; PDEntry < MaxPD; PDEntry++) {
|
|
|
|
( (size_t* ) ((size_t*) Pagetable[PML4Entry])[PDPEntry])[PDEntry] = (( (PML4Entry << 18) + (PDPEntry << 9) + PDPEntry) << 21) | 0x83;
|
|
|
|
}
|
|
|
|
|
|
|
|
( (size_t* ) Pagetable[PML4Entry])[PDPEntry] |= 0x3;
|
|
|
|
}
|
|
|
|
|
|
|
|
Pagetable[PML4Entry] |= 0x3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
WriteControlRegister(3, Pagetable);
|
|
|
|
|
|
|
|
registerTemp = ReadControlRegister(4);
|
|
|
|
if(!(registerTemp & (1 << 7))) {
|
|
|
|
TOGGLE_PGEBIT(registerTemp);
|
|
|
|
WriteControlRegister(4, registerTemp);
|
|
|
|
}*/
|