Switch 2: nx2:gpu 215 DestroySparseRegion; log 214 arguments

nn::gpu::sdk names 214 CreateSparseRegion and 215 DestroySparseRegion.
215 (range in words 3-6, job slot in word 8) drops the GPU mapping and
completes its job behind the GPU; it was auto-stubbed and never signalled.
This commit is contained in:
Takoroka 2026-10-28 13:22:59 -04:00
commit 9e3f5cea40

View file

@ -259,7 +259,8 @@ public:
{102, &INx2GpuSession::SubDestroyMemory, "DestroyGpuAccessibleMemory (guessed)"},
{211, &INx2GpuSession::SubSubmitJob, "NormalMapGpuMemory4K"},
{213, &INx2GpuSession::SubUnmapJob, "NormalUnmapGpuMemory4K"},
{214, &INx2GpuSession::SubCreateGpuOnlyRegion, "CreateGpuOnlyRegion (guessed)"},
{214, &INx2GpuSession::SubCreateGpuOnlyRegion, "CreateSparseRegion"},
{215, &INx2GpuSession::SubDestroySparseRegion, "DestroySparseRegion"},
});
}
@ -460,6 +461,8 @@ private:
const u64 start = u64{w[3]} | (u64{w[4]} << 32);
const u64 last = u64{w[5]} | (u64{w[6]} << 32);
const u32 slot = w[11];
LOG_INFO(Service, "nx2:gpu 214 words {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x}",
w[1], w[2], w[3], w[4], w[5], w[6], w[7], w[8], w[9], w[10], w[11], w[12]);
if (last > start && ((last + 1 - start) % Core::Memory::YUZU_PAGESIZE) == 0) {
const u64 size = last + 1 - start;
if (const auto address = BackGpuOnlyRegion(size)) {
@ -475,6 +478,23 @@ private:
rb.Push(ResultSuccess);
}
// Sub 215 (nn::gpu::sdk::DestroySparseRegion): words 3-6 the range, word 8 the job slot, like
// 213. Drop the GPU mapping; backing memory 214 added stays allocated (its SMMU mapping is
// cached per CPU range, so its pages are not reused).
void SubDestroySparseRegion(HLERequestContext& ctx) {
const auto* w = ctx.CommandBuffer();
const u64 first = u64{w[3]} | (u64{w[4]} << 32);
const u64 last = u64{w[5]} | (u64{w[6]} << 32);
LOG_INFO(Service, "nx2:gpu 215 destroy sparse region [{:#x}, {:#x}] words {:#x} {:#x} {:#x} {:#x}",
first, last, w[1], w[2], w[7], w[8]);
if (last > first) {
Nvidia::Devices::Nx2GpuMemoryRegistry::Get().Unmap(first, last - first + 1);
}
SignalAfterGpu(w[8]);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
std::optional<u64> BackGpuOnlyRegion(u64 size) {
using Core::Memory::YUZU_PAGESIZE;
auto& kernel_core = system.Kernel();