diff --git a/Core/Crash/CrashHandler.cpp b/Core/Crash/CrashHandler.cpp index ba0b186..9e9d9da 100644 --- a/Core/Crash/CrashHandler.cpp +++ b/Core/Crash/CrashHandler.cpp @@ -2,6 +2,7 @@ #include "chfcts.hpp" #include +#include #include #include #include @@ -20,6 +21,22 @@ NewLock(UserInputLock); +#define TRACE_PAGE_TABLE(x, itr, depth) \ + EHPrint("\e888888#%s\eAABBCC%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PS:%s G:%s Address:\e888888%#lx\n", \ + depth, \ + itr, \ + x.Value.Present ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ + x.Value.ReadWrite ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ + x.Value.UserSupervisor ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ + x.Value.WriteThrough ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ + x.Value.CacheDisable ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ + x.Value.Accessed ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ + x.Value.Dirty ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ + x.Value.PageSize ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ + x.Value.Global ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ + x.GetAddress() << 12); \ + Display->SetBuffer(SBIdx); + namespace CrashHandler { void *EHIntFrames[INT_FRAMES_MAX]; @@ -211,6 +228,8 @@ namespace CrashHandler EHPrint(" - A sleep timer will be enabled. This will cause the OS to sleep for an unknown amount of time.\n"); EHPrint(" - \eFF4400WARNING: This can crash the system if a wrong buffer is selected.\eFAFAFA\n"); EHPrint("ifr - Show interrupt frames.\n"); + EHPrint("tlb
- Print the page table entries\n"); + EHPrint("bitmap - Print the memory bitmap\n"); EHPrint("main - Show the main screen.\n"); EHPrint("details - Show the details screen.\n"); EHPrint("frames - Show the stack frame screen.\n"); @@ -285,6 +304,83 @@ namespace CrashHandler } } } + else if (strncmp(Input, "tlb", 3) == 0) + { + char *arg = TrimWhiteSpace(Input + 3); + uint64_t Address = NULL; + Address = strtol(arg, NULL, 16); + debug("Converted %s to %#lx", arg, Address); + Memory::PageTable *BasePageTable = (Memory::PageTable *)Address; + if (Memory::Virtual().Check(BasePageTable)) + for (int Index = 0; Index < 512; Index++) + { + if (BasePageTable->Entries[Index].Value.raw == 0) + continue; + + TRACE_PAGE_TABLE(BasePageTable->Entries[Index], Index, ""); + for (int i = 0; i < 10000; i++) + inb(0x80); + + if (BasePageTable->Entries[Index].GetFlag(Memory::PTFlag::P)) + { + Memory::PageTable *PDP = (Memory::PageTable *)((uint64_t)BasePageTable->Entries[Index].GetAddress() << 12); + for (int PDPIndex = 0; PDPIndex < 512; PDPIndex++) + { + if (PDP->Entries[PDPIndex].Value.raw == 0) + continue; + TRACE_PAGE_TABLE(PDP->Entries[PDPIndex], PDPIndex, " "); + for (int i = 0; i < 10000; i++) + inb(0x80); + + if (PDP->Entries[PDPIndex].GetFlag(Memory::PTFlag::P)) + { + Memory::PageTable *PD = (Memory::PageTable *)((uint64_t)PDP->Entries[PDPIndex].GetAddress() << 12); + for (int PDIndex = 0; PDIndex < 512; PDIndex++) + { + if (PD->Entries[PDIndex].Value.raw == 0) + continue; + TRACE_PAGE_TABLE(PD->Entries[PDIndex], PDIndex, " "); + for (int i = 0; i < 10000; i++) + inb(0x80); + + if (PD->Entries[PDIndex].GetFlag(Memory::PTFlag::P)) + { + Memory::PageTable *PT = (Memory::PageTable *)((uint64_t)PD->Entries[PDIndex].GetAddress() << 12); + for (int PIndex = 0; PIndex < 512; PIndex++) + { + if (PT->Entries[PIndex].Value.raw == 0) + continue; + TRACE_PAGE_TABLE(PT->Entries[PIndex], PIndex, " "); + for (int i = 0; i < 10000; i++) + inb(0x80); + } + } + } + } + } + } + } + } + else if (strncmp(Input, "bitmap", 6) == 0) + { + Bitmap bm = KernelAllocator.GetPageBitmap(); + + EHPrint("\n\eFAFAFA%08ld: ", 0); + for (uint64_t i = 0; i < bm.Size; i++) + { + if (bm.Get(i)) + EHPrint("\eFF00001"); + else + EHPrint("\e00FF000"); + if (i % 128 == 127) + { + EHPrint("\n\eFAFAFA%08ld: ", i); + Display->SetBuffer(SBIdx); + } + } + EHPrint("\n\e22AA44--- END OF BITMAP ---\nBitmap size: %ld\n", bm.Size); + Display->SetBuffer(SBIdx); + } else if (strcmp(Input, "main") == 0) { SBIdx = 255; diff --git a/Core/Crash/UserHandler.cpp b/Core/Crash/UserHandler.cpp index b117868..0160f12 100644 --- a/Core/Crash/UserHandler.cpp +++ b/Core/Crash/UserHandler.cpp @@ -15,7 +15,7 @@ #include "../../kernel.h" -static const char *PagefaultDescriptions[8] = { +static const char *PageFaultDescriptions[8] = { "Supervisory process tried to read a non-present page entry\n", "Supervisory process tried to read a page and caused a protection fault\n", "Supervisory process tried to write to a non-present page entry\n", @@ -177,14 +177,6 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) } case CPU::x64::PageFault: { - if (CurCPU) - if (CurCPU->CurrentThread->Stack->Expand(CPU::x64::readcr2().raw)) - { - debug("Stack expanded"); - TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready; - return; - } - CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode}; #if defined(__amd64__) error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->rip); @@ -203,7 +195,48 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame) if (Frame->ErrorCode & 0x00000008) error("One or more page directory entries contain reserved bits which are set to 1."); else - error(PagefaultDescriptions[Frame->ErrorCode & 0b111]); + error(PageFaultDescriptions[Frame->ErrorCode & 0b111]); + +#ifdef DEBUG + if (CurCPU) + { + Memory::Virtual vma = Memory::Virtual(CurCPU->CurrentProcess->PageTable); + bool PageAvailable = vma.Check((void *)CPU::x64::readcr2().PFLA); + debug("Page available (Check(...)): %s. %s", + PageAvailable ? "Yes" : "No", + (params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result."); + + if (PageAvailable) + { + bool Present = vma.Check((void *)CPU::x64::readcr2().PFLA); + bool ReadWrite = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::RW); + bool User = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::US); + bool WriteThrough = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PWT); + bool CacheDisabled = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PCD); + bool Accessed = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::A); + bool Dirty = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::D); + bool Global = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::G); + /* ... */ + + debug("Page available: %s", Present ? "Yes" : "No"); + debug("Page read/write: %s", ReadWrite ? "Yes" : "No"); + debug("Page user/kernel: %s", User ? "User" : "Kernel"); + debug("Page write-through: %s", WriteThrough ? "Yes" : "No"); + debug("Page cache disabled: %s", CacheDisabled ? "Yes" : "No"); + debug("Page accessed: %s", Accessed ? "Yes" : "No"); + debug("Page dirty: %s", Dirty ? "Yes" : "No"); + debug("Page global: %s", Global ? "Yes" : "No"); + } + } +#endif + + if (CurCPU) + if (CurCPU->CurrentThread->Stack->Expand(CPU::x64::readcr2().raw)) + { + debug("Stack expanded"); + TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready; + return; + } break; } case CPU::x64::x87FloatingPoint: diff --git a/KThread.cpp b/KThread.cpp index b0c0cb5..658bddf 100644 --- a/KThread.cpp +++ b/KThread.cpp @@ -18,9 +18,8 @@ void KernelMainThread() { TaskManager->InitIPC(); TaskManager->GetCurrentThread()->SetPriority(100); - Vector auxv; + CPU::Interrupts(CPU::Disable); - Tasking::TCB *CurrentWorker = nullptr; KPrint("Kernel Compiled at: %s %s with C++ Standard: %d", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD); KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus); @@ -56,22 +55,16 @@ void KernelMainThread() "--critical", nullptr}; - bool ien = CPU::Interrupts(CPU::Check); - CPU::Interrupts(CPU::Disable); Execute::SpawnData ret = Execute::Spawn(Config.InitPath, argv, envp); if (ret.Status != Execute::ExStatus::OK) { KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, ret.Status); - if (ien) - CPU::Interrupts(CPU::Enable); + CPU::Interrupts(CPU::Enable); goto Exit; } ret.Thread->SetCritical(true); - debug("%s interrupts", ien ? "Enabling" : "Disabling"); - if (ien) - CPU::Interrupts(CPU::Enable); - debug("After interrupts boolean"); KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath); + CPU::Interrupts(CPU::Enable); TaskManager->GetCurrentThread()->SetPriority(1); TaskManager->WaitForThread(ret.Thread); KPrint("\eE85230Userspace process exited with code %d", ret.Thread->GetExitCode());