diff --git a/src/platform/include/interrupts.hpp b/src/platform/include/interrupts.hpp index 4ac182c..88fe03f 100644 --- a/src/platform/include/interrupts.hpp +++ b/src/platform/include/interrupts.hpp @@ -151,7 +151,6 @@ class Interrupts { static Handler* handlers; static REC64 *idt; static GDT *gdt; - static TSS64_ENT **tss; static void init(); static uint64_t handle(uint8_t intr, uint64_t stack, uint64_t *cr3); diff --git a/src/platform/include/pagetable.hpp b/src/platform/include/pagetable.hpp index 7e56fa9..66c3580 100644 --- a/src/platform/include/pagetable.hpp +++ b/src/platform/include/pagetable.hpp @@ -64,7 +64,7 @@ class Pagetable { static void* rsvd_pages[rsvd_num]; static Mutex page_mutex; 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* _getRsvd(); static void _renewRsvd(); @@ -72,7 +72,8 @@ class Pagetable { public: 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); }; diff --git a/src/platform/interrupts.cpp b/src/platform/interrupts.cpp index 7da4534..5c1a287 100644 --- a/src/platform/interrupts.cpp +++ b/src/platform/interrupts.cpp @@ -9,24 +9,16 @@ struct Interrupts::Handler { // 68 04 03 02 01 pushq ${int_num} // e9 46 ec 3f 00 jmp . + {diff} - uint8_t push; // == 0x68 + uint8_t push[1] = { 0x68 }; uint32_t int_num; - uint8_t reljmp; // == 0xE9 + uint8_t reljmp[1] = { 0xE9 }; uint32_t diff; - Handler(): - 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) + Handler(uint32_t int_num, uint32_t diff): int_num(int_num), diff(diff) {} } PACKED; Interrupts::REC64 *Interrupts::idt = nullptr; GDT *Interrupts::gdt = nullptr; -TSS64_ENT **Interrupts::tss = nullptr; List *Interrupts::callbacks = nullptr; Mutex Interrupts::callback_locks[256]; Mutex Interrupts::fault; @@ -295,27 +287,34 @@ uint64_t __attribute__((sysv_abi)) Interrupts::handle( void Interrupts::init() { uint64_t ncpu = ACPI::getController()->getCPUCount(); - gdt = new(GDT::size(ncpu)) GDT(); - tss = new TSS64_ENT*[ncpu](); - idt = new REC64[256](); - handlers = new Handler[256](); + gdt = reinterpret_cast( + Pagetable::lowalloc((GDT::size(ncpu) + 0xFFF) / 0x1000)); + idt = reinterpret_cast( + Pagetable::alloc((sizeof(REC64) * 256 + 0xFFF) / 0x1000)); + handlers = reinterpret_cast( + Pagetable::alloc((sizeof(Handler) * 256 + 0xFFF) / 0x1000)); gdt->ents[0] = GDT::Entry(); 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[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); + + size_t tss_size = sizeof(TSS64_ENT) * ncpu; + size_t tss_size_pad = klib::__align(tss_size, 0x1000); + char *tssbuf = reinterpret_cast(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++) { void *stack = Pagetable::alloc(); uintptr_t stack_ptr = uintptr_t(stack) + 0x1000; - char *entbuf = reinterpret_cast(Heap::alloc(0x3000, 0x1000)); - TSS64_ENT *ent = tss[idx] = reinterpret_cast(entbuf + (0x1000 - sizeof(TSS64_ENT))); - Memory::zero(tss[idx], sizeof(TSS64_ENT) + 0x2000); + char *entbuf = tssbuf + sizeof(TSS64_ENT) * idx; + TSS64_ENT *ent = reinterpret_cast(entbuf); ent->ist[0] = stack_ptr; - ent->iomap_base = sizeof(TSS64_ENT); + ent->iomap_base = uint16_t(tsstop - entbuf); 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); } diff --git a/src/platform/pagetable.cpp b/src/platform/pagetable.cpp index 3812f85..c3a03ed 100644 --- a/src/platform/pagetable.cpp +++ b/src/platform/pagetable.cpp @@ -9,7 +9,7 @@ using PTE = Pagetable::Entry; Mutex Pagetable::page_mutex; -uintptr_t Pagetable::last_page = 1; +uintptr_t Pagetable::last_page = 0x1000; void *Pagetable::rsvd_pages[rsvd_num]; static uintptr_t max_page = 0xFFFFFFFFFFFFFllu; static Mutex renewGuard; @@ -176,7 +176,7 @@ void Pagetable::init() { ent = reinterpret_cast(uintptr_t(ent) + entSize)) { 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(0x100, max_page) << 12; PTE *pagetable = static_cast(efiAllocatePage(ptbase, ST)); @@ -189,6 +189,33 @@ void Pagetable::init() { efiMapPage(pagetable, rsp, 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(&map)); + ST->BootServices->GetMemoryMap(&mapSize, map, &mapKey, &entSize, &entVer); + + for (EFI::MemoryDescriptor *ent = map; + ent < reinterpret_cast(uintptr_t(map) + mapSize); + ent = reinterpret_cast(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(); if (fb && fb->base) { fillPagesEfi(fb->base, reinterpret_cast(fb->base) + fb->width * fb->height * 4, pagetable, ST); @@ -380,7 +407,7 @@ void Pagetable::_renewRsvd() { if (!renewGuard.try_lock()) return; for (size_t i = 0; i < rsvd_num; i++) { if (rsvd_pages[i] != nullptr) continue; - rsvd_pages[i] = _alloc(0, true); + rsvd_pages[i] = _alloc(false, 1); } renewGuard.release(); } @@ -416,29 +443,39 @@ void* Pagetable::map(const void* 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)); - void *addr = nullptr; - PTE *page; - uintptr_t i = last_page - 1; - if (nolow && (i < 0x100)) i = 0x100; - while (i < max_page) { + char *addr = nullptr; + uintptr_t i; + i = low ? 1 : last_page; + while (1) { + if (i + count >= max_page) return nullptr; + addr = reinterpret_cast(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++; - addr = reinterpret_cast(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); - PTE::find(addr, pagetable)->avl = avl; - Memory::fill(addr, 0, 0x1000); + for (size_t i = 0; i < count; i++) _map(addr + (i << 12)); + Memory::fill(addr, 0, count * 0x1000); 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); - return _alloc(avl); + return _alloc(true, count); } void Pagetable::free(void* page) { @@ -448,7 +485,7 @@ void Pagetable::free(void* page) { if ((pdata != nullptr) && pdata->present) { pdata->present = 0; 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; } } diff --git a/src/platform/smp.cpp b/src/platform/smp.cpp index 006c64e..39030bb 100644 --- a/src/platform/smp.cpp +++ b/src/platform/smp.cpp @@ -52,7 +52,7 @@ void SMP::init() { char *startupCode; StartupInfo *info; - startupCode = static_cast(Pagetable::alloc()); + startupCode = static_cast(Pagetable::lowalloc()); info = reinterpret_cast(startupCode + klib::__align(smp_init_size, 8)); Memory::copy(startupCode, smp_init, smp_init_size); diff --git a/src/process/process.cpp b/src/process/process.cpp index 099971b..240558f 100644 --- a/src/process/process.cpp +++ b/src/process/process.cpp @@ -301,8 +301,7 @@ void Process::startup() { while (gdt_ent < gdt_top) { uintptr_t base = gdt_ent->getBase(); - size_t limit = gdt_ent->getLimit(); - if (((gdt_ent->type != 0x9) && (gdt_ent->type != 0xB)) || (limit != sizeof(TSS64_ENT) + 0x2000 - 1)) { + if ((gdt_ent->type != 0x9) && (gdt_ent->type != 0xB)) { gdt_ent++; continue; }