Unverified Commit 445d0f7d authored by PhoeniX's avatar PhoeniX

Rewrite pagetable allocation

parent 37a1ebfc
Pipeline #1851 passed with stages
in 31 seconds
...@@ -151,7 +151,6 @@ class Interrupts { ...@@ -151,7 +151,6 @@ class Interrupts {
static Handler* handlers; static Handler* handlers;
static REC64 *idt; static REC64 *idt;
static GDT *gdt; static GDT *gdt;
static TSS64_ENT **tss;
static void init(); static void init();
static uint64_t handle(uint8_t intr, uint64_t stack, uint64_t *cr3); static uint64_t handle(uint8_t intr, uint64_t stack, uint64_t *cr3);
......
...@@ -64,7 +64,7 @@ class Pagetable { ...@@ -64,7 +64,7 @@ class Pagetable {
static void* rsvd_pages[rsvd_num]; static void* rsvd_pages[rsvd_num];
static Mutex page_mutex; static Mutex page_mutex;
static uint64_t last_page; static uint64_t last_page;
static void* _alloc(uint8_t avl = 0, bool nolow = false); static void* _alloc(bool low, size_t count);
static void* _map(const void* addr); static void* _map(const void* addr);
static void* _getRsvd(); static void* _getRsvd();
static void _renewRsvd(); static void _renewRsvd();
...@@ -72,7 +72,8 @@ class Pagetable { ...@@ -72,7 +72,8 @@ class Pagetable {
public: public:
static void* map(const void* mem); static void* map(const void* mem);
static void* alloc(uint8_t avl = 0); static void* alloc(size_t count = 1);
static void* lowalloc(size_t count = 1);
static void free(void* page); static void free(void* page);
}; };
......
...@@ -9,24 +9,16 @@ ...@@ -9,24 +9,16 @@
struct Interrupts::Handler { struct Interrupts::Handler {
// 68 04 03 02 01 pushq ${int_num} // 68 04 03 02 01 pushq ${int_num}
// e9 46 ec 3f 00 jmp . + {diff} // e9 46 ec 3f 00 jmp . + {diff}
uint8_t push; // == 0x68 uint8_t push[1] = { 0x68 };
uint32_t int_num; uint32_t int_num;
uint8_t reljmp; // == 0xE9 uint8_t reljmp[1] = { 0xE9 };
uint32_t diff; uint32_t diff;
Handler(): Handler(uint32_t int_num, uint32_t diff): int_num(int_num), diff(diff) {}
push(0x68), int_num(0),
reljmp(0xE9), diff(0) {}
Handler(uint32_t int_num, uint32_t diff):
push(0x68), int_num(int_num),
reljmp(0xE9), diff(diff) {}
ALIGNED_NEWARR(0x1000)
} PACKED; } PACKED;
Interrupts::REC64 *Interrupts::idt = nullptr; Interrupts::REC64 *Interrupts::idt = nullptr;
GDT *Interrupts::gdt = nullptr; GDT *Interrupts::gdt = nullptr;
TSS64_ENT **Interrupts::tss = nullptr;
List<Interrupts::Callback*> *Interrupts::callbacks = nullptr; List<Interrupts::Callback*> *Interrupts::callbacks = nullptr;
Mutex Interrupts::callback_locks[256]; Mutex Interrupts::callback_locks[256];
Mutex Interrupts::fault; Mutex Interrupts::fault;
...@@ -295,27 +287,34 @@ uint64_t __attribute__((sysv_abi)) Interrupts::handle( ...@@ -295,27 +287,34 @@ uint64_t __attribute__((sysv_abi)) Interrupts::handle(
void Interrupts::init() { void Interrupts::init() {
uint64_t ncpu = ACPI::getController()->getCPUCount(); uint64_t ncpu = ACPI::getController()->getCPUCount();
gdt = new(GDT::size(ncpu)) GDT(); gdt = reinterpret_cast<GDT*>(
tss = new TSS64_ENT*[ncpu](); Pagetable::lowalloc((GDT::size(ncpu) + 0xFFF) / 0x1000));
idt = new REC64[256](); idt = reinterpret_cast<REC64*>(
handlers = new Handler[256](); Pagetable::alloc((sizeof(REC64) * 256 + 0xFFF) / 0x1000));
handlers = reinterpret_cast<Interrupts::Handler*>(
Pagetable::alloc((sizeof(Handler) * 256 + 0xFFF) / 0x1000));
gdt->ents[0] = GDT::Entry(); gdt->ents[0] = GDT::Entry();
gdt->ents[1] = GDT::Entry(0, 0xFFFFFFFFFFFFFFFF, 0xA, 0, 1, 1, 0, 1, 0, 1); gdt->ents[1] = GDT::Entry(0, 0xFFFFFFFFFFFFFFFF, 0xA, 0, 1, 1, 0, 1, 0, 1);
gdt->ents[2] = GDT::Entry(0, 0xFFFFFFFFFFFFFFFF, 0x2, 0, 1, 1, 0, 0, 1, 1); gdt->ents[2] = GDT::Entry(0, 0xFFFFFFFFFFFFFFFF, 0x2, 0, 1, 1, 0, 0, 1, 1);
gdt->ents[3] = GDT::Entry(0, 0xFFFFFFFFFFFFFFFF, 0x2, 3, 1, 1, 0, 0, 1, 1); gdt->ents[3] = GDT::Entry(0, 0xFFFFFFFFFFFFFFFF, 0x2, 3, 1, 1, 0, 0, 1, 1);
gdt->ents[4] = GDT::Entry(0, 0xFFFFFFFFFFFFFFFF, 0xA, 3, 1, 1, 0, 1, 0, 1); gdt->ents[4] = GDT::Entry(0, 0xFFFFFFFFFFFFFFFF, 0xA, 3, 1, 1, 0, 1, 0, 1);
size_t tss_size = sizeof(TSS64_ENT) * ncpu;
size_t tss_size_pad = klib::__align(tss_size, 0x1000);
char *tssbuf = reinterpret_cast<char*>(Pagetable::alloc(2 + tss_size_pad / 0x1000));
char *tsstop = tssbuf + tss_size_pad;
Memory::fill(tsstop, 0xFF, 0x2000);
for (uint32_t idx = 0; idx < ncpu; idx++) { for (uint32_t idx = 0; idx < ncpu; idx++) {
void *stack = Pagetable::alloc(); void *stack = Pagetable::alloc();
uintptr_t stack_ptr = uintptr_t(stack) + 0x1000; uintptr_t stack_ptr = uintptr_t(stack) + 0x1000;
char *entbuf = reinterpret_cast<char*>(Heap::alloc(0x3000, 0x1000)); char *entbuf = tssbuf + sizeof(TSS64_ENT) * idx;
TSS64_ENT *ent = tss[idx] = reinterpret_cast<TSS64_ENT*>(entbuf + (0x1000 - sizeof(TSS64_ENT))); TSS64_ENT *ent = reinterpret_cast<TSS64_ENT*>(entbuf);
Memory::zero(tss[idx], sizeof(TSS64_ENT) + 0x2000);
ent->ist[0] = stack_ptr; ent->ist[0] = stack_ptr;
ent->iomap_base = sizeof(TSS64_ENT); ent->iomap_base = uint16_t(tsstop - entbuf);
gdt->sys_ents[idx] = GDT::SystemEntry( gdt->sys_ents[idx] = GDT::SystemEntry(
uintptr_t(tss[idx]), sizeof(TSS64_ENT) + 0x2000 - 1, uintptr_t(ent), uintptr_t(tsstop - entbuf) + 0x2000 - 1,
0x9, 0, 0, 1, 0, 1, 0, 0); 0x9, 0, 0, 1, 0, 1, 0, 0);
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
using PTE = Pagetable::Entry; using PTE = Pagetable::Entry;
Mutex Pagetable::page_mutex; Mutex Pagetable::page_mutex;
uintptr_t Pagetable::last_page = 1; uintptr_t Pagetable::last_page = 0x1000;
void *Pagetable::rsvd_pages[rsvd_num]; void *Pagetable::rsvd_pages[rsvd_num];
static uintptr_t max_page = 0xFFFFFFFFFFFFFllu; static uintptr_t max_page = 0xFFFFFFFFFFFFFllu;
static Mutex renewGuard; static Mutex renewGuard;
...@@ -176,7 +176,7 @@ void Pagetable::init() { ...@@ -176,7 +176,7 @@ void Pagetable::init() {
ent = reinterpret_cast<EFI::MemoryDescriptor*>(uintptr_t(ent) + entSize)) { ent = reinterpret_cast<EFI::MemoryDescriptor*>(uintptr_t(ent) + entSize)) {
max_page = klib::max(max_page, (ent->PhysicalStart >> 12) + ent->NumberOfPages); max_page = klib::max(max_page, (ent->PhysicalStart >> 12) + ent->NumberOfPages);
} }
ST->BootServices->FreePool(map); ST->BootServices->FreePool(map); map = nullptr;
uintptr_t ptbase = RAND::get<uintptr_t>(0x100, max_page) << 12; uintptr_t ptbase = RAND::get<uintptr_t>(0x100, max_page) << 12;
PTE *pagetable = static_cast<PTE*>(efiAllocatePage(ptbase, ST)); PTE *pagetable = static_cast<PTE*>(efiAllocatePage(ptbase, ST));
...@@ -189,6 +189,33 @@ void Pagetable::init() { ...@@ -189,6 +189,33 @@ void Pagetable::init() {
efiMapPage(pagetable, rsp, ST); efiMapPage(pagetable, rsp, ST);
efiMapPage(pagetable, rsp - 0x1000, ST); efiMapPage(pagetable, rsp - 0x1000, ST);
ST->BootServices->GetMemoryMap(&mapSize, map, &mapKey, &entSize, &entVer);
mapSize += 3 * entSize;
ST->BootServices->AllocatePool(EFI::MEMORY_TYPE_DATA, mapSize, reinterpret_cast<void**>(&map));
ST->BootServices->GetMemoryMap(&mapSize, map, &mapKey, &entSize, &entVer);
for (EFI::MemoryDescriptor *ent = map;
ent < reinterpret_cast<EFI::MemoryDescriptor*>(uintptr_t(map) + mapSize);
ent = reinterpret_cast<EFI::MemoryDescriptor*>(uintptr_t(ent) + entSize)) {
switch (ent->Type) {
case EFI::MEMORY_TYPE_BS_CODE:
case EFI::MEMORY_TYPE_BS_DATA:
case EFI::MEMORY_TYPE_RS_CODE:
case EFI::MEMORY_TYPE_RS_DATA:
case EFI::MEMORY_TYPE_RESERVED:
case EFI::MEMORY_TYPE_ACPI_RECLAIM:
case EFI::MEMORY_TYPE_ACPI_NVS:
case EFI::MEMORY_TYPE_MAPPED_IO:
case EFI::MEMORY_TYPE_MAPPED_IO_PORTSPACE:
fillPagesEfi(ent->PhysicalStart, ent->PhysicalStart + (ent->NumberOfPages << 12), pagetable, ST);
break;
default:
break;
}
}
ST->BootServices->FreePool(map);
const EFI::Framebuffer *fb = EFI::getFramebuffer(); const EFI::Framebuffer *fb = EFI::getFramebuffer();
if (fb && fb->base) { if (fb && fb->base) {
fillPagesEfi(fb->base, reinterpret_cast<char*>(fb->base) + fb->width * fb->height * 4, pagetable, ST); fillPagesEfi(fb->base, reinterpret_cast<char*>(fb->base) + fb->width * fb->height * 4, pagetable, ST);
...@@ -380,7 +407,7 @@ void Pagetable::_renewRsvd() { ...@@ -380,7 +407,7 @@ void Pagetable::_renewRsvd() {
if (!renewGuard.try_lock()) return; if (!renewGuard.try_lock()) return;
for (size_t i = 0; i < rsvd_num; i++) { for (size_t i = 0; i < rsvd_num; i++) {
if (rsvd_pages[i] != nullptr) continue; if (rsvd_pages[i] != nullptr) continue;
rsvd_pages[i] = _alloc(0, true); rsvd_pages[i] = _alloc(false, 1);
} }
renewGuard.release(); renewGuard.release();
} }
...@@ -416,29 +443,39 @@ void* Pagetable::map(const void* mem) { ...@@ -416,29 +443,39 @@ void* Pagetable::map(const void* mem) {
return _map(mem); return _map(mem);
} }
void* Pagetable::_alloc(uint8_t avl, bool nolow) { void* Pagetable::_alloc(bool low, size_t count) {
PTE *pagetable; asm volatile("mov %%cr3, %q0":"=r"(pagetable)); PTE *pagetable; asm volatile("mov %%cr3, %q0":"=r"(pagetable));
void *addr = nullptr; char *addr = nullptr;
PTE *page; uintptr_t i;
uintptr_t i = last_page - 1; i = low ? 1 : last_page;
if (nolow && (i < 0x100)) i = 0x100; while (1) {
while (i < max_page) { if (i + count >= max_page) return nullptr;
addr = reinterpret_cast<char*>(i << 12);
bool found = 1;
for (size_t ii = 0; ii < count; ii++) {
PTE *page = PTE::find(addr + (ii << 12), pagetable);
if (page && page->present) {
found = 0; break;
}
}
if (found) break;
i++; i++;
addr = reinterpret_cast<void*>(i << 12);
page = PTE::find(addr, pagetable);
if ((page == nullptr) || !page->present) break;
} }
if (!nolow) last_page = i; if (!low) last_page = i;
_map(addr); for (size_t i = 0; i < count; i++) _map(addr + (i << 12));
PTE::find(addr, pagetable)->avl = avl; Memory::fill(addr, 0, count * 0x1000);
Memory::fill(addr, 0, 0x1000);
return addr; return addr;
} }
void* Pagetable::alloc(uint8_t avl) { void* Pagetable::alloc(size_t count) {
Mutex::CriticalLock lock(page_mutex);
return _alloc(false, count);
}
void* Pagetable::lowalloc(size_t count) {
Mutex::CriticalLock lock(page_mutex); Mutex::CriticalLock lock(page_mutex);
return _alloc(avl); return _alloc(true, count);
} }
void Pagetable::free(void* page) { void Pagetable::free(void* page) {
...@@ -448,7 +485,7 @@ void Pagetable::free(void* page) { ...@@ -448,7 +485,7 @@ void Pagetable::free(void* page) {
if ((pdata != nullptr) && pdata->present) { if ((pdata != nullptr) && pdata->present) {
pdata->present = 0; pdata->present = 0;
void *addr = pdata->getPtr(); void *addr = pdata->getPtr();
if ((uintptr_t(addr) >> 12) < last_page) if ((uintptr_t(addr) >> 12) < last_page && (uintptr_t(addr) >> 12) >= 0x1000)
last_page = uintptr_t(addr) >> 12; last_page = uintptr_t(addr) >> 12;
} }
} }
...@@ -52,7 +52,7 @@ void SMP::init() { ...@@ -52,7 +52,7 @@ void SMP::init() {
char *startupCode; char *startupCode;
StartupInfo *info; StartupInfo *info;
startupCode = static_cast<char*>(Pagetable::alloc()); startupCode = static_cast<char*>(Pagetable::lowalloc());
info = reinterpret_cast<StartupInfo*>(startupCode + klib::__align(smp_init_size, 8)); info = reinterpret_cast<StartupInfo*>(startupCode + klib::__align(smp_init_size, 8));
Memory::copy(startupCode, smp_init, smp_init_size); Memory::copy(startupCode, smp_init, smp_init_size);
......
...@@ -301,8 +301,7 @@ void Process::startup() { ...@@ -301,8 +301,7 @@ void Process::startup() {
while (gdt_ent < gdt_top) { while (gdt_ent < gdt_top) {
uintptr_t base = gdt_ent->getBase(); uintptr_t base = gdt_ent->getBase();
size_t limit = gdt_ent->getLimit(); if ((gdt_ent->type != 0x9) && (gdt_ent->type != 0xB)) {
if (((gdt_ent->type != 0x9) && (gdt_ent->type != 0xB)) || (limit != sizeof(TSS64_ENT) + 0x2000 - 1)) {
gdt_ent++; gdt_ent++;
continue; continue;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment