From 99e795c141bcf94657367d85c9343b585d82051b Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Sun, 18 Sep 2022 22:52:24 +0300 Subject: [PATCH] [GSP::GPU] Implement writeHwRegs --- include/services/gsp_gpu.hpp | 1 + src/core/elf.cpp | 3 ++- src/core/kernel/memory_management.cpp | 2 +- src/core/services/gsp_gpu.cpp | 32 ++++++++++++++++++++++++++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/include/services/gsp_gpu.hpp b/include/services/gsp_gpu.hpp index 305130e5..651412a8 100644 --- a/include/services/gsp_gpu.hpp +++ b/include/services/gsp_gpu.hpp @@ -15,6 +15,7 @@ class GPUService { // Service commands void acquireRight(u32 messagePointer); void registerInterruptRelayQueue(u32 messagePointer); + void writeHwRegs(u32 messagePointer); public: GPUService(Memory& mem, u32& currentPID) : mem(mem), currentPID(currentPID) {} diff --git a/src/core/elf.cpp b/src/core/elf.cpp index b6bf0e93..5f668400 100644 --- a/src/core/elf.cpp +++ b/src/core/elf.cpp @@ -45,11 +45,12 @@ std::optional Memory::loadELF(std::ifstream& file) { Helpers::warn("Rounding ELF segment size to %08X\n", memorySize); } + // This should also assert that findPaddr doesn't fail u32 fcramAddr = findPaddr(memorySize).value(); std::memcpy(&fcram[fcramAddr], data, fileSize); // Allocate the segment on the OS side - allocateMemory(vaddr, fcramAddr, memorySize, true); + allocateMemory(vaddr, fcramAddr, memorySize, true, r, w, x); } return static_cast(reader.get_entry()); diff --git a/src/core/kernel/memory_management.cpp b/src/core/kernel/memory_management.cpp index 9094f951..e7c3b01a 100644 --- a/src/core/kernel/memory_management.cpp +++ b/src/core/kernel/memory_management.cpp @@ -55,7 +55,7 @@ void Kernel::controlMemory() { switch (operation & 0xFF) { case Operation::Commit: { - std::optional address = mem.allocateMemory(addr0, 0, size, linear); + std::optional address = mem.allocateMemory(addr0, 0, size, linear, r, w, x); if (!address.has_value()) Helpers::panic("ControlMemory: Failed to allocate memory"); diff --git a/src/core/services/gsp_gpu.cpp b/src/core/services/gsp_gpu.cpp index 0225cbef..fca0e6ee 100644 --- a/src/core/services/gsp_gpu.cpp +++ b/src/core/services/gsp_gpu.cpp @@ -3,7 +3,8 @@ namespace GPUCommands { enum : u32 { AcquireRight = 0x00160042, - RegisterInterruptRelayQueue = 0x00130042 + RegisterInterruptRelayQueue = 0x00130042, + WriteHwRegs = 0x00010082 }; } @@ -23,6 +24,7 @@ void GPUService::handleSyncRequest(u32 messagePointer) { switch (command) { case GPUCommands::AcquireRight: acquireRight(messagePointer); break; case GPUCommands::RegisterInterruptRelayQueue: registerInterruptRelayQueue(messagePointer); break; + case GPUCommands::WriteHwRegs: writeHwRegs(messagePointer); break; ; default: Helpers::panic("GPU service requested. Command: %08X\n", command); } } @@ -57,4 +59,32 @@ void GPUService::registerInterruptRelayQueue(u32 messagePointer) { mem.write32(messagePointer + 8, 0); // TODO: GSP module thread index mem.write32(messagePointer + 12, 0); // Translation descriptor mem.write32(messagePointer + 16, 0); // TODO: shared memory handle +} + +void GPUService::writeHwRegs(u32 messagePointer) { + u32 ioAddr = mem.read32(messagePointer + 4); // GPU address based at 0x1EB00000, word aligned + const u32 size = mem.read32(messagePointer + 8); // Size in bytes + u32 dataPointer = mem.read32(messagePointer + 16); + printf("GSP::GPU::writeHwRegs (GPU address = %08X, size = %X, data address = %08X)\n", ioAddr, size, dataPointer); + + // Check for alignment + if ((size & 3) || (ioAddr & 3)) { + Helpers::panic("GSP::GPU::writeHwRegs misalignment"); + } + + if (size > 0x80) { + Helpers::panic("GSP::GPU::writeHwRegs size too big"); + } + + if (ioAddr >= 0x420000) { + Helpers::panic("GSP::GPU::writeHwRegs offset too big"); + } + + for (u32 i = 0; i < size; i += 4) { + const u32 value = mem.read32(dataPointer); + printf("GSP::GPU: Wrote %08X to GPU register %X\n", value, ioAddr); + dataPointer += 4; + ioAddr += 4; + } + mem.write32(messagePointer + 4, Result::Success); } \ No newline at end of file