mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-06 22:25:41 +12:00
[Kernel] CreateThread stub
This commit is contained in:
parent
765b51696e
commit
1c4348248d
8 changed files with 58 additions and 7 deletions
|
@ -23,8 +23,12 @@ class CP15 final : public Dynarmic::A32::Coprocessor {
|
||||||
|
|
||||||
CallbackOrAccessOneWord CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
|
CallbackOrAccessOneWord CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
|
||||||
CoprocReg CRm, unsigned opc2) override {
|
CoprocReg CRm, unsigned opc2) override {
|
||||||
|
if (!two && opc1 == 0 && CRn == CoprocReg::C7 && CRm == CoprocReg::C10 && opc2 == 4) {
|
||||||
|
return &dummy; // Normally inserts a "Data Synchronization Barrier"
|
||||||
|
}
|
||||||
|
|
||||||
if (!two && opc1 == 0 && CRn == CoprocReg::C7 && CRm == CoprocReg::C10 && opc2 == 5) {
|
if (!two && opc1 == 0 && CRn == CoprocReg::C7 && CRm == CoprocReg::C10 && opc2 == 5) {
|
||||||
return &dummy; // TODO: Find out what this is. Some sort of memory barrier reg.
|
return &dummy; // Normally inserts a "Data Memory Barrier"
|
||||||
}
|
}
|
||||||
Helpers::panic("CP15: CompileSendOneWord\nopc1: %d CRn: %d CRm: %d opc2: %d\n", opc1, (int)CRn, (int)CRm, opc2);
|
Helpers::panic("CP15: CompileSendOneWord\nopc1: %d CRn: %d CRm: %d opc2: %d\n", opc1, (int)CRn, (int)CRm, opc2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,9 @@ class Kernel {
|
||||||
std::vector<KernelObject> objects;
|
std::vector<KernelObject> objects;
|
||||||
std::vector<Handle> portHandles;
|
std::vector<Handle> portHandles;
|
||||||
|
|
||||||
u32 currentProcess;
|
Handle currentProcess;
|
||||||
|
Handle currentThread;
|
||||||
|
u32 threadCount;
|
||||||
ServiceManager serviceManager;
|
ServiceManager serviceManager;
|
||||||
|
|
||||||
// Get pointer to the object with the specified handle
|
// Get pointer to the object with the specified handle
|
||||||
|
@ -53,6 +55,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);
|
||||||
|
|
||||||
std::optional<Handle> getPortHandle(const char* name);
|
std::optional<Handle> getPortHandle(const char* name);
|
||||||
void deleteObjectData(KernelObject& object);
|
void deleteObjectData(KernelObject& object);
|
||||||
|
@ -68,6 +71,7 @@ class Kernel {
|
||||||
// SVC implementations
|
// SVC implementations
|
||||||
void createAddressArbiter();
|
void createAddressArbiter();
|
||||||
void createEvent();
|
void createEvent();
|
||||||
|
void createThread();
|
||||||
void controlMemory();
|
void controlMemory();
|
||||||
void mapMemoryBlock();
|
void mapMemoryBlock();
|
||||||
void queryMemory();
|
void queryMemory();
|
||||||
|
|
|
@ -10,12 +10,14 @@ namespace SVCResult {
|
||||||
// Different calls return a different value
|
// Different calls return a different value
|
||||||
BadHandle = 0xD8E007F7,
|
BadHandle = 0xD8E007F7,
|
||||||
BadHandleAlt = 0xD9001BF7,
|
BadHandleAlt = 0xD9001BF7,
|
||||||
PortNameTooLong = 0xE0E0181E
|
|
||||||
|
BadThreadPriority = 0xE0E01BFD,
|
||||||
|
PortNameTooLong = 0xE0E0181E,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class KernelObjectType : u8 {
|
enum class KernelObjectType : u8 {
|
||||||
Event, Port, Process, ResourceLimit, Session, Dummy
|
Event, Port, Process, ResourceLimit, Session, Thread, Dummy
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ResourceLimitCategory : int {
|
enum class ResourceLimitCategory : int {
|
||||||
|
@ -84,6 +86,7 @@ static const char* kernelObjectTypeToString(KernelObjectType t) {
|
||||||
case KernelObjectType::Process: return "process";
|
case KernelObjectType::Process: return "process";
|
||||||
case KernelObjectType::ResourceLimit: return "resource limit";
|
case KernelObjectType::ResourceLimit: return "resource limit";
|
||||||
case KernelObjectType::Session: return "session";
|
case KernelObjectType::Session: return "session";
|
||||||
|
case KernelObjectType::Thread: return "thread";
|
||||||
case KernelObjectType::Dummy: return "dummy";
|
case KernelObjectType::Dummy: return "dummy";
|
||||||
default: return "unknown";
|
default: return "unknown";
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ void Kernel::serviceSVC(u32 svc) {
|
||||||
switch (svc) {
|
switch (svc) {
|
||||||
case 0x01: controlMemory(); break;
|
case 0x01: controlMemory(); break;
|
||||||
case 0x02: queryMemory(); break;
|
case 0x02: queryMemory(); break;
|
||||||
|
case 0x08: createThread(); break;
|
||||||
case 0x17: createEvent(); break;
|
case 0x17: createEvent(); break;
|
||||||
case 0x1F: mapMemoryBlock(); break;
|
case 0x1F: mapMemoryBlock(); break;
|
||||||
case 0x21: createAddressArbiter(); break;
|
case 0x21: createAddressArbiter(); break;
|
||||||
|
@ -57,6 +58,7 @@ void Kernel::deleteObjectData(KernelObject& object) {
|
||||||
|
|
||||||
void Kernel::reset() {
|
void Kernel::reset() {
|
||||||
handleCounter = 0;
|
handleCounter = 0;
|
||||||
|
threadCount = 0;
|
||||||
|
|
||||||
for (auto& object : objects) {
|
for (auto& object : objects) {
|
||||||
deleteObjectData(object);
|
deleteObjectData(object);
|
||||||
|
@ -68,6 +70,9 @@ 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.
|
||||||
|
// Main thread seems to have a priority of 0x30
|
||||||
|
currentThread = makeThread(0, 0, 0x30, 0);
|
||||||
|
|
||||||
// Create global service manager port
|
// Create global service manager port
|
||||||
makePort("srv:");
|
makePort("srv:");
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include "kernel.hpp"
|
||||||
|
#include "resource_limits.hpp"
|
||||||
|
|
||||||
|
// Internal OS function to spawn a thread
|
||||||
|
Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, u32 id) {
|
||||||
|
if (threadCount >= appResourceLimits.maxThreads) {
|
||||||
|
Helpers::panic("Overflowed the number of threads");
|
||||||
|
}
|
||||||
|
threadCount++;
|
||||||
|
|
||||||
|
// TODO: Actually create the thread
|
||||||
|
return makeObject(KernelObjectType::Thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result CreateThread(s32 priority, ThreadFunc entrypoint, u32 arg, u32 stacktop, s32 threadPriority, s32 processorID)
|
||||||
|
void Kernel::createThread() {
|
||||||
|
u32 priority = regs[0];
|
||||||
|
u32 entrypoint = regs[1];
|
||||||
|
u32 initialSP = regs[3] & ~7; // SP is force-aligned to 8 bytes
|
||||||
|
u32 id = regs[4];
|
||||||
|
|
||||||
|
printf("CreateThread(entry = %08X, stacktop = %08X, priority = %X, processor ID = %d)\n", entrypoint,
|
||||||
|
initialSP, priority, id);
|
||||||
|
|
||||||
|
if (!(priority <= 0x3F)) [[unlikely]] {
|
||||||
|
Helpers::panic("Created thread with bad priority value %X", priority);
|
||||||
|
regs[0] = SVCResult::BadThreadPriority;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs[0] = SVCResult::Success;
|
||||||
|
regs[1] = makeThread(entrypoint, initialSP, priority, id);
|
||||||
|
}
|
|
@ -58,9 +58,9 @@ void GPUService::registerInterruptRelayQueue(u32 messagePointer) {
|
||||||
printf("GSP::GPU::RegisterInterruptRelayQueue (flags = %X, event handle = %X)\n", flags, eventHandle);
|
printf("GSP::GPU::RegisterInterruptRelayQueue (flags = %X, event handle = %X)\n", flags, eventHandle);
|
||||||
|
|
||||||
mem.write32(messagePointer + 4, Result::SuccessRegisterIRQ);
|
mem.write32(messagePointer + 4, Result::SuccessRegisterIRQ);
|
||||||
mem.write32(messagePointer + 8, 79797979); // TODO: GSP module thread index
|
mem.write32(messagePointer + 8, 0); // TODO: GSP module thread index
|
||||||
mem.write32(messagePointer + 12, 0); // Translation descriptor
|
mem.write32(messagePointer + 12, 0); // Translation descriptor
|
||||||
mem.write32(messagePointer + 16, KernelHandles::GSPSharedMemHandle); // TODO: GSP shared memory handle
|
mem.write32(messagePointer + 16, KernelHandles::GSPSharedMemHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUService::writeHwRegs(u32 messagePointer) {
|
void GPUService::writeHwRegs(u32 messagePointer) {
|
||||||
|
|
|
@ -5,6 +5,8 @@ void Emulator::reset() {
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
kernel.reset();
|
kernel.reset();
|
||||||
|
|
||||||
|
// Reloading r13 and r15 needs to happen after everything has been reset
|
||||||
|
// Otherwise resetting the kernel or cpu might nuke them
|
||||||
cpu.setReg(13, VirtualAddrs::StackTop); // Set initial SP
|
cpu.setReg(13, VirtualAddrs::StackTop); // Set initial SP
|
||||||
if (romType == ROMType::ELF) { // Reload ELF if we're using one
|
if (romType == ROMType::ELF) { // Reload ELF if we're using one
|
||||||
loadELF(loadedROM);
|
loadELF(loadedROM);
|
||||||
|
|
|
@ -7,7 +7,7 @@ int main (int argc, char *argv[]) {
|
||||||
Helpers::panic("Failed to initialize OpenGL");
|
Helpers::panic("Failed to initialize OpenGL");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto elfPath = std::filesystem::current_path() / (argc > 1 ? argv[1] : "sm64.elf");
|
auto elfPath = std::filesystem::current_path() / (argc > 1 ? argv[1] : "SimplerTri.elf");
|
||||||
if (!emu.loadELF(elfPath)) {
|
if (!emu.loadELF(elfPath)) {
|
||||||
Helpers::panic("Failed to load ELF file: %s", elfPath.c_str());
|
Helpers::panic("Failed to load ELF file: %s", elfPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue