From 6bfe321777f41e69dace78f12729db60f1da2c24 Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Tue, 20 Sep 2022 17:51:24 +0300 Subject: [PATCH] [Kernel] Allocate TLS for other threads, fix CreateThread svc --- include/kernel/kernel.hpp | 2 +- include/kernel/kernel_types.hpp | 2 +- src/core/kernel/kernel.cpp | 6 ++++-- src/core/kernel/threads.cpp | 15 ++++++++++----- src/core/memory.cpp | 11 ++++++++--- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/include/kernel/kernel.hpp b/include/kernel/kernel.hpp index 14be3fa2..74f078d2 100644 --- a/include/kernel/kernel.hpp +++ b/include/kernel/kernel.hpp @@ -64,7 +64,7 @@ class Kernel { Handle makeProcess(); Handle makePort(const char* name); Handle makeSession(Handle port); - Handle makeThread(u32 entrypoint, u32 initialSP, u32 priority, u32 id, ThreadStatus status = ThreadStatus::Dormant); + Handle makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u32 arg,ThreadStatus status = ThreadStatus::Dormant); void sleepThreadOnArbiter(u32 waitingAddress); void switchThread(int newThreadIndex); diff --git a/include/kernel/kernel_types.hpp b/include/kernel/kernel_types.hpp index f6a21dfb..fcc96367 100644 --- a/include/kernel/kernel_types.hpp +++ b/include/kernel/kernel_types.hpp @@ -101,7 +101,7 @@ struct Thread { u32 initialSP; // Initial r13 value u32 entrypoint; // Initial r15 value u32 priority; - u32 processorID; + s32 processorID; ThreadStatus status; Handle handle; // OS handle for this thread diff --git a/src/core/kernel/kernel.cpp b/src/core/kernel/kernel.cpp index 74166bf8..cfda939e 100644 --- a/src/core/kernel/kernel.cpp +++ b/src/core/kernel/kernel.cpp @@ -84,9 +84,11 @@ void Kernel::reset() { // Allocate handle #0 to a dummy object and make a main process object makeObject(KernelObjectType::Dummy); currentProcess = makeProcess(); + // Make main thread object. We do not have to set the entrypoint and SP for it as the ROM loader does. - // Main thread seems to have a priority of 0x30 - mainThread = makeThread(0, 0, 0x30, 0, ThreadStatus::Running); + // Main thread seems to have a priority of 0x30. TODO: This creates a dummy context for thread 0, + // which is thankfully not used. Maybe we should prevent this + mainThread = makeThread(0, 0, 0x30, -2, 0, ThreadStatus::Running); currentThreadIndex = 0; // Create global service manager port diff --git a/src/core/kernel/threads.cpp b/src/core/kernel/threads.cpp index a5d3273f..56e60170 100644 --- a/src/core/kernel/threads.cpp +++ b/src/core/kernel/threads.cpp @@ -32,7 +32,7 @@ void Kernel::switchThread(int newThreadIndex) { } // Internal OS function to spawn a thread -Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, u32 id, ThreadStatus status) { +Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u32 arg, ThreadStatus status) { if (threadCount >= appResourceLimits.maxThreads) { Helpers::panic("Overflowed the number of threads"); } @@ -47,17 +47,21 @@ Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, u32 id, T t.fprs.fill(0); t.initialSP = initialSP; - t.gprs[13] = initialSP; t.entrypoint = entrypoint; + + t.gprs[0] = arg; + t.gprs[13] = initialSP; t.gprs[15] = entrypoint; t.priority = priority; t.processorID = id; t.status = status; t.handle = ret; + t.waitingAddress = 0; t.cpsr = CPSR::UserMode | (isThumb ? CPSR::Thumb : 0); t.fpscr = FPSCR::ThreadDefault; // Initial TLS base has already been set in Kernel::Kernel() + // TODO: Does svcCreateThread zero-set the TLS of the new thread? return ret; } @@ -66,8 +70,9 @@ Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, u32 id, T void Kernel::createThread() { u32 priority = regs[0]; u32 entrypoint = regs[1]; + u32 arg = regs[2]; // An argument value stored in r0 of the new thread u32 initialSP = regs[3] & ~7; // SP is force-aligned to 8 bytes - u32 id = regs[4]; + s32 id = static_cast(regs[4]); printf("CreateThread(entry = %08X, stacktop = %08X, priority = %X, processor ID = %d)\n", entrypoint, initialSP, priority, id); @@ -79,7 +84,7 @@ void Kernel::createThread() { } regs[0] = SVCResult::Success; - regs[1] = makeThread(entrypoint, initialSP, priority, id); + regs[1] = makeThread(entrypoint, initialSP, priority, id, arg, ThreadStatus::Ready); } void Kernel::sleepThreadOnArbiter(u32 waitingAddress) { @@ -87,5 +92,5 @@ void Kernel::sleepThreadOnArbiter(u32 waitingAddress) { t.status = ThreadStatus::WaitArbiter; t.waitingAddress = waitingAddress; - Helpers::panic("AOWPWOOOPDQ"); + switchThread(1); } \ No newline at end of file diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 3cd34f1f..d225519f 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -1,5 +1,6 @@ #include "memory.hpp" #include "config_mem.hpp" +#include "resource_limits.hpp" #include using namespace KernelMemoryTypes; @@ -27,9 +28,13 @@ void Memory::reset() { u32 basePaddrForStack = FCRAM_APPLICATION_SIZE - VirtualAddrs::StackSize; allocateMemory(VirtualAddrs::StackBottom, basePaddrForStack, VirtualAddrs::StackSize, true); - // And map 4KB of FCRAM before the stack for TLS - u32 basePaddrForTLS = basePaddrForStack - VirtualAddrs::TLSSize; - allocateMemory(VirtualAddrs::TLSBase, basePaddrForTLS, VirtualAddrs::TLSSize, true); + // And map (4 * 32)KB of FCRAM before the stack for the TLS of each thread + u32 basePaddrForTLS = basePaddrForStack; + for (int i = 0; i < appResourceLimits.maxThreads; i++) { + u32 vaddr = VirtualAddrs::TLSBase + i * VirtualAddrs::TLSSize; + basePaddrForTLS -= VirtualAddrs::TLSSize; + allocateMemory(vaddr, basePaddrForTLS, VirtualAddrs::TLSSize, true); + } // Reserve 4KB of memory for GSP shared memory constexpr u32 gspMemSize = 0x1000;