[GSP::GPU] We can now request interrupts

This commit is contained in:
wheremyfoodat 2022-09-20 23:22:35 +03:00
parent 194761ca54
commit 3ccba6db40
5 changed files with 37 additions and 0 deletions

View file

@ -2,11 +2,23 @@
#include "helpers.hpp" #include "helpers.hpp"
#include "kernel_types.hpp" #include "kernel_types.hpp"
#include "memory.hpp" #include "memory.hpp"
#include <cstring>
enum class GPUInterrupt : u8 {
PSC0 = 0, // Memory fill completed
PSC1 = 1, // ?
VBlank0 = 2, // ?
VBlank1 = 3, // ?
PPF = 4, // Display transfer finished
P3D = 5, // Command list processing finished
DMA = 6
};
class GPUService { class GPUService {
Handle handle = KernelHandles::GPU; Handle handle = KernelHandles::GPU;
Memory& mem; Memory& mem;
u32& currentPID; // Process ID of the current process u32& currentPID; // Process ID of the current process
u8* sharedMem; // Pointer to GSP shared memory
// At any point in time only 1 process has privileges to use rendering functions // At any point in time only 1 process has privileges to use rendering functions
// This is the PID of that process // This is the PID of that process
@ -22,4 +34,11 @@ public:
GPUService(Memory& mem, u32& currentPID) : mem(mem), currentPID(currentPID) {} GPUService(Memory& mem, u32& currentPID) : mem(mem), currentPID(currentPID) {}
void reset(); void reset();
void handleSyncRequest(u32 messagePointer); void handleSyncRequest(u32 messagePointer);
void requestInterrupt(GPUInterrupt type);
void setSharedMem(u8* ptr) {
sharedMem = ptr;
if (ptr != nullptr) { // Zero-fill shared memory in case the process tries to read stale service data or vice versa
std::memset(ptr, 0, 0x1000);
}
}
}; };

View file

@ -29,4 +29,6 @@ public:
// Forward a SendSyncRequest IPC message to the service with the respective handle // Forward a SendSyncRequest IPC message to the service with the respective handle
void sendCommandToService(u32 messagePointer, Handle handle); void sendCommandToService(u32 messagePointer, Handle handle);
void requestGPUInterrupt(GPUInterrupt type) { gsp_gpu.requestInterrupt(type); }
void setGSPSharedMem(u8* ptr) { gsp_gpu.setSharedMem(ptr); }
}; };

View file

@ -57,5 +57,6 @@ void Kernel::waitSynchronization1() {
} }
printf("WaitSynchronization1(handle = %X, ns = %lld) (STUBBED)\n", handle, ns); printf("WaitSynchronization1(handle = %X, ns = %lld) (STUBBED)\n", handle, ns);
serviceManager.requestGPUInterrupt(GPUInterrupt::VBlank0);
regs[0] = SVCResult::Success; regs[0] = SVCResult::Success;
} }

View file

@ -105,6 +105,7 @@ void Kernel::mapMemoryBlock() {
if (block == KernelHandles::GSPSharedMemHandle) { if (block == KernelHandles::GSPSharedMemHandle) {
mem.mapGSPSharedMemory(addr, myPerms, otherPerms); mem.mapGSPSharedMemory(addr, myPerms, otherPerms);
serviceManager.setGSPSharedMem(static_cast<u8*>(mem.getReadPointer(addr)));
} else { } else {
Helpers::panic("MapMemoryBlock where the handle does not refer to GSP memory"); Helpers::panic("MapMemoryBlock where the handle does not refer to GSP memory");
} }

View file

@ -18,6 +18,7 @@ namespace Result {
void GPUService::reset() { void GPUService::reset() {
privilegedProcess = 0xFFFFFFFF; // Set the privileged process to an invalid handle privilegedProcess = 0xFFFFFFFF; // Set the privileged process to an invalid handle
sharedMem = nullptr;
} }
void GPUService::handleSyncRequest(u32 messagePointer) { void GPUService::handleSyncRequest(u32 messagePointer) {
@ -63,6 +64,19 @@ void GPUService::registerInterruptRelayQueue(u32 messagePointer) {
mem.write32(messagePointer + 16, KernelHandles::GSPSharedMemHandle); mem.write32(messagePointer + 16, KernelHandles::GSPSharedMemHandle);
} }
void GPUService::requestInterrupt(GPUInterrupt type) {
if (sharedMem == nullptr) [[unlikely]] { // Shared memory hasn't been set up yet
return;
}
u8 index = sharedMem[0];
u8& interruptCount = sharedMem[1];
u8 flagIndex = (index + interruptCount) % 0x34;
interruptCount++;
sharedMem[0xC + flagIndex] = static_cast<u8>(type);
}
void GPUService::writeHwRegs(u32 messagePointer) { void GPUService::writeHwRegs(u32 messagePointer) {
u32 ioAddr = mem.read32(messagePointer + 4); // GPU address based at 0x1EB00000, word aligned u32 ioAddr = mem.read32(messagePointer + 4); // GPU address based at 0x1EB00000, word aligned
const u32 size = mem.read32(messagePointer + 8); // Size in bytes const u32 size = mem.read32(messagePointer + 8); // Size in bytes