Kernel: Paging uses now PAE with 2 MiB pages
This commit is contained in:
parent
a12ddfa12a
commit
d6623def32
|
@ -211,7 +211,7 @@ namespace APIC
|
||||||
static void ParseMADT(RSDPDescriptor* rsdp)
|
static void ParseMADT(RSDPDescriptor* rsdp)
|
||||||
{
|
{
|
||||||
RSDT* root = (RSDT*)(rsdp->revision == 2 ? ((RSDPDescriptor20*)rsdp)->xsdt_address : rsdp->rsdt_address);
|
RSDT* root = (RSDT*)(rsdp->revision == 2 ? ((RSDPDescriptor20*)rsdp)->xsdt_address : rsdp->rsdt_address);
|
||||||
Paging::MapRSDP((uint32_t)root & 0xFFC00000);
|
Paging::MapPage((uint32_t)root);
|
||||||
uint32_t sdt_entry_count = (root->header.length - sizeof(root->header)) / (rsdp->revision == 2 ? 8 : 4);
|
uint32_t sdt_entry_count = (root->header.length - sizeof(root->header)) / (rsdp->revision == 2 ? 8 : 4);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < sdt_entry_count; i++)
|
for (uint32_t i = 0; i < sdt_entry_count; i++)
|
||||||
|
@ -372,10 +372,8 @@ namespace APIC
|
||||||
if (s_local_apic == 0 || s_io_apic == 0)
|
if (s_local_apic == 0 || s_io_apic == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((s_io_apic & 0xFFC00000) != (s_local_apic & 0xFFC00000))
|
Paging::MapPage(s_io_apic);
|
||||||
Kernel::panic("lapic and ioapic are not in the same 4 MiB are");
|
Paging::MapPage(s_local_apic);
|
||||||
|
|
||||||
Paging::MapAPIC(s_io_apic & 0xFFC00000);
|
|
||||||
|
|
||||||
// Enable Local APIC
|
// Enable Local APIC
|
||||||
SetMSR(IA32_APIC_BASE, (s_local_apic & 0xFFFFF000) | IA32_APIC_BASE_ENABLE, 0);
|
SetMSR(IA32_APIC_BASE, (s_local_apic & 0xFFFFF000) | IA32_APIC_BASE_ENABLE, 0);
|
||||||
|
|
|
@ -1,66 +1,88 @@
|
||||||
|
#include <kernel/CPUID.h>
|
||||||
#include <kernel/Paging.h>
|
#include <kernel/Paging.h>
|
||||||
#include <kernel/panic.h>
|
#include <kernel/panic.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define PRESENT (1 << 0)
|
||||||
|
#define READ_WRITE (1 << 1)
|
||||||
|
#define PAGE_SIZE (1 << 7)
|
||||||
|
|
||||||
namespace Paging
|
namespace Paging
|
||||||
{
|
{
|
||||||
|
|
||||||
static uint32_t s_page_directory[1024] __attribute__((aligned(4096)));
|
static uint64_t s_page_directory_pointer_table[4] __attribute__((aligned(0x20)));
|
||||||
static uint32_t s_page_table[1024] __attribute__((aligned(4096)));
|
static uint64_t s_page_directory[4 * 512] __attribute__((aligned(4096)));
|
||||||
static uint32_t s_page_table_framebuffer[1024] __attribute__((aligned(4096)));
|
|
||||||
static uint32_t s_page_table_rsdp[1024] __attribute__((aligned(4096)));
|
static bool HasRequirements()
|
||||||
static uint32_t s_page_table_apic[1024] __attribute__((aligned(4096)));
|
{
|
||||||
|
uint32_t ecx, edx;
|
||||||
|
CPUID::GetFeatures(ecx, edx);
|
||||||
|
if (!(edx & CPUID::Features::EDX_PAE))
|
||||||
|
{
|
||||||
|
derrorln("PAE not supported, halting");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Initialize()
|
void Initialize()
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < 1024; i++)
|
if (!HasRequirements())
|
||||||
s_page_directory[i] = 0x00000002;
|
asm volatile("hlt");
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 1024; i++)
|
// Identity map first 2 (2 MiB) pages
|
||||||
s_page_table[i] = (i << 12) | 0x03;
|
memset(s_page_directory, 0x00, sizeof(s_page_directory));
|
||||||
s_page_directory[0] = (uint32_t)s_page_table | 0x03;
|
s_page_directory[0] = (0x00 << 21) | PAGE_SIZE | READ_WRITE | PRESENT;
|
||||||
|
s_page_directory[1] = (0x01 << 21) | PAGE_SIZE | READ_WRITE | PRESENT;
|
||||||
|
|
||||||
|
// Initialize PDPTEs
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
s_page_directory_pointer_table[i] = (uint64_t)(&s_page_directory[512 * i]) | PRESENT;
|
||||||
|
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"movl %%eax, %%cr3;"
|
// Enable PAE
|
||||||
|
"movl %%cr4, %%eax;"
|
||||||
|
"orl $0x20, %%eax;"
|
||||||
|
"movl %%eax, %%cr4;"
|
||||||
|
|
||||||
|
// Load PDPT address to cr3
|
||||||
|
"movl %0, %%cr3;"
|
||||||
|
|
||||||
|
// Enable paging
|
||||||
"movl %%cr0, %%eax;"
|
"movl %%cr0, %%eax;"
|
||||||
"orl $0x80000001, %%eax;"
|
"orl $0x80000000, %%eax;"
|
||||||
"movl %%eax, %%cr0;"
|
"movl %%eax, %%cr0;"
|
||||||
:: "a"(s_page_directory)
|
|
||||||
|
:: "r" (s_page_directory_pointer_table)
|
||||||
|
: "eax"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
dprintln("Paging enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MapPDE(uint32_t address, uint32_t* pt)
|
void MapPage(uintptr_t address)
|
||||||
{
|
{
|
||||||
if ((address & 0xffc00000) != address)
|
if (address != ((address >> 21) << 21))
|
||||||
Kernel::panic("Trying to map non 4 MiB aligned address");
|
|
||||||
|
|
||||||
uint32_t pd_index = address >> 22;
|
|
||||||
|
|
||||||
if (!(s_page_directory[pd_index] & (1 << 0)))
|
|
||||||
{
|
{
|
||||||
// Identity map the whole page table
|
dprintln("aligning 0x{8H} to 2 MiB boundary -> 0x{8H}", address, (address >> 21) << 21);
|
||||||
for (uint32_t i = 0; i < 1024; i++)
|
address = (address >> 21) << 21;
|
||||||
pt[i] = address | (i << 12) | 0x03;
|
|
||||||
// Set the pde to point to page table
|
|
||||||
s_page_directory[pd_index] = (uint32_t)pt | 0x03;
|
|
||||||
// Flush TLB
|
|
||||||
for (uint32_t i = 0; i < 1024; i++)
|
|
||||||
asm volatile("invlpg (%0)" :: "r" (address | (i << 12)) : "memory");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MapFramebuffer(uint32_t address)
|
uint32_t pde = address >> 21;
|
||||||
{
|
|
||||||
MapPDE(address, s_page_table_framebuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapRSDP(uint32_t address)
|
dprintln("mapping pde {} (0x{8H} - 0x{8H})", pde, pde << 21, ((pde + 1) << 21) - 1);
|
||||||
{
|
|
||||||
MapPDE(address, s_page_table_rsdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapAPIC(uint32_t address)
|
if (s_page_directory[pde] & PRESENT)
|
||||||
{
|
{
|
||||||
MapPDE(address, s_page_table_apic);
|
dprintln("page already mapped");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map and flush the given address
|
||||||
|
s_page_directory[pde] = address | PAGE_SIZE | READ_WRITE | PRESENT;
|
||||||
|
asm volatile("invlpg (%0)" :: "r"(address) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -95,7 +95,7 @@ namespace VESA
|
||||||
s_height = framebuffer.height;
|
s_height = framebuffer.height;
|
||||||
s_mode = framebuffer.type;
|
s_mode = framebuffer.type;
|
||||||
|
|
||||||
Paging::MapFramebuffer(framebuffer.addr & 0xFFC00000);
|
Paging::MapPage(framebuffer.addr);
|
||||||
|
|
||||||
if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS)
|
if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,8 +7,6 @@ namespace Paging
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
|
||||||
void MapFramebuffer(uint32_t address);
|
void MapPage(uintptr_t address);
|
||||||
void MapRSDP(uint32_t address);
|
|
||||||
void MapAPIC(uint32_t address);
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue