[Kernel] Allocate TLS for other threads, fix CreateThread svc

This commit is contained in:
wheremyfoodat 2022-09-20 17:51:24 +03:00
parent 77078f73b3
commit 6bfe321777
5 changed files with 24 additions and 12 deletions

View file

@ -64,7 +64,7 @@ class Kernel {
Handle makeProcess(); Handle makeProcess();
Handle makePort(const char* name); Handle makePort(const char* name);
Handle makeSession(Handle port); 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 sleepThreadOnArbiter(u32 waitingAddress);
void switchThread(int newThreadIndex); void switchThread(int newThreadIndex);

View file

@ -101,7 +101,7 @@ struct Thread {
u32 initialSP; // Initial r13 value u32 initialSP; // Initial r13 value
u32 entrypoint; // Initial r15 value u32 entrypoint; // Initial r15 value
u32 priority; u32 priority;
u32 processorID; s32 processorID;
ThreadStatus status; ThreadStatus status;
Handle handle; // OS handle for this thread Handle handle; // OS handle for this thread

View file

@ -84,9 +84,11 @@ void Kernel::reset() {
// Allocate handle #0 to a dummy object and make a main process object // Allocate handle #0 to a dummy object and make a main process object
makeObject(KernelObjectType::Dummy); makeObject(KernelObjectType::Dummy);
currentProcess = makeProcess(); currentProcess = makeProcess();
// Make main thread object. We do not have to set the entrypoint and SP for it as the ROM loader does. // 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 // Main thread seems to have a priority of 0x30. TODO: This creates a dummy context for thread 0,
mainThread = makeThread(0, 0, 0x30, 0, ThreadStatus::Running); // which is thankfully not used. Maybe we should prevent this
mainThread = makeThread(0, 0, 0x30, -2, 0, ThreadStatus::Running);
currentThreadIndex = 0; currentThreadIndex = 0;
// Create global service manager port // Create global service manager port

View file

@ -32,7 +32,7 @@ void Kernel::switchThread(int newThreadIndex) {
} }
// Internal OS function to spawn a thread // 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) { if (threadCount >= appResourceLimits.maxThreads) {
Helpers::panic("Overflowed the number of threads"); 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.fprs.fill(0);
t.initialSP = initialSP; t.initialSP = initialSP;
t.gprs[13] = initialSP;
t.entrypoint = entrypoint; t.entrypoint = entrypoint;
t.gprs[0] = arg;
t.gprs[13] = initialSP;
t.gprs[15] = entrypoint; t.gprs[15] = entrypoint;
t.priority = priority; t.priority = priority;
t.processorID = id; t.processorID = id;
t.status = status; t.status = status;
t.handle = ret; t.handle = ret;
t.waitingAddress = 0;
t.cpsr = CPSR::UserMode | (isThumb ? CPSR::Thumb : 0); t.cpsr = CPSR::UserMode | (isThumb ? CPSR::Thumb : 0);
t.fpscr = FPSCR::ThreadDefault; t.fpscr = FPSCR::ThreadDefault;
// Initial TLS base has already been set in Kernel::Kernel() // Initial TLS base has already been set in Kernel::Kernel()
// TODO: Does svcCreateThread zero-set the TLS of the new thread?
return ret; return ret;
} }
@ -66,8 +70,9 @@ Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, u32 id, T
void Kernel::createThread() { void Kernel::createThread() {
u32 priority = regs[0]; u32 priority = regs[0];
u32 entrypoint = regs[1]; 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 initialSP = regs[3] & ~7; // SP is force-aligned to 8 bytes
u32 id = regs[4]; s32 id = static_cast<s32>(regs[4]);
printf("CreateThread(entry = %08X, stacktop = %08X, priority = %X, processor ID = %d)\n", entrypoint, printf("CreateThread(entry = %08X, stacktop = %08X, priority = %X, processor ID = %d)\n", entrypoint,
initialSP, priority, id); initialSP, priority, id);
@ -79,7 +84,7 @@ void Kernel::createThread() {
} }
regs[0] = SVCResult::Success; 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) { void Kernel::sleepThreadOnArbiter(u32 waitingAddress) {
@ -87,5 +92,5 @@ void Kernel::sleepThreadOnArbiter(u32 waitingAddress) {
t.status = ThreadStatus::WaitArbiter; t.status = ThreadStatus::WaitArbiter;
t.waitingAddress = waitingAddress; t.waitingAddress = waitingAddress;
Helpers::panic("AOWPWOOOPDQ"); switchThread(1);
} }

View file

@ -1,5 +1,6 @@
#include "memory.hpp" #include "memory.hpp"
#include "config_mem.hpp" #include "config_mem.hpp"
#include "resource_limits.hpp"
#include <cassert> #include <cassert>
using namespace KernelMemoryTypes; using namespace KernelMemoryTypes;
@ -27,9 +28,13 @@ void Memory::reset() {
u32 basePaddrForStack = FCRAM_APPLICATION_SIZE - VirtualAddrs::StackSize; u32 basePaddrForStack = FCRAM_APPLICATION_SIZE - VirtualAddrs::StackSize;
allocateMemory(VirtualAddrs::StackBottom, basePaddrForStack, VirtualAddrs::StackSize, true); allocateMemory(VirtualAddrs::StackBottom, basePaddrForStack, VirtualAddrs::StackSize, true);
// And map 4KB of FCRAM before the stack for TLS // And map (4 * 32)KB of FCRAM before the stack for the TLS of each thread
u32 basePaddrForTLS = basePaddrForStack - VirtualAddrs::TLSSize; u32 basePaddrForTLS = basePaddrForStack;
allocateMemory(VirtualAddrs::TLSBase, basePaddrForTLS, VirtualAddrs::TLSSize, true); 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 // Reserve 4KB of memory for GSP shared memory
constexpr u32 gspMemSize = 0x1000; constexpr u32 gspMemSize = 0x1000;