mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-17 19:21:30 +12:00
[Kernel] Fix ArbitrateAddress
This commit is contained in:
parent
919951516a
commit
77078f73b3
5 changed files with 25 additions and 13 deletions
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
|
@ -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");
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue