summaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2023-12-25 07:32:16 +0100
committerGravatar Liam2024-01-18 21:12:30 -0500
commit0a2536a0df1f4aea406f2132d3edda0430acc9d1 (patch)
treec0ad53890581c9c7e180c5ccb3b66e3c63e3ba64 /src/core/hle
parentSMMU: Implement backing CPU page protect/unprotect (diff)
downloadyuzu-0a2536a0df1f4aea406f2132d3edda0430acc9d1.tar.gz
yuzu-0a2536a0df1f4aea406f2132d3edda0430acc9d1.tar.xz
yuzu-0a2536a0df1f4aea406f2132d3edda0430acc9d1.zip
SMMU: Initial adaptation to video_core.
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/service/hle_ipc.cpp61
-rw-r--r--src/core/hle/service/hle_ipc.h9
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.cpp64
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.h19
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp57
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h20
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp4
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.cpp6
10 files changed, 94 insertions, 156 deletions
diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp
index 3f38ceb03..9f6274c7d 100644
--- a/src/core/hle/service/hle_ipc.cpp
+++ b/src/core/hle/service/hle_ipc.cpp
@@ -22,19 +22,7 @@
22#include "core/hle/service/hle_ipc.h" 22#include "core/hle/service/hle_ipc.h"
23#include "core/hle/service/ipc_helpers.h" 23#include "core/hle/service/ipc_helpers.h"
24#include "core/memory.h" 24#include "core/memory.h"
25 25#include "core/guest_memory.h"
26namespace {
27static thread_local std::array read_buffer_data_a{
28 Common::ScratchBuffer<u8>(),
29 Common::ScratchBuffer<u8>(),
30 Common::ScratchBuffer<u8>(),
31};
32static thread_local std::array read_buffer_data_x{
33 Common::ScratchBuffer<u8>(),
34 Common::ScratchBuffer<u8>(),
35 Common::ScratchBuffer<u8>(),
36};
37} // Anonymous namespace
38 26
39namespace Service { 27namespace Service {
40 28
@@ -343,48 +331,27 @@ std::vector<u8> HLERequestContext::ReadBufferCopy(std::size_t buffer_index) cons
343} 331}
344 332
345std::span<const u8> HLERequestContext::ReadBufferA(std::size_t buffer_index) const { 333std::span<const u8> HLERequestContext::ReadBufferA(std::size_t buffer_index) const {
346 static thread_local std::array read_buffer_a{ 334 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> gm(memory, 0, 0);
347 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
348 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
349 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
350 };
351 335
352 ASSERT_OR_EXECUTE_MSG( 336 ASSERT_OR_EXECUTE_MSG(
353 BufferDescriptorA().size() > buffer_index, { return {}; }, 337 BufferDescriptorA().size() > buffer_index, { return {}; },
354 "BufferDescriptorA invalid buffer_index {}", buffer_index); 338 "BufferDescriptorA invalid buffer_index {}", buffer_index);
355 auto& read_buffer = read_buffer_a[buffer_index]; 339 return gm.Read(BufferDescriptorA()[buffer_index].Address(),
356 return read_buffer.Read(BufferDescriptorA()[buffer_index].Address(), 340 BufferDescriptorA()[buffer_index].Size(), &read_buffer_data_a[buffer_index]);
357 BufferDescriptorA()[buffer_index].Size(),
358 &read_buffer_data_a[buffer_index]);
359} 341}
360 342
361std::span<const u8> HLERequestContext::ReadBufferX(std::size_t buffer_index) const { 343std::span<const u8> HLERequestContext::ReadBufferX(std::size_t buffer_index) const {
362 static thread_local std::array read_buffer_x{ 344 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> gm(memory, 0, 0);
363 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
364 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
365 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
366 };
367 345
368 ASSERT_OR_EXECUTE_MSG( 346 ASSERT_OR_EXECUTE_MSG(
369 BufferDescriptorX().size() > buffer_index, { return {}; }, 347 BufferDescriptorX().size() > buffer_index, { return {}; },
370 "BufferDescriptorX invalid buffer_index {}", buffer_index); 348 "BufferDescriptorX invalid buffer_index {}", buffer_index);
371 auto& read_buffer = read_buffer_x[buffer_index]; 349 return gm.Read(BufferDescriptorX()[buffer_index].Address(),
372 return read_buffer.Read(BufferDescriptorX()[buffer_index].Address(), 350 BufferDescriptorX()[buffer_index].Size(), &read_buffer_data_x[buffer_index]);
373 BufferDescriptorX()[buffer_index].Size(),
374 &read_buffer_data_x[buffer_index]);
375} 351}
376 352
377std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { 353std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
378 static thread_local std::array read_buffer_a{ 354 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> gm(memory, 0, 0);
379 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
380 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
381 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
382 };
383 static thread_local std::array read_buffer_x{
384 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
385 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
386 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
387 };
388 355
389 const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && 356 const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
390 BufferDescriptorA()[buffer_index].Size()}; 357 BufferDescriptorA()[buffer_index].Size()};
@@ -401,18 +368,14 @@ std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) cons
401 ASSERT_OR_EXECUTE_MSG( 368 ASSERT_OR_EXECUTE_MSG(
402 BufferDescriptorA().size() > buffer_index, { return {}; }, 369 BufferDescriptorA().size() > buffer_index, { return {}; },
403 "BufferDescriptorA invalid buffer_index {}", buffer_index); 370 "BufferDescriptorA invalid buffer_index {}", buffer_index);
404 auto& read_buffer = read_buffer_a[buffer_index]; 371 return gm.Read(BufferDescriptorA()[buffer_index].Address(),
405 return read_buffer.Read(BufferDescriptorA()[buffer_index].Address(), 372 BufferDescriptorA()[buffer_index].Size(), &read_buffer_data_a[buffer_index]);
406 BufferDescriptorA()[buffer_index].Size(),
407 &read_buffer_data_a[buffer_index]);
408 } else { 373 } else {
409 ASSERT_OR_EXECUTE_MSG( 374 ASSERT_OR_EXECUTE_MSG(
410 BufferDescriptorX().size() > buffer_index, { return {}; }, 375 BufferDescriptorX().size() > buffer_index, { return {}; },
411 "BufferDescriptorX invalid buffer_index {}", buffer_index); 376 "BufferDescriptorX invalid buffer_index {}", buffer_index);
412 auto& read_buffer = read_buffer_x[buffer_index]; 377 return gm.Read(BufferDescriptorX()[buffer_index].Address(),
413 return read_buffer.Read(BufferDescriptorX()[buffer_index].Address(), 378 BufferDescriptorX()[buffer_index].Size(), &read_buffer_data_x[buffer_index]);
414 BufferDescriptorX()[buffer_index].Size(),
415 &read_buffer_data_x[buffer_index]);
416 } 379 }
417} 380}
418 381
diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h
index d550a11b7..8329d7265 100644
--- a/src/core/hle/service/hle_ipc.h
+++ b/src/core/hle/service/hle_ipc.h
@@ -19,8 +19,6 @@
19#include "core/hle/ipc.h" 19#include "core/hle/ipc.h"
20#include "core/hle/kernel/k_handle_table.h" 20#include "core/hle/kernel/k_handle_table.h"
21#include "core/hle/kernel/svc_common.h" 21#include "core/hle/kernel/svc_common.h"
22#include "core/hle/kernel/k_auto_object.h"
23#include "core/hle/kernel/k_handle_table.h"
24 22
25union Result; 23union Result;
26 24
@@ -377,10 +375,6 @@ public:
377 return nullptr; 375 return nullptr;
378 } 376 }
379 377
380 Kernel::KScopedAutoObject<Kernel::KAutoObject> GetObjectFromHandle(u32 handle) {
381 return GetClientHandleTable().GetObjectForIpc(handle, thread);
382 }
383
384 [[nodiscard]] std::shared_ptr<SessionRequestManager> GetManager() const { 378 [[nodiscard]] std::shared_ptr<SessionRequestManager> GetManager() const {
385 return manager.lock(); 379 return manager.lock();
386 } 380 }
@@ -432,6 +426,9 @@ private:
432 426
433 Kernel::KernelCore& kernel; 427 Kernel::KernelCore& kernel;
434 Core::Memory::Memory& memory; 428 Core::Memory::Memory& memory;
429
430 mutable std::array<Common::ScratchBuffer<u8>, 3> read_buffer_data_a{};
431 mutable std::array<Common::ScratchBuffer<u8>, 3> read_buffer_data_x{};
435}; 432};
436 433
437} // namespace Service 434} // namespace Service
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp
index fd6c9aa0c..7879c6f04 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/core/nvmap.cpp
@@ -2,6 +2,8 @@
2// SPDX-FileCopyrightText: 2022 Skyline Team and Contributors 2// SPDX-FileCopyrightText: 2022 Skyline Team and Contributors
3// SPDX-License-Identifier: GPL-3.0-or-later 3// SPDX-License-Identifier: GPL-3.0-or-later
4 4
5#include <functional>
6
5#include "common/alignment.h" 7#include "common/alignment.h"
6#include "common/assert.h" 8#include "common/assert.h"
7#include "common/logging/log.h" 9#include "common/logging/log.h"
@@ -18,6 +20,7 @@ NvMap::Handle::Handle(u64 size_, Id id_)
18} 20}
19 21
20NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress) { 22NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress) {
23 std::scoped_lock lock(mutex);
21 // Handles cannot be allocated twice 24 // Handles cannot be allocated twice
22 if (allocated) { 25 if (allocated) {
23 return NvResult::AccessDenied; 26 return NvResult::AccessDenied;
@@ -78,11 +81,9 @@ void NvMap::UnmapHandle(Handle& handle_description) {
78 81
79 // Free and unmap the handle from the SMMU 82 // Free and unmap the handle from the SMMU
80 auto& smmu = host1x.MemoryManager(); 83 auto& smmu = host1x.MemoryManager();
81 smmu.Unmap(static_cast<DAddr>(handle_description.pin_virt_address), 84 smmu.Unmap(handle_description.d_address, handle_description.aligned_size);
82 handle_description.aligned_size); 85 smmu.Free(handle_description.d_address, static_cast<size_t>(handle_description.aligned_size));
83 smmu.Free(handle_description.pin_virt_address, 86 handle_description.d_address = 0;
84 static_cast<size_t>(handle_description.aligned_size));
85 handle_description.pin_virt_address = 0;
86} 87}
87 88
88bool NvMap::TryRemoveHandle(const Handle& handle_description) { 89bool NvMap::TryRemoveHandle(const Handle& handle_description) {
@@ -123,41 +124,16 @@ std::shared_ptr<NvMap::Handle> NvMap::GetHandle(Handle::Id handle) {
123 } 124 }
124} 125}
125 126
126VAddr NvMap::GetHandleAddress(Handle::Id handle) { 127DAddr NvMap::GetHandleAddress(Handle::Id handle) {
127 std::scoped_lock lock(handles_lock); 128 std::scoped_lock lock(handles_lock);
128 try { 129 try {
129 return handles.at(handle)->address; 130 return handles.at(handle)->d_address;
130 } catch (std::out_of_range&) { 131 } catch (std::out_of_range&) {
131 return 0; 132 return 0;
132 } 133 }
133} 134}
134 135
135NvResult NvMap::AllocateHandle(Handle::Id handle, Handle::Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress, size_t session_id) { 136DAddr NvMap::PinHandle(NvMap::Handle::Id handle, size_t session_id, bool low_area_pin) {
136 auto handle_description{GetHandle(handle)};
137 if (!handle_description) [[unlikely]] {
138 return NvResult::BadParameter;
139 }
140
141 if (handle_description->allocated) [[unlikely]] {
142 return NvResult::InsufficientMemory;
143 }
144
145 std::scoped_lock lock(handle_description->mutex);
146 NvResult result = handle_description->Alloc(pFlags, pAlign, pKind, pAddress);
147 if (result != NvResult::Success) {
148 return result;
149 }
150 auto& smmu = host1x.MemoryManager();
151 size_t total_size = static_cast<size_t>(handle_description->aligned_size);
152 handle_description->d_address = smmu.Allocate(total_size);
153 if (handle_description->d_address == 0) {
154 return NvResult::InsufficientMemory;
155 }
156 smmu.Map(handle_description->d_address, handle_description->address, total_size, session_id);
157 return NvResult::Success;
158}
159
160u32 NvMap::PinHandle(NvMap::Handle::Id handle, size_t session_id) {
161 auto handle_description{GetHandle(handle)}; 137 auto handle_description{GetHandle(handle)};
162 if (!handle_description) [[unlikely]] { 138 if (!handle_description) [[unlikely]] {
163 return 0; 139 return 0;
@@ -176,35 +152,38 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle, size_t session_id) {
176 handle_description->unmap_queue_entry.reset(); 152 handle_description->unmap_queue_entry.reset();
177 153
178 handle_description->pins++; 154 handle_description->pins++;
179 return handle_description->pin_virt_address; 155 return handle_description->d_address;
180 } 156 }
181 } 157 }
182 158
159 using namespace std::placeholders;
183 // If not then allocate some space and map it 160 // If not then allocate some space and map it
184 DAddr address{}; 161 DAddr address{};
185 auto& smmu = host1x.MemoryManager(); 162 auto& smmu = host1x.MemoryManager();
186 while ((address = smmu.AllocatePinned( 163 auto allocate = std::bind(&Tegra::MaxwellDeviceMemoryManager::Allocate, &smmu, _1);
187 static_cast<size_t>(handle_description->aligned_size))) == 0) { 164 //: std::bind(&Tegra::MaxwellDeviceMemoryManager::Allocate, &smmu, _1);
165 while ((address = allocate(static_cast<size_t>(handle_description->aligned_size))) == 0) {
188 // Free handles until the allocation succeeds 166 // Free handles until the allocation succeeds
189 std::scoped_lock queueLock(unmap_queue_lock); 167 std::scoped_lock queueLock(unmap_queue_lock);
190 if (auto freeHandleDesc{unmap_queue.front()}) { 168 if (auto freeHandleDesc{unmap_queue.front()}) {
191 // Handles in the unmap queue are guaranteed not to be pinned so don't bother 169 // Handles in the unmap queue are guaranteed not to be pinned so don't bother
192 // checking if they are before unmapping 170 // checking if they are before unmapping
193 std::scoped_lock freeLock(freeHandleDesc->mutex); 171 std::scoped_lock freeLock(freeHandleDesc->mutex);
194 if (handle_description->pin_virt_address) 172 if (handle_description->d_address)
195 UnmapHandle(*freeHandleDesc); 173 UnmapHandle(*freeHandleDesc);
196 } else { 174 } else {
197 LOG_CRITICAL(Service_NVDRV, "Ran out of SMMU address space!"); 175 LOG_CRITICAL(Service_NVDRV, "Ran out of SMMU address space!");
198 } 176 }
199 } 177 }
200 178
179 handle_description->d_address = address;
180
201 smmu.Map(address, handle_description->address, handle_description->aligned_size, 181 smmu.Map(address, handle_description->address, handle_description->aligned_size,
202 session_id); 182 session_id);
203 handle_description->pin_virt_address = static_cast<u32>(address);
204 } 183 }
205 184
206 handle_description->pins++; 185 handle_description->pins++;
207 return handle_description->pin_virt_address; 186 return handle_description->d_address;
208} 187}
209 188
210void NvMap::UnpinHandle(Handle::Id handle) { 189void NvMap::UnpinHandle(Handle::Id handle) {
@@ -255,15 +234,10 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna
255 LOG_WARNING(Service_NVDRV, "User duplicate count imbalance detected!"); 234 LOG_WARNING(Service_NVDRV, "User duplicate count imbalance detected!");
256 } else if (handle_description->dupes == 0) { 235 } else if (handle_description->dupes == 0) {
257 // Force unmap the handle 236 // Force unmap the handle
258 if (handle_description->pin_virt_address) { 237 if (handle_description->d_address) {
259 std::scoped_lock queueLock(unmap_queue_lock); 238 std::scoped_lock queueLock(unmap_queue_lock);
260 UnmapHandle(*handle_description); 239 UnmapHandle(*handle_description);
261 } 240 }
262 if (handle_description->allocated) {
263 auto& smmu = host1x.MemoryManager();
264 smmu.Free(handle_description->d_address, handle_description->aligned_size);
265 smmu.Unmap(handle_description->d_address, handle_description->aligned_size);
266 }
267 241
268 handle_description->pins = 0; 242 handle_description->pins = 0;
269 } 243 }
diff --git a/src/core/hle/service/nvdrv/core/nvmap.h b/src/core/hle/service/nvdrv/core/nvmap.h
index 7c3110d91..e9e9e8b5b 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.h
+++ b/src/core/hle/service/nvdrv/core/nvmap.h
@@ -48,7 +48,7 @@ public:
48 using Id = u32; 48 using Id = u32;
49 Id id; //!< A globally unique identifier for this handle 49 Id id; //!< A globally unique identifier for this handle
50 50
51 s32 pins{}; 51 s64 pins{};
52 u32 pin_virt_address{}; 52 u32 pin_virt_address{};
53 std::optional<typename std::list<std::shared_ptr<Handle>>::iterator> unmap_queue_entry{}; 53 std::optional<typename std::list<std::shared_ptr<Handle>>::iterator> unmap_queue_entry{};
54 54
@@ -63,15 +63,14 @@ public:
63 63
64 VAddr address{}; //!< The memory location in the guest's AS that this handle corresponds to, 64 VAddr address{}; //!< The memory location in the guest's AS that this handle corresponds to,
65 //!< this can also be in the nvdrv tmem 65 //!< this can also be in the nvdrv tmem
66 DAddr d_address{}; //!< The memory location in the device's AS that this handle corresponds to,
67 //!< this can also be in the nvdrv tmem
68 bool is_shared_mem_mapped{}; //!< If this nvmap has been mapped with the MapSharedMem IPC 66 bool is_shared_mem_mapped{}; //!< If this nvmap has been mapped with the MapSharedMem IPC
69 //!< call 67 //!< call
70 68
71 u8 kind{}; //!< Used for memory compression 69 u8 kind{}; //!< Used for memory compression
72 bool allocated{}; //!< If the handle has been allocated with `Alloc` 70 bool allocated{}; //!< If the handle has been allocated with `Alloc`
73 71
74 u64 dma_map_addr{}; //! remove me after implementing pinning. 72 DAddr d_address{}; //!< The memory location in the device's AS that this handle corresponds to,
73 //!< this can also be in the nvdrv tmem
75 74
76 Handle(u64 size, Id id); 75 Handle(u64 size, Id id);
77 76
@@ -119,15 +118,7 @@ public:
119 118
120 std::shared_ptr<Handle> GetHandle(Handle::Id handle); 119 std::shared_ptr<Handle> GetHandle(Handle::Id handle);
121 120
122 VAddr GetHandleAddress(Handle::Id handle); 121 DAddr GetHandleAddress(Handle::Id handle);
123
124 /**
125 * @brief Maps a handle into the SMMU address space
126 * @note This operation is refcounted, the number of calls to this must eventually match the
127 * number of calls to `UnpinHandle`
128 * @return The SMMU virtual address that the handle has been mapped to
129 */
130 u32 PinHandle(Handle::Id handle, size_t session_id);
131 122
132 /** 123 /**
133 * @brief Maps a handle into the SMMU address space 124 * @brief Maps a handle into the SMMU address space
@@ -135,7 +126,7 @@ public:
135 * number of calls to `UnpinHandle` 126 * number of calls to `UnpinHandle`
136 * @return The SMMU virtual address that the handle has been mapped to 127 * @return The SMMU virtual address that the handle has been mapped to
137 */ 128 */
138 NvResult AllocateHandle(Handle::Id handle, Handle::Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress, size_t session_id); 129 DAddr PinHandle(Handle::Id handle, size_t session_id, bool low_area_pin);
139 130
140 /** 131 /**
141 * @brief When this has been called an equal number of times to `PinHandle` for the supplied 132 * @brief When this has been called an equal number of times to `PinHandle` for the supplied
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 0ff41c6b2..f1404b9da 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -42,7 +42,7 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat form
42 u32 height, u32 stride, android::BufferTransformFlags transform, 42 u32 height, u32 stride, android::BufferTransformFlags transform,
43 const Common::Rectangle<int>& crop_rect, 43 const Common::Rectangle<int>& crop_rect,
44 std::array<Service::Nvidia::NvFence, 4>& fences, u32 num_fences) { 44 std::array<Service::Nvidia::NvFence, 4>& fences, u32 num_fences) {
45 const VAddr addr = nvmap.GetHandleAddress(buffer_handle); 45 const DAddr addr = nvmap.GetHandleAddress(buffer_handle);
46 LOG_TRACE(Service, 46 LOG_TRACE(Service,
47 "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}", 47 "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}",
48 addr, offset, width, height, stride, format); 48 addr, offset, width, height, stride, format);
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 c92a7b2f6..8bc10eac2 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -40,15 +40,15 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> i
40 case 0x3: 40 case 0x3:
41 return WrapFixed(this, &nvhost_as_gpu::FreeSpace, input, output); 41 return WrapFixed(this, &nvhost_as_gpu::FreeSpace, input, output);
42 case 0x5: 42 case 0x5:
43 return WrapFixed(this, &nvhost_as_gpu::UnmapBuffer, input, output); 43 return WrapFixed(this, &nvhost_as_gpu::UnmapBuffer, input, output, fd);
44 case 0x6: 44 case 0x6:
45 return WrapFixed(this, &nvhost_as_gpu::MapBufferEx, input, output); 45 return WrapFixed(this, &nvhost_as_gpu::MapBufferEx, input, output, fd);
46 case 0x8: 46 case 0x8:
47 return WrapFixed(this, &nvhost_as_gpu::GetVARegions1, input, output); 47 return WrapFixed(this, &nvhost_as_gpu::GetVARegions1, input, output);
48 case 0x9: 48 case 0x9:
49 return WrapFixed(this, &nvhost_as_gpu::AllocAsEx, input, output); 49 return WrapFixed(this, &nvhost_as_gpu::AllocAsEx, input, output);
50 case 0x14: 50 case 0x14:
51 return WrapVariable(this, &nvhost_as_gpu::Remap, input, output); 51 return WrapVariable(this, &nvhost_as_gpu::Remap, input, output, fd);
52 default: 52 default:
53 break; 53 break;
54 } 54 }
@@ -86,8 +86,15 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i
86 return NvResult::NotImplemented; 86 return NvResult::NotImplemented;
87} 87}
88 88
89void nvhost_as_gpu::OnOpen(size_t session_id, DeviceFD fd) {} 89void nvhost_as_gpu::OnOpen(size_t session_id, DeviceFD fd) {
90void nvhost_as_gpu::OnClose(DeviceFD fd) {} 90 sessions[fd] = session_id;
91}
92void nvhost_as_gpu::OnClose(DeviceFD fd) {
93 auto it = sessions.find(fd);
94 if (it != sessions.end()) {
95 sessions.erase(it);
96 }
97}
91 98
92NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { 99NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
93 LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size); 100 LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size);
@@ -206,6 +213,8 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) {
206 static_cast<u32>(aligned_size >> page_size_bits)); 213 static_cast<u32>(aligned_size >> page_size_bits));
207 } 214 }
208 215
216 nvmap.UnpinHandle(mapping->handle);
217
209 // Sparse mappings shouldn't be fully unmapped, just returned to their sparse state 218 // Sparse mappings shouldn't be fully unmapped, just returned to their sparse state
210 // Only FreeSpace can unmap them fully 219 // Only FreeSpace can unmap them fully
211 if (mapping->sparse_alloc) { 220 if (mapping->sparse_alloc) {
@@ -259,7 +268,7 @@ NvResult nvhost_as_gpu::FreeSpace(IoctlFreeSpace& params) {
259 return NvResult::Success; 268 return NvResult::Success;
260} 269}
261 270
262NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) { 271NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries, DeviceFD fd) {
263 LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", entries.size()); 272 LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", entries.size());
264 273
265 if (!vm.initialised) { 274 if (!vm.initialised) {
@@ -293,19 +302,19 @@ NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) {
293 return NvResult::BadValue; 302 return NvResult::BadValue;
294 } 303 }
295 304
296 VAddr cpu_address{static_cast<VAddr>( 305 DAddr base = nvmap.PinHandle(entry.handle, sessions[fd], false);
297 handle->address + 306 DAddr device_address{static_cast<DAddr>(
298 (static_cast<u64>(entry.handle_offset_big_pages) << vm.big_page_size_bits))}; 307 base + (static_cast<u64>(entry.handle_offset_big_pages) << vm.big_page_size_bits))};
299 308
300 gmmu->Map(virtual_address, cpu_address, size, static_cast<Tegra::PTEKind>(entry.kind), 309 gmmu->Map(virtual_address, device_address, size,
301 use_big_pages); 310 static_cast<Tegra::PTEKind>(entry.kind), use_big_pages);
302 } 311 }
303 } 312 }
304 313
305 return NvResult::Success; 314 return NvResult::Success;
306} 315}
307 316
308NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { 317NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params, DeviceFD fd) {
309 LOG_DEBUG(Service_NVDRV, 318 LOG_DEBUG(Service_NVDRV,
310 "called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}" 319 "called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}"
311 ", offset={}", 320 ", offset={}",
@@ -331,9 +340,9 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
331 } 340 }
332 341
333 u64 gpu_address{static_cast<u64>(params.offset + params.buffer_offset)}; 342 u64 gpu_address{static_cast<u64>(params.offset + params.buffer_offset)};
334 VAddr cpu_address{mapping->ptr + params.buffer_offset}; 343 VAddr device_address{mapping->ptr + params.buffer_offset};
335 344
336 gmmu->Map(gpu_address, cpu_address, params.mapping_size, 345 gmmu->Map(gpu_address, device_address, params.mapping_size,
337 static_cast<Tegra::PTEKind>(params.kind), mapping->big_page); 346 static_cast<Tegra::PTEKind>(params.kind), mapping->big_page);
338 347
339 return NvResult::Success; 348 return NvResult::Success;
@@ -349,7 +358,8 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
349 return NvResult::BadValue; 358 return NvResult::BadValue;
350 } 359 }
351 360
352 VAddr cpu_address{static_cast<VAddr>(handle->address + params.buffer_offset)}; 361 DAddr device_address{static_cast<DAddr>(nvmap.PinHandle(params.handle, sessions[fd], false) +
362 params.buffer_offset)};
353 u64 size{params.mapping_size ? params.mapping_size : handle->orig_size}; 363 u64 size{params.mapping_size ? params.mapping_size : handle->orig_size};
354 364
355 bool big_page{[&]() { 365 bool big_page{[&]() {
@@ -373,15 +383,14 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
373 } 383 }
374 384
375 const bool use_big_pages = alloc->second.big_pages && big_page; 385 const bool use_big_pages = alloc->second.big_pages && big_page;
376 gmmu->Map(params.offset, cpu_address, size, static_cast<Tegra::PTEKind>(params.kind), 386 gmmu->Map(params.offset, device_address, size, static_cast<Tegra::PTEKind>(params.kind),
377 use_big_pages); 387 use_big_pages);
378 388
379 auto mapping{std::make_shared<Mapping>(cpu_address, params.offset, size, true, 389 auto mapping{std::make_shared<Mapping>(params.handle, device_address, params.offset, size,
380 use_big_pages, alloc->second.sparse)}; 390 true, use_big_pages, alloc->second.sparse)};
381 alloc->second.mappings.push_back(mapping); 391 alloc->second.mappings.push_back(mapping);
382 mapping_map[params.offset] = mapping; 392 mapping_map[params.offset] = mapping;
383 } else { 393 } else {
384
385 auto& allocator{big_page ? *vm.big_page_allocator : *vm.small_page_allocator}; 394 auto& allocator{big_page ? *vm.big_page_allocator : *vm.small_page_allocator};
386 u32 page_size{big_page ? vm.big_page_size : VM::YUZU_PAGESIZE}; 395 u32 page_size{big_page ? vm.big_page_size : VM::YUZU_PAGESIZE};
387 u32 page_size_bits{big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS}; 396 u32 page_size_bits{big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS};
@@ -394,18 +403,18 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
394 return NvResult::InsufficientMemory; 403 return NvResult::InsufficientMemory;
395 } 404 }
396 405
397 gmmu->Map(params.offset, cpu_address, Common::AlignUp(size, page_size), 406 gmmu->Map(params.offset, device_address, Common::AlignUp(size, page_size),
398 static_cast<Tegra::PTEKind>(params.kind), big_page); 407 static_cast<Tegra::PTEKind>(params.kind), big_page);
399 408
400 auto mapping{ 409 auto mapping{std::make_shared<Mapping>(params.handle, device_address, params.offset, size,
401 std::make_shared<Mapping>(cpu_address, params.offset, size, false, big_page, false)}; 410 false, big_page, false)};
402 mapping_map[params.offset] = mapping; 411 mapping_map[params.offset] = mapping;
403 } 412 }
404 413
405 return NvResult::Success; 414 return NvResult::Success;
406} 415}
407 416
408NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) { 417NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params, DeviceFD fd) {
409 LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset); 418 LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset);
410 419
411 std::scoped_lock lock(mutex); 420 std::scoped_lock lock(mutex);
@@ -433,6 +442,8 @@ NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) {
433 gmmu->Unmap(params.offset, mapping->size); 442 gmmu->Unmap(params.offset, mapping->size);
434 } 443 }
435 444
445 nvmap.UnpinHandle(mapping->handle);
446
436 mapping_map.erase(params.offset); 447 mapping_map.erase(params.offset);
437 } catch (const std::out_of_range&) { 448 } catch (const std::out_of_range&) {
438 LOG_WARNING(Service_NVDRV, "Couldn't find region to unmap at 0x{:X}", params.offset); 449 LOG_WARNING(Service_NVDRV, "Couldn't find region to unmap at 0x{:X}", params.offset);
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 0dd279f88..4b28f5078 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -141,9 +141,9 @@ private:
141 141
142 NvResult AllocAsEx(IoctlAllocAsEx& params); 142 NvResult AllocAsEx(IoctlAllocAsEx& params);
143 NvResult AllocateSpace(IoctlAllocSpace& params); 143 NvResult AllocateSpace(IoctlAllocSpace& params);
144 NvResult Remap(std::span<IoctlRemapEntry> params); 144 NvResult Remap(std::span<IoctlRemapEntry> params, DeviceFD fd);
145 NvResult MapBufferEx(IoctlMapBufferEx& params); 145 NvResult MapBufferEx(IoctlMapBufferEx& params, DeviceFD fd);
146 NvResult UnmapBuffer(IoctlUnmapBuffer& params); 146 NvResult UnmapBuffer(IoctlUnmapBuffer& params, DeviceFD fd);
147 NvResult FreeSpace(IoctlFreeSpace& params); 147 NvResult FreeSpace(IoctlFreeSpace& params);
148 NvResult BindChannel(IoctlBindChannel& params); 148 NvResult BindChannel(IoctlBindChannel& params);
149 149
@@ -159,16 +159,18 @@ private:
159 NvCore::NvMap& nvmap; 159 NvCore::NvMap& nvmap;
160 160
161 struct Mapping { 161 struct Mapping {
162 VAddr ptr; 162 NvCore::NvMap::Handle::Id handle;
163 DAddr ptr;
163 u64 offset; 164 u64 offset;
164 u64 size; 165 u64 size;
165 bool fixed; 166 bool fixed;
166 bool big_page; // Only valid if fixed == false 167 bool big_page; // Only valid if fixed == false
167 bool sparse_alloc; 168 bool sparse_alloc;
168 169
169 Mapping(VAddr ptr_, u64 offset_, u64 size_, bool fixed_, bool big_page_, bool sparse_alloc_) 170 Mapping(NvCore::NvMap::Handle::Id handle_, DAddr ptr_, u64 offset_, u64 size_, bool fixed_,
170 : ptr(ptr_), offset(offset_), size(size_), fixed(fixed_), big_page(big_page_), 171 bool big_page_, bool sparse_alloc_)
171 sparse_alloc(sparse_alloc_) {} 172 : handle(handle_), ptr(ptr_), offset(offset_), size(size_), fixed(fixed_),
173 big_page(big_page_), sparse_alloc(sparse_alloc_) {}
172 }; 174 };
173 175
174 struct Allocation { 176 struct Allocation {
@@ -212,9 +214,7 @@ private:
212 bool initialised{}; 214 bool initialised{};
213 } vm; 215 } vm;
214 std::shared_ptr<Tegra::MemoryManager> gmmu; 216 std::shared_ptr<Tegra::MemoryManager> gmmu;
215 217 std::unordered_map<DeviceFD, size_t> sessions;
216 // s32 channel{};
217 // u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE};
218}; 218};
219 219
220} // namespace Service::Nvidia::Devices 220} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 9ab0ae4d8..78bc5f3c4 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -95,6 +95,9 @@ NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, De
95 offset += SliceVectors(data, fence_thresholds, params.fence_count, offset); 95 offset += SliceVectors(data, fence_thresholds, params.fence_count, offset);
96 96
97 auto& gpu = system.GPU(); 97 auto& gpu = system.GPU();
98 //auto& device_memory = system.Host1x().MemoryManager();
99 auto* session = core.GetSession(sessions[fd]);
100
98 if (gpu.UseNvdec()) { 101 if (gpu.UseNvdec()) {
99 for (std::size_t i = 0; i < syncpt_increments.size(); i++) { 102 for (std::size_t i = 0; i < syncpt_increments.size(); i++) {
100 const SyncptIncr& syncpt_incr = syncpt_increments[i]; 103 const SyncptIncr& syncpt_incr = syncpt_increments[i];
@@ -106,7 +109,7 @@ NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, De
106 const auto object = nvmap.GetHandle(cmd_buffer.memory_id); 109 const auto object = nvmap.GetHandle(cmd_buffer.memory_id);
107 ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); 110 ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;);
108 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); 111 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count);
109 system.ApplicationMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(), 112 session->process->GetMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(),
110 cmdlist.size() * sizeof(u32)); 113 cmdlist.size() * sizeof(u32));
111 gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); 114 gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist);
112 } 115 }
@@ -136,7 +139,8 @@ NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) {
136NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries, DeviceFD fd) { 139NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries, DeviceFD fd) {
137 const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size())); 140 const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size()));
138 for (size_t i = 0; i < num_entries; i++) { 141 for (size_t i = 0; i < num_entries; i++) {
139 entries[i].map_address = nvmap.PinHandle(entries[i].map_handle, sessions[fd]); 142 DAddr pin_address = nvmap.PinHandle(entries[i].map_handle, sessions[fd], true);
143 entries[i].map_address = static_cast<u32>(pin_address);
140 } 144 }
141 145
142 return NvResult::Success; 146 return NvResult::Success;
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 2b107f009..7765ca1be 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -123,8 +123,8 @@ NvResult nvmap::IocAlloc(IocAllocParams& params, DeviceFD fd) {
123 return NvResult::InsufficientMemory; 123 return NvResult::InsufficientMemory;
124 } 124 }
125 125
126 const auto result = file.AllocateHandle(params.handle, params.flags, params.align, params.kind, 126 const auto result =
127 params.address, sessions[fd]); 127 handle_description->Alloc(params.flags, params.align, params.kind, params.address);
128 if (result != NvResult::Success) { 128 if (result != NvResult::Success) {
129 LOG_CRITICAL(Service_NVDRV, "Object failed to allocate, handle={:08X}", params.handle); 129 LOG_CRITICAL(Service_NVDRV, "Object failed to allocate, handle={:08X}", params.handle);
130 return result; 130 return result;
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
index 492ad849a..6e4825313 100644
--- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
@@ -13,8 +13,6 @@
13#include "core/hle/service/nvdrv/nvdrv.h" 13#include "core/hle/service/nvdrv/nvdrv.h"
14#include "core/hle/service/nvdrv/nvdrv_interface.h" 14#include "core/hle/service/nvdrv/nvdrv_interface.h"
15 15
16#pragma optimize("", off)
17
18namespace Service::Nvidia { 16namespace Service::Nvidia {
19 17
20void NVDRV::Open(HLERequestContext& ctx) { 18void NVDRV::Open(HLERequestContext& ctx) {
@@ -173,8 +171,8 @@ void NVDRV::Initialize(HLERequestContext& ctx) {
173 [[maybe_unused]] const auto transfer_memory_size = rp.Pop<u32>(); 171 [[maybe_unused]] const auto transfer_memory_size = rp.Pop<u32>();
174 172
175 auto& container = nvdrv->GetContainer(); 173 auto& container = nvdrv->GetContainer();
176 auto process = ctx.GetObjectFromHandle(process_handle); 174 auto process = ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle);
177 session_id = container.OpenSession(process->DynamicCast<Kernel::KProcess*>()); 175 session_id = container.OpenSession(process.GetPointerUnsafe());
178 176
179 is_initialized = true; 177 is_initialized = true;
180} 178}