diff options
-rw-r--r-- | AK/Function.h | 1 | ||||
-rw-r--r-- | ELFLoader/ExecSpace.cpp | 11 | ||||
-rw-r--r-- | ELFLoader/ExecSpace.h | 3 | ||||
-rw-r--r-- | Kernel/MemoryManager.cpp | 29 | ||||
-rw-r--r-- | Kernel/MemoryManager.h | 2 | ||||
-rw-r--r-- | Kernel/Task.cpp | 100 | ||||
-rw-r--r-- | Kernel/Task.h | 3 | ||||
-rw-r--r-- | Kernel/_fs_contents | bin | 1024000 -> 1024000 bytes | |||
-rw-r--r-- | Kernel/init.cpp | 4 | ||||
-rw-r--r-- | LibC/entry.cpp | 4 |
10 files changed, 141 insertions, 16 deletions
diff --git a/AK/Function.h b/AK/Function.h index 0fef35abe8..34a2bc68fc 100644 --- a/AK/Function.h +++ b/AK/Function.h @@ -25,6 +25,7 @@ #pragma once +#include "Assertions.h" #include "OwnPtr.h" #include "StdLib.h" diff --git a/ELFLoader/ExecSpace.cpp b/ELFLoader/ExecSpace.cpp index fb6d55a0dd..cbcc8568a5 100644 --- a/ELFLoader/ExecSpace.cpp +++ b/ELFLoader/ExecSpace.cpp @@ -22,7 +22,9 @@ int puts(const char* str) void ExecSpace::initializeBuiltins() { +#ifndef SERENITY m_symbols.set("puts", { (char*)puts, 0 }); +#endif } #ifdef SERENITY @@ -86,8 +88,13 @@ char* ExecSpace::symbolPtr(const char* name) char* ExecSpace::allocateArea(String&& name, unsigned size) { - char* ptr = static_cast<char*>(kmalloc(size)); - ASSERT(ptr); + char* ptr; + if (hookableAlloc) + ptr = static_cast<char*>(hookableAlloc(name, size)); + else + ptr = static_cast<char*>(kmalloc(size)); + if (size) + ASSERT(ptr); m_areas.append(make<Area>(move(name), ptr, size)); return ptr; } diff --git a/ELFLoader/ExecSpace.h b/ELFLoader/ExecSpace.h index 1e22468af4..432bf0a82e 100644 --- a/ELFLoader/ExecSpace.h +++ b/ELFLoader/ExecSpace.h @@ -1,5 +1,6 @@ #pragma once +#include <AK/Function.h> #include <AK/HashMap.h> #include <AK/MappedFile.h> #include <AK/OwnPtr.h> @@ -37,6 +38,8 @@ public: ExecSpace(); ~ExecSpace(); + Function<void*(const String&, size_t)> hookableAlloc; + #ifdef SERENITY bool loadELF(ByteBuffer&&); #else diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index 1d85aca254..019242a741 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -161,20 +161,27 @@ bool MemoryManager::unmapRegionsForTask(Task& task) return true; } +bool MemoryManager::mapRegion(Task& task, Task::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(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; +} + bool MemoryManager::mapRegionsForTask(Task& task) { for (auto& region : task.m_regions) { - 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(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()); - } + if (!mapRegion(task, *region)) + return false; } return true; } diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index 7c6910a5da..a597280add 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -6,6 +6,7 @@ #include <AK/RetainPtr.h> #include <AK/Vector.h> #include <AK/HashMap.h> +#include "Task.h" class Task; @@ -49,6 +50,7 @@ public: // HACK: don't use this jeez :( byte* quickMapOnePage(PhysicalAddress); + bool mapRegion(Task&, Task::Region&); bool mapRegionsForTask(Task&); bool unmapRegionsForTask(Task&); diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 96b5508564..cab2b17ea6 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -7,6 +7,7 @@ #include "system.h" #include <VirtualFileSystem/FileHandle.h> #include <VirtualFileSystem/VirtualFileSystem.h> +#include <ELFLoader/ExecSpace.h> #include "MemoryManager.h" Task* current; @@ -103,6 +104,104 @@ Task::Region* Task::allocateRegion(size_t size, String&& name) return m_regions.last().ptr(); } +Task* Task::create(const String& path, uid_t uid, gid_t gid) +{ + auto parts = path.split('/'); + if (parts.isEmpty()) + return nullptr; + + auto handle = VirtualFileSystem::the().open(path); + if (!handle) + return nullptr; + + auto elfData = handle->readEntireFile(); + if (!elfData) + return nullptr; + + Task* t = new Task(parts.takeLast(), uid, gid); + + ExecSpace space; + space.hookableAlloc = [&] (const String& name, size_t size) { + if (!size) + return (void*)nullptr; + size = ((size / 4096) + 1) * 4096; + Region* region = t->allocateRegion(size, String(name)); + ASSERT(region); + MemoryManager::the().mapRegion(*t, *region); + return (void*)region->linearAddress.asPtr(); + }; + bool success = space.loadELF(move(elfData)); + if (!success) { + delete t; + return nullptr; + } + + t->m_tss.eip = (dword)space.symbolPtr("_start"); + + // Add this task to head of task list (meaning it's next to run too, ATM.) + cli(); + s_tasks->prepend(t); + system.nprocess++; + kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip); + sti(); + + return t; +} + +Task::Task(String&& name, uid_t uid, gid_t gid) + : m_name(move(name)) + , m_pid(next_pid++) + , m_uid(uid) + , m_gid(gid) + , m_state(Runnable) + , m_ring(Ring3) +{ + m_nextRegion = LinearAddress(0x600000); + + memset(&m_tss, 0, sizeof(m_tss)); + memset(&m_ldtEntries, 0, sizeof(m_ldtEntries)); + + allocateLDT(); + + // Only IF is set when a task boots. + m_tss.eflags = 0x0202; + + WORD codeSegment = 0x1b; + WORD dataSegment = 0x23; + WORD stackSegment = dataSegment; + + m_tss.ds = dataSegment; + m_tss.es = dataSegment; + m_tss.fs = dataSegment; + m_tss.gs = dataSegment; + m_tss.ss = stackSegment; + m_tss.cs = codeSegment; + + m_tss.cr3 = MemoryManager::the().pageDirectoryBase().get(); + + // NOTE: Each task gets 16KB of stack. + static const DWORD defaultStackSize = 16384; + + auto* region = allocateRegion(defaultStackSize, "stack"); + ASSERT(region); + m_stackTop = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8; + m_tss.esp = m_stackTop; + + // Set up a separate stack for Ring0. + // FIXME: Don't leak this stack. + m_kernelStack = kmalloc(defaultStackSize); + DWORD ring0StackTop = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8; + m_tss.ss0 = 0x10; + m_tss.esp0 = ring0StackTop; + + // HACK: Ring2 SS in the TSS is the current PID. + m_tss.ss2 = m_pid; + + m_farPtr.offset = 0x98765432; + + ASSERT(m_pid); +} + Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring) : m_name(n) , m_entry(e) @@ -241,7 +340,6 @@ void Task::sys$exit(int status) kprintf("sys$exit: %s(%u) exit with status %d\n", name().characters(), pid(), status); setState(Exiting); - dumpRegions(); s_tasks->remove(this); diff --git a/Kernel/Task.h b/Kernel/Task.h index eaf338b212..2e230bf2ef 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -16,6 +16,9 @@ class Zone; class Task : public InlineLinkedListNode<Task> { friend class InlineLinkedListNode<Task>; public: + static Task* create(const String& path, uid_t, gid_t); + Task(String&& name, uid_t, gid_t); + #ifdef TASK_SANITY_CHECKS static void checkSanity(const char* msg = nullptr); #else diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents Binary files differindex fb6d9448f3..db5b3cfb2f 100644 --- a/Kernel/_fs_contents +++ b/Kernel/_fs_contents diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 238f6d4253..b35f34bcb6 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -27,7 +27,7 @@ #include "Console.h" #define TEST_VFS -#define TEST_ELF_LOADER +//#define TEST_ELF_LOADER //#define TEST_CRASHY_USER_PROCESSES static void motd_main() NORETURN; @@ -167,6 +167,8 @@ static void init_stage2() } #endif + auto* idTask = Task::create("/bin/id", (uid_t)209, (gid_t)1985); + //new Task(motd_main, "motd", IPC::Handle::MotdTask, Task::Ring0); //new Task(syscall_test_main, "syscall_test", IPC::Handle::MotdTask, Task::Ring3); diff --git a/LibC/entry.cpp b/LibC/entry.cpp index c84b819b02..9a34577977 100644 --- a/LibC/entry.cpp +++ b/LibC/entry.cpp @@ -5,7 +5,9 @@ extern "C" int main(int, char**); extern "C" int _start() { // FIXME: Pass appropriate argc/argv. - main(0, nullptr); + int status = main(0, nullptr); + + Syscall::invoke(Syscall::PosixExit, status); // Birger's birthday <3 return 20150614; |