diff --git a/include/kernel/kernel.hpp b/include/kernel/kernel.hpp index bdd48b09..978856d4 100644 --- a/include/kernel/kernel.hpp +++ b/include/kernel/kernel.hpp @@ -21,11 +21,12 @@ class Kernel { Handle currentThread; Handle mainThread; Handle srvHandle; // Handle for the special service manager port "srv:" + u32 arbiterCount; u32 threadCount; ServiceManager serviceManager; // Get pointer to the object with the specified handle - KernelObject* getObject(u32 handle) { + KernelObject* getObject(Handle handle) { // Accessing an object that has not been created if (handle >= objects.size()) [[unlikely]] { return nullptr; @@ -35,7 +36,7 @@ class Kernel { } // Get pointer to the object with the specified handle and type - KernelObject* getObject(u32 handle, KernelObjectType type) { + KernelObject* getObject(Handle handle, KernelObjectType type) { if (handle >= objects.size() || objects[handle].type != type) [[unlikely]] { return nullptr; } @@ -53,6 +54,7 @@ class Kernel { return handleCounter++; } + Handle makeArbiter(); Handle makeEvent(ResetType resetType); Handle makeProcess(); Handle makePort(const char* name); @@ -71,6 +73,7 @@ class Kernel { const char* resetTypeToString(u32 type); // SVC implementations + void arbitrateAddress(); void createAddressArbiter(); void createEvent(); void createThread(); diff --git a/include/kernel/kernel_types.hpp b/include/kernel/kernel_types.hpp index 2d6a7fc6..f4ae210f 100644 --- a/include/kernel/kernel_types.hpp +++ b/include/kernel/kernel_types.hpp @@ -88,7 +88,13 @@ struct Session { }; struct Thread { + u32 initialSP; // Initial r13 value + u32 entrypoint; // Initial r15 value + u32 priority; + u32 processorID; + Thread(u32 initialSP, u32 entrypoint, u32 priority, u32 processorID) : initialSP(initialSP), entrypoint(entrypoint), + priority(priority), processorID(processorID) {} }; static const char* kernelObjectTypeToString(KernelObjectType t) { diff --git a/src/core/kernel/address_arbiter.cpp b/src/core/kernel/address_arbiter.cpp index e69de29b..a87d545e 100644 --- a/src/core/kernel/address_arbiter.cpp +++ b/src/core/kernel/address_arbiter.cpp @@ -0,0 +1,40 @@ +#include "kernel.hpp" +#include "resource_limits.hpp" + +Handle Kernel::makeArbiter() { + if (arbiterCount >= appResourceLimits.maxAddressArbiters) { + Helpers::panic("Overflowed the number of address arbiters"); + } + arbiterCount++; + + Handle ret = makeObject(KernelObjectType::AddressArbiter); + objects[ret].data = new AddressArbiter(); + return ret; +} + +// Result CreateAddressArbiter(Handle* arbiter) +void Kernel::createAddressArbiter() { + regs[0] = SVCResult::Success; + regs[1] = makeArbiter(); +} + +// Result ArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds) +void Kernel::arbitrateAddress() { + const Handle handle = regs[0]; + const u32 address = regs[1]; + const u32 type = regs[2]; + const u32 value = regs[3]; + const s64 ns = s64(u64(regs[4]) | (u64(regs[5]) << 32)); + + printf("ArbitrateAddress(Handle = %X, address = %08X, type = %d, value = %d, ns = %lld)\n", handle, address, type, + value, ns); + + const auto arbiter = getObject(handle, KernelObjectType::AddressArbiter); + if (arbiter == nullptr) [[unlikely]] { + regs[0] = SVCResult::BadHandle; + return; + } + + Helpers::panic("My balls\n"); + regs[0] = SVCResult::Success; +} \ No newline at end of file diff --git a/src/core/kernel/events.cpp b/src/core/kernel/events.cpp index 05644040..024240d9 100644 --- a/src/core/kernel/events.cpp +++ b/src/core/kernel/events.cpp @@ -25,7 +25,6 @@ void Kernel::createEvent() { printf("CreateEvent(handle pointer = %08X, resetType = %s)\n", outPointer, resetTypeToString(resetType)); - Handle handle = makeEvent(static_cast(resetType)); regs[0] = SVCResult::Success; - regs[1] = handle; + regs[1] = makeEvent(static_cast(resetType)); } \ No newline at end of file diff --git a/src/core/kernel/kernel.cpp b/src/core/kernel/kernel.cpp index b578c854..9c6871ce 100644 --- a/src/core/kernel/kernel.cpp +++ b/src/core/kernel/kernel.cpp @@ -10,6 +10,7 @@ void Kernel::serviceSVC(u32 svc) { case 0x17: createEvent(); break; case 0x1F: mapMemoryBlock(); break; case 0x21: createAddressArbiter(); break; + case 0x22: arbitrateAddress(); break; case 0x23: svcCloseHandle(); break; case 0x2D: connectToPort(); break; case 0x32: sendSyncRequest(); break; @@ -58,6 +59,7 @@ void Kernel::deleteObjectData(KernelObject& object) { void Kernel::reset() { handleCounter = 0; + arbiterCount = 0; threadCount = 0; for (auto& object : objects) { @@ -85,12 +87,6 @@ u32 Kernel::getTLSPointer() { return VirtualAddrs::TLSBase; } -// Result CreateAddressArbiter(Handle* arbiter) -void Kernel::createAddressArbiter() { - printf("Stubbed call to CreateAddressArbiter. Handle address: %08X\n", regs[0]); - regs[0] = SVCResult::Success; -} - // Result CloseHandle(Handle handle) void Kernel::svcCloseHandle() { printf("CloseHandle(handle = %d) (Unimplemented)\n", regs[0]); diff --git a/src/core/kernel/ports.cpp b/src/core/kernel/ports.cpp index d2f4158b..75900030 100644 --- a/src/core/kernel/ports.cpp +++ b/src/core/kernel/ports.cpp @@ -56,7 +56,7 @@ void Kernel::connectToPort() { } Handle portHandle = optionalHandle.value(); - printf("ConnectToPort(handle pointer = %08X, port = \"%s\")\n", handlePointer, port.c_str()); + printf("ConnectToPort(handle pointer = %X, port = \"%s\")\n", handlePointer, port.c_str()); const auto portData = objects[portHandle].getData(); if (!portData->isPublic) { diff --git a/src/core/kernel/threads.cpp b/src/core/kernel/threads.cpp index 57e422f2..dab3be72 100644 --- a/src/core/kernel/threads.cpp +++ b/src/core/kernel/threads.cpp @@ -8,8 +8,9 @@ Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, u32 id) { } threadCount++; - // TODO: Actually create the thread - return makeObject(KernelObjectType::Thread); + Handle ret = makeObject(KernelObjectType::Thread); + objects[ret].data = new Thread(initialSP, entrypoint, priority, id); + return ret; } // Result CreateThread(s32 priority, ThreadFunc entrypoint, u32 arg, u32 stacktop, s32 threadPriority, s32 processorID)