[Kernel] Fix ArbitrateAddress

This commit is contained in:
wheremyfoodat 2022-09-20 16:50:20 +03:00
parent 919951516a
commit 77078f73b3
5 changed files with 25 additions and 13 deletions

View file

@ -66,6 +66,7 @@ class Kernel {
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, u32 id, ThreadStatus status = ThreadStatus::Dormant);
void sleepThreadOnArbiter(u32 waitingAddress);
void switchThread(int newThreadIndex); void switchThread(int newThreadIndex);
std::optional<Handle> getPortHandle(const char* name); std::optional<Handle> getPortHandle(const char* name);

View file

@ -88,13 +88,13 @@ struct Session {
}; };
enum class ThreadStatus { enum class ThreadStatus {
Running, // Currently running Running, // Currently running
Ready, // Ready to run Ready, // Ready to run
WaitArb, // Waiting on an address arbiter WaitArbiter, // Waiting on an address arbiter
WaitSleep, // Waiting due to a SleepThread SVC WaitSleep, // Waiting due to a SleepThread SVC
WaitIPC, // Waiting for the reply from an IPC request WaitIPC, // Waiting for the reply from an IPC request
Dormant, // Created but not yet made ready Dormant, // Created but not yet made ready
Dead // Run to completion, or forcefully terminated Dead // Run to completion, or forcefully terminated
}; };
struct Thread { struct Thread {
@ -105,6 +105,9 @@ struct Thread {
ThreadStatus status; ThreadStatus status;
Handle handle; // OS handle for this thread Handle handle; // OS handle for this thread
// The waiting address for threads that are waiting on an AddressArbiter
u32 waitingAddress;
// Thread context used for switching between threads // Thread context used for switching between threads
std::array<u32, 16> gprs; std::array<u32, 16> gprs;
std::array<u32, 32> fprs; // Stored as u32 because dynarmic does it std::array<u32, 32> fprs; // Stored as u32 because dynarmic does it

View file

@ -34,7 +34,7 @@ void Kernel::arbitrateAddress() {
const Handle handle = regs[0]; const Handle handle = regs[0];
const u32 address = regs[1]; const u32 address = regs[1];
const u32 type = regs[2]; const u32 type = regs[2];
const s32 value = regs[3]; const s32 value = s32(regs[3]);
const s64 ns = s64(u64(regs[4]) | (u64(regs[5]) << 32)); const s64 ns = s64(u64(regs[4]) | (u64(regs[5]) << 32));
printf("ArbitrateAddress(Handle = %X, address = %08X, type = %s, value = %d, ns = %lld)\n", handle, address, printf("ArbitrateAddress(Handle = %X, address = %08X, type = %s, value = %d, ns = %lld)\n", handle, address,
@ -50,17 +50,19 @@ void Kernel::arbitrateAddress() {
Helpers::panic("ArbitrateAddres:: Unaligned address"); Helpers::panic("ArbitrateAddres:: Unaligned address");
} }
if (value > 4) [[unlikely]] { if (type > 4) [[unlikely]] {
regs[0] = SVCResult::InvalidEnumValueAlt; regs[0] = SVCResult::InvalidEnumValueAlt;
return; return;
} }
// This needs to put the error code in r0 before we change threats
regs[0] = SVCResult::Success;
switch (static_cast<ArbitrationType>(type)) { switch (static_cast<ArbitrationType>(type)) {
// Puts this thread to sleep if word < value until another thread signals the address with the type SIGNAL // Puts this thread to sleep if word < value until another thread signals the address with the type SIGNAL
case ArbitrationType::WaitIfLess: { case ArbitrationType::WaitIfLess: {
s32 word = static_cast<s32>(mem.read32(address)); // Yes this is meant to be signed s32 word = static_cast<s32>(mem.read32(address)); // Yes this is meant to be signed
if (word < value) { if (word < value) {
Helpers::panic("Needa sleep"); sleepThreadOnArbiter(address);
} }
break; break;
} }
@ -68,6 +70,4 @@ void Kernel::arbitrateAddress() {
default: default:
Helpers::panic("ArbitrateAddress: Unimplemented type %s", arbitrationTypeToString(type)); Helpers::panic("ArbitrateAddress: Unimplemented type %s", arbitrationTypeToString(type));
} }
regs[0] = SVCResult::Success;
} }

View file

@ -81,3 +81,11 @@ 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);
} }
void Kernel::sleepThreadOnArbiter(u32 waitingAddress) {
Thread& t = threads[currentThreadIndex];
t.status = ThreadStatus::WaitArbiter;
t.waitingAddress = waitingAddress;
Helpers::panic("AOWPWOOOPDQ");
}

View file

@ -302,7 +302,7 @@ void Memory::mapGSPSharedMemory(u32 vaddr, u32 myPerms, u32 otherPerms) {
// Wipe the GSP memory allocation from existence // Wipe the GSP memory allocation from existence
gspMemIndex = std::nullopt; gspMemIndex = std::nullopt;
//std::erase(lockedMemoryInfo, index); lockedMemoryInfo.erase(lockedMemoryInfo.begin() + index);
if (myPerms == 0x10000000) { if (myPerms == 0x10000000) {
myPerms = 3; myPerms = 3;