diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index 48dd737337fa04..cc6185ca3f49e8 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -68,9 +68,9 @@ auto MemoryManager::ensurePTE(LinearAddress linearAddress) -> PageTableEntry pde.setWritable(true); } else if (pageDirectoryIndex == 1) { pde.setPageTableBase((dword)m_pageTableOne); - pde.setUserAllowed(false); + pde.setUserAllowed(true); pde.setPresent(true); - pde.setWritable(false); + pde.setWritable(true); } else { // FIXME: We need an allocator! ASSERT_NOT_REACHED(); @@ -120,7 +120,6 @@ RetainPtr MemoryManager::createZone(size_t size) Vector MemoryManager::allocatePhysicalPages(size_t count) { - kprintf("MM: alloc %u pages from %u available\n", count, m_freePages.size()); if (count > m_freePages.size()) return { }; @@ -128,7 +127,6 @@ Vector MemoryManager::allocatePhysicalPages(size_t count) pages.ensureCapacity(count); for (size_t i = 0; i < count; ++i) pages.append(m_freePages.takeLast()); - kprintf("MM: returning the pages (%u of them)\n", pages.size()); return pages; } @@ -142,19 +140,24 @@ byte* MemoryManager::quickMapOnePage(PhysicalAddress physicalAddress) return (byte*)(4 * MB); } -bool MemoryManager::unmapZonesForTask(Task& task) +bool MemoryManager::unmapRegionsForTask(Task& task) { return true; } -bool MemoryManager::mapZonesForTask(Task& task) +bool MemoryManager::mapRegionsForTask(Task& task) { - for (auto& mappedZone : task.m_mappedZones) { - auto& zone = *mappedZone.zone; + for (auto& region : task.m_regions) { + auto& zone = *region->zone; for (size_t i = 0; i < zone.m_pages.size(); ++i) { - auto pte = ensurePTE(mappedZone.linearAddress.offset(i * PAGE_SIZE)); + auto laddr = region->linearAddress.offset(i * PAGE_SIZE); + auto pte = ensurePTE(laddr); pte.setPhysicalPageBase(zone.m_pages[i].get()); pte.setPresent(true); + pte.setWritable(true); + pte.setUserAllowed(!task.isRing0()); + + kprintf("MM: >> Mapped L%x => P%x <<\n", laddr, zone.m_pages[i].get()); } } return true; diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index fe23d14e96d17e..048834a21c0904 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -49,8 +49,8 @@ class MemoryManager { // HACK: don't use this jeez :( byte* quickMapOnePage(PhysicalAddress); - bool mapZonesForTask(Task&); - bool unmapZonesForTask(Task&); + bool mapRegionsForTask(Task&); + bool unmapRegionsForTask(Task&); private: MemoryManager(); diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 34e58ab52addb8..2c69ad929f1842 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -74,7 +74,7 @@ void Task::allocateLDT() static const WORD numLDTEntries = 4; WORD newLDTSelector = allocateGDTEntry(); m_ldtEntries = new Descriptor[numLDTEntries]; -#if 1 +#if 0 kprintf("new ldt selector = %x\n", newLDTSelector); kprintf("new ldt table at = %p\n", m_ldtEntries); kprintf("new ldt table size = %u\n", (numLDTEntries * 8) - 1); @@ -92,12 +92,15 @@ void Task::allocateLDT() m_tss.ldt = newLDTSelector; } -bool Task::mapZone(LinearAddress address, RetainPtr&& zone) +Task::Region* Task::allocateRegion(size_t size, String&& name) { - // FIXME: This needs sanity checks. What if this overlaps existing zones? - kprintf("mapped zone with size %u at %x\n", zone->size(), address.get()); - m_mappedZones.append({ address, move(zone) }); - return true; + // FIXME: This needs sanity checks. What if this overlaps existing regions? + + auto zone = MemoryManager::the().createZone(PAGE_SIZE); + ASSERT(zone); + m_regions.append(make(m_nextRegion, size, move(zone), move(name))); + m_nextRegion = m_nextRegion.offset(size).offset(16384); + return m_regions.last().ptr(); } Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring) @@ -108,16 +111,13 @@ Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring) , m_state(Runnable) , m_ring(ring) { - if (!isRing0()) { - auto zone = MemoryManager::the().createZone(PAGE_SIZE); - ASSERT(zone); - - kprintf("New task zone: { size: %u }\n", zone->size()); - - bool success = mapZone(LinearAddress(0x300000), zone.copyRef()); - ASSERT(success); + m_nextRegion = LinearAddress(0x600000); - success = copyToZone(*zone, (void*)e, PAGE_SIZE); + Region* codeRegion = nullptr; + if (!isRing0()) { + codeRegion = allocateRegion(4096, "code"); + ASSERT(codeRegion); + bool success = copyToZone(*codeRegion->zone, (void*)e, PAGE_SIZE); ASSERT(success); } @@ -157,22 +157,31 @@ Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring) if (isRing0()) { m_tss.eip = (DWORD)m_entry; } else { - m_tss.eip = m_mappedZones[0].linearAddress.get(); + m_tss.eip = codeRegion->linearAddress.get(); } kprintf("basically ready\n"); // NOTE: Each task gets 4KB of stack. - // This memory is leaked ATM. - // But uh, there's also no process termination, so I guess it's not technically leaked... static const DWORD defaultStackSize = 4096; - m_stackTop = ((DWORD)kmalloc(defaultStackSize) + defaultStackSize) & 0xffffff8; - m_tss.esp = m_stackTop; + + if (isRing0()) { + // FIXME: This memory is leaked. + // But uh, there's also no kernel task termination, so I guess it's not technically leaked... + m_stackTop = ((DWORD)kmalloc(defaultStackSize) + defaultStackSize) & 0xffffff8; + m_tss.esp = m_stackTop; + } else { + auto* region = allocateRegion(defaultStackSize, "stack"); + ASSERT(region); + m_stackTop = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8; + m_tss.esp = m_stackTop; + } if (ring == Ring3) { // Set up a separate stack for Ring0. // FIXME: Don't leak this stack either. - DWORD ring0StackTop = ((DWORD)kmalloc(defaultStackSize) + defaultStackSize) & 0xffffff8; + m_kernelStack = kmalloc(defaultStackSize); + DWORD ring0StackTop = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8; m_tss.ss0 = 0x10; m_tss.esp0 = ring0StackTop; } @@ -200,11 +209,36 @@ Task::~Task() system.nprocess--; delete [] m_ldtEntries; m_ldtEntries = nullptr; + + // FIXME: The task's kernel stack is currently leaked, because otherwise we GPF. + // This obviously needs figuring out. +#if 0 + if (m_kernelStack) { + kfree(m_kernelStack); + m_kernelStack = nullptr; + } +#endif +} + +void Task::dumpRegions() +{ + kprintf("Task %s(%u) regions:\n", name().characters(), pid()); + kprintf("BEGIN END SIZE NAME\n"); + for (auto& region : m_regions) { + kprintf("%x -- %x %x %s\n", + region->linearAddress.get(), + region->linearAddress.offset(region->size - 1).get(), + region->size, + region->name.characters()); + } } void Task::taskDidCrash(Task* crashedTask) { crashedTask->setState(Crashing); + + crashedTask->dumpRegions(); + s_tasks->remove(crashedTask); if (!scheduleNewTask()) { @@ -327,9 +361,9 @@ static bool contextSwitch(Task* t) if (current->state() == Task::Running) current->setState(Task::Runnable); - bool success = MemoryManager::the().unmapZonesForTask(*current); + bool success = MemoryManager::the().unmapRegionsForTask(*current); ASSERT(success); - success = MemoryManager::the().mapZonesForTask(*t); + success = MemoryManager::the().mapRegionsForTask(*t); ASSERT(success); current = t; @@ -523,3 +557,15 @@ void Task::setError(int error) { m_error = error; } + +Task::Region::Region(LinearAddress a, size_t s, RetainPtr&& z, String&& n) + : linearAddress(a) + , size(s) + , zone(move(z)) + , name(move(n)) +{ +} + +Task::Region::~Region() +{ +} diff --git a/Kernel/Task.h b/Kernel/Task.h index 347bafb2ca8859..c3d55e36214b98 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -97,10 +97,11 @@ class Task : public InlineLinkedListNode { static void taskDidCrash(Task*); + void dumpRegions(); + private: friend class MemoryManager; - bool mapZone(LinearAddress, RetainPtr&&); FileHandle* openFile(String&&); void allocateLDT(); @@ -124,13 +125,22 @@ class Task : public InlineLinkedListNode { Vector> m_fileHandles; RingLevel m_ring { Ring0 }; int m_error { 0 }; + void* m_kernelStack { nullptr }; - struct MappedZone { + struct Region { + Region(LinearAddress, size_t, RetainPtr&&, String&&); + ~Region(); LinearAddress linearAddress; + size_t size { 0 }; RetainPtr zone; + String name; }; + Region* allocateRegion(size_t, String&& name); + + Vector> m_regions; - Vector m_mappedZones; + // FIXME: Implement some kind of ASLR? + LinearAddress m_nextRegion; }; extern void task_init(); diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index 1406df5a96ec60..99db7cd24efcbb 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -73,12 +73,22 @@ EH_ENTRY(13); void exception_13_handler() { auto& regs = *reinterpret_cast(exception_state_dump); - kprintf("Process crash: %u(%s)\n", current->pid(), current->name().characters()); + kprintf("%s crash: %u(%s)\n", current->isRing0() ? "Kernel" : "Process", current->pid(), current->name().characters()); + + word ss; + dword esp; + if (current->isRing0()) { + ss = regs.ds; + esp = regs.esp; + } else { + ss = regs.ss_if_crossRing; + esp = regs.esp_if_crossRing; + } kprintf("exception code: %w\n", exception_code); kprintf("pc=%w:%x ds=%w es=%w fs=%w gs=%w\n", regs.cs, regs.eip, regs.ds, regs.es, regs.fs, regs.gs); kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx); - kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, regs.esp, regs.esi, regs.edi); + kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, esp, regs.esi, regs.edi); if (current->isRing0()) { kprintf("Oh shit, we've crashed in ring 0 :(\n"); @@ -104,10 +114,20 @@ void exception_14_handler() exception_code & 2 ? "write" : "read", faultAddress); + word ss; + dword esp; + if (current->isRing0()) { + ss = regs.ds; + esp = regs.esp; + } else { + ss = regs.ss_if_crossRing; + esp = regs.esp_if_crossRing; + } + kprintf("exception code: %w\n", exception_code); kprintf("pc=%w:%x ds=%w es=%w fs=%w gs=%w\n", regs.cs, regs.eip, regs.ds, regs.es, regs.fs, regs.gs); kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx); - kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, regs.esp, regs.esi, regs.edi); + kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, esp, regs.esi, regs.edi); if (current->isRing0()) HANG; diff --git a/Kernel/i386.h b/Kernel/i386.h index b15b8b6069161a..73c23e5fbfbf8e 100644 --- a/Kernel/i386.h +++ b/Kernel/i386.h @@ -131,6 +131,8 @@ struct RegisterDump { WORD cs; WORD __csPadding; DWORD eflags; + DWORD esp_if_crossRing; + WORD ss_if_crossRing; } PACKED; inline constexpr dword pageBaseOf(dword address) diff --git a/Kernel/init.cpp b/Kernel/init.cpp index fa91a36763cd4b..70e4ad24260e7e 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -76,6 +76,14 @@ static void user_main() } } +static void user_kprintf_main() NORETURN; +static void user_kprintf_main() +{ + DO_SYSCALL_A1(0x4000, 0); + kprintf("This should not work!\n"); + HANG; +} + system_t system; void banner() @@ -155,10 +163,11 @@ void init() //new Task(motd_main, "motd", IPC::Handle::MotdTask, Task::Ring0); new Task(user_main, "user", IPC::Handle::UserTask, Task::Ring3); + new Task(user_kprintf_main, "user_kprintf", IPC::Handle::UserTask, Task::Ring3); //vfs->listDirectory("/"); -#if 0 +#if 1 { auto motdFile = vfs->open("/motd.txt"); ASSERT(motdFile);