Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Rewrite pagetable allocation
  • Loading branch information
djphoenix committed May 27, 2019
1 parent 37a1ebf commit 445d0f7
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 45 deletions.
1 change: 0 additions & 1 deletion src/platform/include/interrupts.hpp
Expand Up @@ -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);

Expand Down
5 changes: 3 additions & 2 deletions src/platform/include/pagetable.hpp
Expand Up @@ -64,15 +64,16 @@ 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();
static void init();

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);
};

Expand Down
39 changes: 19 additions & 20 deletions src/platform/interrupts.cpp
Expand Up @@ -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::Callback*> *Interrupts::callbacks = nullptr;
Mutex Interrupts::callback_locks[256];
Mutex Interrupts::fault;
Expand Down Expand Up @@ -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<GDT*>(
Pagetable::lowalloc((GDT::size(ncpu) + 0xFFF) / 0x1000));
idt = reinterpret_cast<REC64*>(
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[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<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++) {
void *stack = Pagetable::alloc();
uintptr_t stack_ptr = uintptr_t(stack) + 0x1000;
char *entbuf = reinterpret_cast<char*>(Heap::alloc(0x3000, 0x1000));
TSS64_ENT *ent = tss[idx] = reinterpret_cast<TSS64_ENT*>(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<TSS64_ENT*>(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);
}

Expand Down
75 changes: 56 additions & 19 deletions src/platform/pagetable.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -176,7 +176,7 @@ void Pagetable::init() {
ent = reinterpret_cast<EFI::MemoryDescriptor*>(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<uintptr_t>(0x100, max_page) << 12;
PTE *pagetable = static_cast<PTE*>(efiAllocatePage(ptbase, ST));
Expand All @@ -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<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();
if (fb && fb->base) {
fillPagesEfi(fb->base, reinterpret_cast<char*>(fb->base) + fb->width * fb->height * 4, pagetable, ST);
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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<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++;
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);
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) {
Expand All @@ -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;
}
}
2 changes: 1 addition & 1 deletion src/platform/smp.cpp
Expand Up @@ -52,7 +52,7 @@ void SMP::init() {
char *startupCode;
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));

Memory::copy(startupCode, smp_init, smp_init_size);
Expand Down
3 changes: 1 addition & 2 deletions src/process/process.cpp
Expand Up @@ -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;
}
Expand Down

0 comments on commit 445d0f7

Please sign in to comment.