aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorduck912 <350528965+Duck912@users.noreply.github.com>2026-10-31 01:46:15 -0400
committerDuck912 <350528965+Duck912@users.noreply.github.com>2026-11-01 14:58:36 -0500
commit210fb0cb690318e8ff65a042cfecb8dc345a66ab (patch)
tree0aa0f814c02e554e9e31d2afd429605fcb0e42b9
parent5f0325e2b4e72c3d10c44c7445bf73bc63e0ea32 (diff)
nvhost_ctrl_gpu: implement VSMS_MAPPING
The Switch 2 SDK asks for the {gpc, tpc} pair of every virtual SM and treats a pair left at its 0xc0c0 sentinel as failure; with the ioctl unimplemented, Fire Emblem: Fortune's Weave tore NVN down at boot (2162-0001). Fill every pair: one GPC, two SMs per TPC. Assisted-by: Claude Opus 5.5 (debugging, porting and drafting) Signed-off-by: duck912 <350528965+Duck912@users.noreply.github.com>
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp22
1 files changed, 16 insertions, 6 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index 5998940afa..c13ad4fbff 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -113,12 +113,22 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8>
case 0x6:
return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetTPCMasks3, input, output,
inline_output);
- case 0x13:
- LOG_DEBUG(Service_NVDRV, "(STUBBED) called.");
-
- // TODO (jarrodnorwell)
-
- return NvResult::NotImplemented;
+ case 0x13: {
+ // NVGPU_GPU_IOCTL_VSMS_MAPPING: an 8-byte argument struct plus a buffer of
+ // {gpc_index, tpc_index} byte pairs, one per virtual SM. The SDK treats a pair left at
+ // its 0xc0c0 sentinel as failure, so fill every pair: one GPC, two SMs per TPC.
+ if (command.raw != 0xc0084713 || input.size() != 8 || output.size() != 8 ||
+ inline_output.size() < 2) {
+ return NvResult::BadParameter;
+ }
+ std::memcpy(output.data(), input.data(), output.size());
+ for (size_t i = 0; i + 1 < inline_output.size(); i += 2) {
+ inline_output[i] = 0; // gpc_index
+ inline_output[i + 1] = static_cast<u8>(i / 4); // tpc_index
+ }
+ LOG_DEBUG(Service_NVDRV, "VSMS mapping for {} SMs", inline_output.size() / 2);
+ return NvResult::Success;
+ }
default:
break;
}