diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-27 14:57:51 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-27 14:57:51 -0400 |
| commit | 58e1e35e1026d1a3eac87a82a22ac28bdbea8dc3 (patch) | |
| tree | 024699c3a7cb2360b1f2b626d52226bad46d5c6a /src | |
| parent | b04c1af7890335abc82526ba539db0a24515afb4 (diff) | |
nvdrv: Switch 2 GPU address-space layout; gpu 33/203
- AllocAsEx from Switch 2 NvRm passes flags 5, no big page size, range
[0x8000000, 0xC000000000) and split 0 (small pages only). Treat split 0
as small pages up to the end, keep a 4 GiB big-page region after it, and
give that allocator an absolute limit (Eden's length-as-limit breaks once
the split is past the region length).
- gpu TIPC 33 returns a count, 203 a kind plus a VA range used by
nn::gpu::sdk::CreateGpuAddressSpace.
- gdbrsp.py: unbreak, step, breaklr, unbreakpc, fp (frame walk), trace.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 18 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/nx2_gsv.h | 19 |
3 files changed, 35 insertions, 3 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 3c9e42f602..0733b5afaf 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -94,7 +94,7 @@ void nvhost_as_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {} void nvhost_as_gpu::OnClose(DeviceFD fd) {} NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { - LOG_DEBUG(Service_NVDRV, "called, big_page_size={:#x}", params.big_page_size); + LOG_DEBUG(Service_NVDRV, "called, flags={:#x} big_page_size={:#x} va_range_start={:#x} va_range_end={:#x} va_range_split={:#x}", params.flags, params.big_page_size, params.va_range_start, params.va_range_end, params.va_range_split); std::scoped_lock lock(mutex); @@ -125,6 +125,15 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { vm.va_range_start = params.va_range_start; vm.va_range_split = params.va_range_split; vm.va_range_end = params.va_range_end; + if (vm.va_range_split == 0) { + // Switch 2 NvRm (flags 5, no big page size) asks for small pages over the whole range + // and then reserves 4 KiB VA up to 512 GiB. Keep a small big-page region past the end + // so both allocators stay valid. + vm.va_range_split = vm.va_range_end; + vm.va_range_end += 4ULL << 30; + vm.absolute_big_page_limit = true; + LOG_WARNING(Service_NVDRV, "No VA split given; small pages up to {:#x}", vm.va_range_split); + } } const u64 max_big_page_bits = Common::Log2Ceil(vm.va_range_end); @@ -134,8 +143,11 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { vm.small_page_allocator.emplace(start_pages, end_pages); const auto start_big_pages{static_cast<u32>(vm.va_range_split >> vm.big_page_size_bits)}; - const auto end_big_pages{ - static_cast<u32>((vm.va_range_end - vm.va_range_split) >> vm.big_page_size_bits)}; + // The Switch 1 layout passes the big-page region length as the limit (so the limit stays above + // the start there); a split past the region length needs the absolute end instead. + const auto end_big_pages{static_cast<u32>( + (vm.absolute_big_page_limit ? vm.va_range_end : vm.va_range_end - vm.va_range_split) >> + vm.big_page_size_bits)}; vm.big_page_allocator.emplace(start_big_pages, end_big_pages); gmmu = std::make_unique<Tegra::MemoryManager>(system, max_big_page_bits, vm.va_range_split, vm.big_page_size_bits, VM::PAGE_SIZE_BITS); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index b13b1c9efa..9102252c96 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -218,6 +218,7 @@ private: std::optional<Allocator> small_page_allocator; //! Shared as this is also used by nvhost::GpuChannel bool initialised{}; + bool absolute_big_page_limit{}; //!< Switch 2 layout: big-page limit is va_range_end } vm; std::unique_ptr<Tegra::MemoryManager> gmmu; }; diff --git a/src/core/hle/service/nx2_gsv.h b/src/core/hle/service/nx2_gsv.h index 5494b46497..a7d9817dd2 100644 --- a/src/core/hle/service/nx2_gsv.h +++ b/src/core/hle/service/nx2_gsv.h @@ -110,6 +110,8 @@ public: {12, &INx2GpuSession::GetIdEvent, "GetIdEvent (guessed)"}, {21, &INx2GpuSession::Start, "Start (guessed)"}, {22, &INx2GpuSession::OpenSubSession, "OpenSubSession (guessed)"}, + {33, &INx2GpuSession::GetCount33, "Unknown33 (u32 count)"}, + {203, &INx2GpuSession::GetVaRange, "GetVaRange (guessed)"}, }); } @@ -153,6 +155,23 @@ private: rb.Push(ResultSuccess); } + void GetCount33(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) nx2:gpu TIPC 33 [2]={:#x}, returning 1", ctx.CommandBuffer()[2]); + TipcReplyWords(ctx, {1}); + } + + // Used by nn::gpu::sdk::CreateGpuAddressSpace: three u64s after the result, a kind (< 5, 0 = + // none) and what looks like a GPU VA range. Report kind 1, [0x10000000, +64 GiB). + void GetVaRange(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) nx2:gpu TIPC 203 [2]={:#x}", ctx.CommandBuffer()[2]); + constexpr u64 kind = 1; + constexpr u64 start = 0x10000000ULL; + constexpr u64 size = 64ULL << 30; + TipcReplyWords(ctx, {static_cast<u32>(kind), static_cast<u32>(kind >> 32), + static_cast<u32>(start), static_cast<u32>(start >> 32), + static_cast<u32>(size), static_cast<u32>(size >> 32)}); + } + void OpenSubSession(HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) nx2:gpu TIPC 22, returning a nx2:gpu-sub session"); ReturnRawSession(system, ctx, |
