...
 
Commits (4)
......@@ -5,7 +5,7 @@ add_custom_target(${EFIROOT}
DEPENDS pxkrnl
)
set(QEMU_FLAGS -smp cores=2,threads=2 -cpu Nehalem-IBRS -serial stdio)
set(QEMU_FLAGS -smp cores=2,threads=2 -machine pc-q35-2.10 -cpu Nehalem-IBRS -serial stdio)
add_custom_target(launch
${QEMU} ${QEMU_FLAGS} -kernel pxkrnl
DEPENDS pxkrnl
......
......@@ -100,10 +100,9 @@ class FramebufferDisplay: public Display {
uint8_t *line = fbptr + y * width * pb;
uint8_t fontline = fontsym[y];
for (size_t x = 0; x < 8; x++) {
if (fontline & (1 << (8 - x))) {
for (size_t px = 0; px < pb; px++)
line[x * pb + px] = 0xFF;
}
uint8_t val = (fontline & (1 << (8 - x))) ? 0xFF : 0x00;
for (size_t px = 0; px < pb; px++)
line[x * pb + px] = val;
}
}
......
......@@ -20,6 +20,9 @@ class List {
}
return items[count++];
}
void remove(size_t idx) {
Memory::copy(items + idx, items + idx + 1, sizeof(Item) * ((--count) - idx));
}
void add(const Item &item) { insert() = item; }
......
......@@ -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);
......
......@@ -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);
};
......
......@@ -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;
......@@ -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);
}
......
......@@ -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<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));
......@@ -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);
......@@ -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<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) {
......@@ -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;
}
}
......@@ -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);
......
......@@ -29,7 +29,8 @@ class ProcessManager {
static bool FaultHandler(uint8_t intr, uint32_t code, Interrupts::CallbackRegs *regs);
public:
uint64_t RegisterProcess(Process *process);
uint64_t registerProcess(Process *process);
void exitProcess(Process *process, int code);
void queueThread(Process *process, Thread *thread);
void dequeueThread(Thread *thread);
Process *currentProcess();
......
......@@ -77,26 +77,22 @@ PTE* Process::addPage(uintptr_t vaddr, void* paddr, uint8_t flags) {
pagetable = static_cast<PTE*>(Pagetable::alloc());
addPage(uintptr_t(pagetable), pagetable, 5);
}
PTE pte = pagetable[ptx];
if (!pte.present) {
pagetable[ptx] = pte = PTE(Pagetable::alloc(), 7);
addPage(pte.getUintPtr(), pte.getPtr(), 5);
if (!pagetable[ptx].present) {
pagetable[ptx] = PTE(Pagetable::alloc(), 7);
addPage(pagetable[ptx].getUintPtr(), pagetable[ptx].getPtr(), 5);
}
PTE *pde = pte.getPTE();
pte = pde[pdx];
if (!pte.present) {
pde[pdx] = pte = PTE(Pagetable::alloc(), 7);
addPage(pte.getUintPtr(), pte.getPtr(), 5);
PTE *pde = pagetable[ptx].getPTE();
if (!pde[pdx].present) {
pde[pdx] = PTE(Pagetable::alloc(), 7);
addPage(pde[pdx].getUintPtr(), pde[pdx].getPtr(), 5);
}
PTE *pdpe = pte.getPTE();
pte = pdpe[pdpx];
if (!pte.present) {
pdpe[pdpx] = pte = PTE(Pagetable::alloc(), 7);
addPage(pte.getUintPtr(), pte.getPtr(), 5);
PTE *pdpe = pde[pdx].getPTE();
if (!pdpe[pdpx].present) {
pdpe[pdpx] = PTE(Pagetable::alloc(), 7);
addPage(pdpe[pdpx].getUintPtr(), pdpe[pdpx].getPtr(), 5);
}
PTE *pml4e = pte.getPTE();
flags |= 1;
pml4e[pml4x] = PTE(paddr, flags);
PTE *pml4e = pdpe[pdpx].getPTE();
pml4e[pml4x] = PTE(paddr, flags | 1);
return &pml4e[pml4x];
}
......@@ -305,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;
}
......@@ -329,7 +324,7 @@ void Process::startup() {
Thread *thread = new Thread();
thread->regs.rip = entry;
thread->regs.rflags = 0;
id = (ProcessManager::getManager())->RegisterProcess(this);
id = (ProcessManager::getManager())->registerProcess(this);
addThread(thread, false);
}
......@@ -338,6 +333,7 @@ void Process::exit(int code) {
for (size_t i = 0; i < threads.getCount(); i++) {
ProcessManager::getManager()->dequeueThread(threads[i]);
}
ProcessManager::getManager()->exitProcess(this, code);
delete this;
}
......
......@@ -104,7 +104,7 @@ bool ProcessManager::HandleFault(uint8_t intr, uint32_t code, Interrupts::Callba
return true;
}
uint64_t ProcessManager::RegisterProcess(Process *process) {
uint64_t ProcessManager::registerProcess(Process *process) {
Mutex::CriticalLock lock(processSwitchMutex);
uint64_t pid = 1;
for (size_t i = 0; i < processes.getCount(); i++) {
......@@ -114,6 +114,14 @@ uint64_t ProcessManager::RegisterProcess(Process *process) {
return pid;
}
void ProcessManager::exitProcess(Process *process, int code) {
(void)code; // TODO: handle
Mutex::CriticalLock lock(processSwitchMutex);
for (size_t i = processes.getCount(); i > 0; i--) {
if (processes[i-1] == process) processes.remove(i-1);
}
}
void ProcessManager::queueThread(Process *process, Thread *thread) {
QueuedThread *q = new QueuedThread();
q->process = process;
......