diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index a12bf28093..beca4e6ca7 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -17,7 +17,7 @@ MemoryManager& MM MemoryManager::MemoryManager() { - m_kernel_page_directory = (dword*)0x5000; + m_kernel_page_directory = (PageDirectory*)0x4000; m_pageTableZero = (dword*)0x6000; m_pageTableOne = (dword*)0x7000; @@ -32,10 +32,19 @@ MemoryManager::~MemoryManager() void MemoryManager::populate_page_directory(Process& process) { - memset(process.m_pageDirectory, 0, 4096); + memset(process.m_page_directory, 0, sizeof(PageDirectory)); + process.m_page_directory[0] = m_kernel_page_directory[0]; + process.m_page_directory[1] = m_kernel_page_directory[1]; +} - process.m_pageDirectory[0] = m_kernel_page_directory[0]; - process.m_pageDirectory[1] = m_kernel_page_directory[1]; +void MemoryManager::release_page_directory(Process& process) +{ + ASSERT_INTERRUPTS_DISABLED(); + for (size_t i = 0; i < 1024; ++i) { + auto paddr = process.m_page_directory->physical_addresses[i]; + if (!paddr.is_null()) + m_freePages.append(paddr); + } } void MemoryManager::initializePaging() @@ -44,7 +53,7 @@ void MemoryManager::initializePaging() static_assert(sizeof(MemoryManager::PageTableEntry) == 4); memset(m_pageTableZero, 0, 4096); memset(m_pageTableOne, 0, 4096); - memset(m_kernel_page_directory, 0, 4096); + memset(m_kernel_page_directory, 0, 8192); #ifdef MM_DEBUG kprintf("MM: Kernel page directory @ %p\n", m_kernel_page_directory); @@ -68,7 +77,7 @@ void MemoryManager::initializePaging() ); } -void* MemoryManager::allocatePageTable() +void* MemoryManager::allocate_page_table() { auto ppages = allocatePhysicalPages(1); dword address = ppages[0].get(); @@ -77,39 +86,40 @@ void* MemoryManager::allocatePageTable() return (void*)address; } -auto MemoryManager::ensurePTE(dword* page_directory, LinearAddress laddr) -> PageTableEntry +auto MemoryManager::ensurePTE(PageDirectory* page_directory, LinearAddress laddr) -> PageTableEntry { ASSERT_INTERRUPTS_DISABLED(); - dword pageDirectoryIndex = (laddr.get() >> 22) & 0x3ff; - dword pageTableIndex = (laddr.get() >> 12) & 0x3ff; + dword page_directory_index = (laddr.get() >> 22) & 0x3ff; + dword page_table_index = (laddr.get() >> 12) & 0x3ff; - PageDirectoryEntry pde = PageDirectoryEntry(&page_directory[pageDirectoryIndex]); + PageDirectoryEntry pde = PageDirectoryEntry(&page_directory->entries[page_directory_index]); if (!pde.isPresent()) { #ifdef MM_DEBUG - dbgprintf("MM: PDE %u not present, allocating\n", pageDirectoryIndex); + dbgprintf("MM: PDE %u not present, allocating\n", page_directory_index); #endif - if (pageDirectoryIndex == 0) { + if (page_directory_index == 0) { pde.setPageTableBase((dword)m_pageTableZero); pde.setUserAllowed(false); pde.setPresent(true); pde.setWritable(true); - } else if (pageDirectoryIndex == 1) { + } else if (page_directory_index == 1) { pde.setPageTableBase((dword)m_pageTableOne); pde.setUserAllowed(false); pde.setPresent(true); pde.setWritable(true); } else { - auto* pageTable = allocatePageTable(); + auto* page_table = allocate_page_table(); #ifdef MM_DEBUG - dbgprintf("MM: PDE %x allocated page table #%u (for laddr=%p) at %p\n", page_directory, pageDirectoryIndex, laddr.get(), pageTable); + dbgprintf("MM: PDE %x allocated page table #%u (for laddr=%p) at %p\n", page_directory, page_directory_index, laddr.get(), page_table); #endif - pde.setPageTableBase((dword)pageTable); + page_directory->physical_addresses[page_directory_index] = PhysicalAddress((dword)page_table); + pde.setPageTableBase((dword)page_table); pde.setUserAllowed(true); pde.setPresent(true); pde.setWritable(true); } } - return PageTableEntry(&pde.pageTableBase()[pageTableIndex]); + return PageTableEntry(&pde.pageTableBase()[page_table_index]); } void MemoryManager::protectMap(LinearAddress linearAddress, size_t length) @@ -217,8 +227,8 @@ void MemoryManager::enter_kernel_paging_scope() void MemoryManager::enter_process_paging_scope(Process& process) { InterruptDisabler disabler; - current->m_tss.cr3 = (dword)process.m_pageDirectory; - asm volatile("movl %%eax, %%cr3"::"a"(process.m_pageDirectory)); + current->m_tss.cr3 = (dword)process.m_page_directory; + asm volatile("movl %%eax, %%cr3"::"a"(process.m_page_directory)); } void MemoryManager::flushEntireTLB() @@ -234,7 +244,7 @@ void MemoryManager::flushTLB(LinearAddress laddr) asm volatile("invlpg %0": :"m" (*(char*)laddr.get())); } -void MemoryManager::map_region_at_address(dword* page_directory, Region& region, LinearAddress laddr, bool user_allowed) +void MemoryManager::map_region_at_address(PageDirectory* page_directory, Region& region, LinearAddress laddr, bool user_allowed) { InterruptDisabler disabler; auto& zone = *region.zone; @@ -252,7 +262,7 @@ void MemoryManager::map_region_at_address(dword* page_directory, Region& region, } } -void MemoryManager::unmap_range(dword* page_directory, LinearAddress laddr, size_t size) +void MemoryManager::unmap_range(PageDirectory* page_directory, LinearAddress laddr, size_t size) { ASSERT((size % PAGE_SIZE) == 0); @@ -287,6 +297,9 @@ byte* MemoryManager::create_kernel_alias_for_region(Region& region) InterruptDisabler disabler; auto laddr = allocate_linear_address_range(region.size); map_region_at_address(m_kernel_page_directory, region, laddr, false); +#ifdef MM_DEBUG + dbgprintf("MM: Created alias L%x for L%x\n", laddr.get(), region.linearAddress.get()); +#endif return laddr.asPtr(); } @@ -301,7 +314,7 @@ bool MemoryManager::unmapRegion(Process& process, Region& region) auto& zone = *region.zone; for (size_t i = 0; i < zone.m_pages.size(); ++i) { auto laddr = region.linearAddress.offset(i * PAGE_SIZE); - auto pte = ensurePTE(process.m_pageDirectory, laddr); + auto pte = ensurePTE(process.m_page_directory, laddr); pte.setPhysicalPageBase(0); pte.setPresent(false); pte.setWritable(false); @@ -321,7 +334,7 @@ bool MemoryManager::unmapSubregion(Process& process, Subregion& subregion) ASSERT(numPages); for (size_t i = 0; i < numPages; ++i) { auto laddr = subregion.linearAddress.offset(i * PAGE_SIZE); - auto pte = ensurePTE(process.m_pageDirectory, laddr); + auto pte = ensurePTE(process.m_page_directory, laddr); pte.setPhysicalPageBase(0); pte.setPresent(false); pte.setWritable(false); @@ -344,7 +357,7 @@ bool MemoryManager::mapSubregion(Process& process, Subregion& subregion) ASSERT(numPages); for (size_t i = 0; i < numPages; ++i) { auto laddr = subregion.linearAddress.offset(i * PAGE_SIZE); - auto pte = ensurePTE(process.m_pageDirectory, laddr); + auto pte = ensurePTE(process.m_page_directory, laddr); pte.setPhysicalPageBase(zone.m_pages[firstPage + i].get()); pte.setPresent(true); pte.setWritable(true); @@ -359,7 +372,7 @@ bool MemoryManager::mapSubregion(Process& process, Subregion& subregion) bool MemoryManager::mapRegion(Process& process, Region& region) { - map_region_at_address(process.m_pageDirectory, region, region.linearAddress, true); + map_region_at_address(process.m_page_directory, region, region.linearAddress, true); return true; } @@ -367,7 +380,7 @@ bool MemoryManager::validate_user_read(const Process& process, LinearAddress lad { dword pageDirectoryIndex = (laddr.get() >> 22) & 0x3ff; dword pageTableIndex = (laddr.get() >> 12) & 0x3ff; - auto pde = PageDirectoryEntry(&process.m_pageDirectory[pageDirectoryIndex]); + auto pde = PageDirectoryEntry(&process.m_page_directory->entries[pageDirectoryIndex]); if (!pde.isPresent()) return false; auto pte = PageTableEntry(&pde.pageTableBase()[pageTableIndex]); @@ -382,7 +395,7 @@ bool MemoryManager::validate_user_write(const Process& process, LinearAddress la { dword pageDirectoryIndex = (laddr.get() >> 22) & 0x3ff; dword pageTableIndex = (laddr.get() >> 12) & 0x3ff; - auto pde = PageDirectoryEntry(&process.m_pageDirectory[pageDirectoryIndex]); + auto pde = PageDirectoryEntry(&process.m_page_directory->entries[pageDirectoryIndex]); if (!pde.isPresent()) return false; auto pte = PageTableEntry(&pde.pageTableBase()[pageTableIndex]); diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index 6b2611081b..f86e1e5ea0 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -17,6 +17,11 @@ enum class PageFaultResponse { Continue, }; +struct PageDirectory { + dword entries[1024]; + PhysicalAddress physical_addresses[1024]; +}; + struct Zone : public Retainable { friend ByteBuffer procfs$mm(); public: @@ -78,6 +83,7 @@ public: void unregisterZone(Zone&); void populate_page_directory(Process&); + void release_page_directory(Process&); byte* create_kernel_alias_for_region(Region&); void remove_kernel_alias_for_region(Region&, byte*); @@ -93,14 +99,14 @@ private: ~MemoryManager(); LinearAddress allocate_linear_address_range(size_t); - void map_region_at_address(dword* page_directory, Region&, LinearAddress, bool user_accessible); - void unmap_range(dword* page_directory, LinearAddress, size_t); + void map_region_at_address(PageDirectory*, Region&, LinearAddress, bool user_accessible); + void unmap_range(PageDirectory*, LinearAddress, size_t); void initializePaging(); void flushEntireTLB(); void flushTLB(LinearAddress); - void* allocatePageTable(); + void* allocate_page_table(); void protectMap(LinearAddress, size_t length); void identityMap(LinearAddress, size_t length); @@ -185,9 +191,9 @@ private: dword* m_pte; }; - PageTableEntry ensurePTE(dword* pageDirectory, LinearAddress); + PageTableEntry ensurePTE(PageDirectory*, LinearAddress); - dword* m_kernel_page_directory; + PageDirectory* m_kernel_page_directory; dword* m_pageTableZero; dword* m_pageTableOne; @@ -203,7 +209,7 @@ struct KernelPagingScope { ~KernelPagingScope() { MM.enter_process_paging_scope(*current); } }; -struct OtherProcessPagingScope { - OtherProcessPagingScope(Process& process) { MM.enter_process_paging_scope(process); } - ~OtherProcessPagingScope() { MM.enter_process_paging_scope(*current); } +struct ProcessPagingScope { + ProcessPagingScope(Process& process) { MM.enter_process_paging_scope(process); } + ~ProcessPagingScope() { MM.enter_process_paging_scope(*current); } }; diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp index 46180eeb6f..e85cc87a9a 100644 --- a/Kernel/ProcFileSystem.cpp +++ b/Kernel/ProcFileSystem.cpp @@ -78,7 +78,7 @@ ByteBuffer procfs$pid_vm(Process& process) ByteBuffer procfs$pid_stack(Process& process) { ProcessInspectionScope scope(process); - OtherProcessPagingScope pagingScope(process); + ProcessPagingScope pagingScope(process); struct RecognizedSymbol { dword address; const KSym* ksym; @@ -147,14 +147,14 @@ ByteBuffer procfs$mm() zonePageCount += zone->m_pages.size(); auto buffer = ByteBuffer::createUninitialized(1024 + 80 * MM.m_zones.size() + zonePageCount * 10); char* ptr = (char*)buffer.pointer(); - ptr += ksprintf(ptr, "Zone count: %u\n", MM.m_zones.size()); - ptr += ksprintf(ptr, "Free physical pages: %u\n", MM.m_freePages.size()); for (auto* zone : MM.m_zones) { ptr += ksprintf(ptr, "Zone %p size: %u\n ", zone, zone->size()); for (auto page : zone->m_pages) ptr += ksprintf(ptr, "%x ", page); ptr += ksprintf(ptr, "\n"); } + ptr += ksprintf(ptr, "Zone count: %u\n", MM.m_zones.size()); + ptr += ksprintf(ptr, "Free physical pages: %u\n", MM.m_freePages.size()); buffer.trim(ptr - (char*)buffer.pointer()); return buffer; } diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 1c2597d042..0aad37c661 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -285,22 +285,17 @@ Process* Process::createUserProcess(const String& path, uid_t uid, gid_t gid, pi ExecSpace space; Region* region = nullptr; - byte* region_alias = nullptr; - KernelPagingScope pagingScope; + ProcessPagingScope pagingScope(*t); space.hookableAlloc = [&] (const String& name, size_t size) { if (!size) return (void*)nullptr; size = ((size / 4096) + 1) * 4096; // FIXME: Use ceil_div? region = t->allocateRegion(size, String(name)); - ASSERT(region); - region_alias = MM.create_kernel_alias_for_region(*region); - return (void*)region_alias; + return (void*)region->linearAddress.get(); }; bool success = space.loadELF(move(elfData)); if (!success) { - if (region) - MM.remove_kernel_alias_for_region(*region, region_alias); delete t; kprintf("Failure loading ELF %s\n", path.characters()); error = -ENOEXEC; @@ -325,15 +320,12 @@ Process* Process::createUserProcess(const String& path, uid_t uid, gid_t gid, pi t->m_tss.eip = (dword)space.symbolPtr("_start"); if (!t->m_tss.eip) { // FIXME: This is ugly. If we need to do this, it should be at a different level. - if (region) - MM.remove_kernel_alias_for_region(*region, region_alias); delete t; error = -ENOEXEC; return nullptr; } ASSERT(region); - MM.remove_kernel_alias_for_region(*region, region_alias); ProcFileSystem::the().addProcess(*t); @@ -414,7 +406,7 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel , m_tty(tty) , m_parentPID(parentPID) { - m_pageDirectory = (dword*)kmalloc_page_aligned(4096); + m_page_directory = (PageDirectory*)kmalloc_page_aligned(sizeof(PageDirectory)); MM.populate_page_directory(*this); m_file_descriptors.resize(m_max_open_file_descriptors); @@ -456,7 +448,7 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel m_tss.ss = ss; m_tss.cs = cs; - m_tss.cr3 = (dword)m_pageDirectory; + m_tss.cr3 = (dword)m_page_directory; if (isRing0()) { // FIXME: This memory is leaked. @@ -502,6 +494,8 @@ Process::~Process() kfree(m_kernelStack); m_kernelStack = nullptr; } + + MM.release_page_directory(*this); } void Process::dumpRegions() @@ -610,9 +604,9 @@ void Process::processDidCrash(Process* crashedProcess) void Process::doHouseKeeping() { - InterruptDisabler disabler; if (s_deadProcesses->isEmpty()) return; + InterruptDisabler disabler; Process* next = nullptr; for (auto* deadProcess = s_deadProcesses->head(); deadProcess; deadProcess = next) { next = deadProcess->next(); diff --git a/Kernel/Process.h b/Kernel/Process.h index 27f78d461c..b1cb535a74 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -10,6 +10,7 @@ #include "TTY.h" class FileHandle; +class PageDirectory; class Region; class Subregion; class Zone; @@ -149,7 +150,7 @@ private: void allocateLDT(); - dword* m_pageDirectory { nullptr }; + PageDirectory* m_page_directory { nullptr }; Process* m_prev { nullptr }; Process* m_next { nullptr }; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 96ec5be317..81a3fd84f0 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -49,13 +49,20 @@ static byte parseHexDigit(char nibble) return 10 + (nibble - 'a'); } +#ifdef KSYMS static Vector* s_ksyms; +static bool s_ksyms_ready; Vector& ksyms() { return *s_ksyms; } +volatile bool ksyms_ready() +{ + return s_ksyms_ready; +} + const KSym* ksymbolicate(dword address) { if (address < ksyms().first().address || address > ksyms().last().address) @@ -90,8 +97,38 @@ static void loadKsyms(const ByteBuffer& buffer) ksyms().append({ address, String(startOfName, bufptr - startOfName) }); ++bufptr; } + s_ksyms_ready = true; } +void dump_backtrace() +{ + if (!current) + return; + extern volatile bool ksyms_ready(); + if (!ksyms_ready()) + return; + dword stack_variable; + struct RecognizedSymbol { + dword address; + const KSym* ksym; + }; + Vector recognizedSymbols; + for (dword* stackPtr = &stack_variable; current->isValidAddressForKernel(LinearAddress((dword)stackPtr)); stackPtr = (dword*)*stackPtr) { + dword retaddr = stackPtr[1]; + if (auto* ksym = ksymbolicate(retaddr)) + recognizedSymbols.append({ retaddr, ksym }); + } + size_t bytesNeeded = 0; + for (auto& symbol : recognizedSymbols) { + bytesNeeded += symbol.ksym->name.length() + 8 + 16; + } + for (auto& symbol : recognizedSymbols) { + unsigned offset = symbol.address - symbol.ksym->address; + dbgprintf("%p %s +%u\n", symbol.address, symbol.ksym->name.characters(), offset); + } +} +#endif + static void undertaker_main() NORETURN; static void undertaker_main() { @@ -109,8 +146,8 @@ static void spawn_stress() for (unsigned i = 0; i < 10000; ++i) { int error; Process::createUserProcess("/bin/id", (uid_t)100, (gid_t)100, (pid_t)0, error, nullptr, tty0); - kprintf("malloc stats: alloc:%u free:%u page_aligned:%u eternal:%u\n", sum_alloc, sum_free, kmalloc_page_aligned, kmalloc_sum_eternal); - kprintf("delta:%u\n", sum_alloc - lastAlloc); +// kprintf("malloc stats: alloc:%u free:%u page_aligned:%u eternal:%u\n", sum_alloc, sum_free, kmalloc_page_aligned, kmalloc_sum_eternal); +// kprintf("delta:%u\n", sum_alloc - lastAlloc); lastAlloc = sum_alloc; sleep(60); } @@ -223,6 +260,11 @@ void init() { cli(); +#ifdef KSYMS + s_ksyms = nullptr; + s_ksyms_ready = false; +#endif + kmalloc_init(); vga_init(); diff --git a/Kernel/types.h b/Kernel/types.h index 99fa7c989a..e81762617a 100644 --- a/Kernel/types.h +++ b/Kernel/types.h @@ -66,6 +66,8 @@ public: void set(dword address) { m_address = address; } void mask(dword m) { m_address &= m; } + bool is_null() const { return m_address == 0; } + byte* asPtr() { return reinterpret_cast(m_address); } const byte* asPtr() const { return reinterpret_cast(m_address); } diff --git a/Userland/id.cpp b/Userland/id.cpp index 60e0b056a9..44a31264fc 100644 --- a/Userland/id.cpp +++ b/Userland/id.cpp @@ -9,7 +9,7 @@ int main(int c, char** v) struct passwd* pw = getpwuid(uid); - printf("uid=%u(%s), gid=%u\n", uid, pw ? pw->pw_name : "n/a", gid); + printf("uid=%u(%s), gid=%u, pid=%u\n", uid, pw ? pw->pw_name : "n/a", gid, getpid()); return 0; }