diff options
Diffstat (limited to 'src/core/hle/service/nvdrv/core/nvmap.cpp')
-rw-r--r-- | src/core/hle/service/nvdrv/core/nvmap.cpp | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp index 0ca05257e..fd6c9aa0c 100644 --- a/src/core/hle/service/nvdrv/core/nvmap.cpp +++ b/src/core/hle/service/nvdrv/core/nvmap.cpp @@ -18,8 +18,6 @@ NvMap::Handle::Handle(u64 size_, Id id_) } NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress) { - std::scoped_lock lock(mutex); - // Handles cannot be allocated twice if (allocated) { return NvResult::AccessDenied; @@ -79,10 +77,11 @@ void NvMap::UnmapHandle(Handle& handle_description) { } // Free and unmap the handle from the SMMU - host1x.MemoryManager().Unmap(static_cast<GPUVAddr>(handle_description.pin_virt_address), - handle_description.aligned_size); - host1x.Allocator().Free(handle_description.pin_virt_address, - static_cast<u32>(handle_description.aligned_size)); + auto& smmu = host1x.MemoryManager(); + smmu.Unmap(static_cast<DAddr>(handle_description.pin_virt_address), + handle_description.aligned_size); + smmu.Free(handle_description.pin_virt_address, + static_cast<size_t>(handle_description.aligned_size)); handle_description.pin_virt_address = 0; } @@ -133,7 +132,32 @@ VAddr NvMap::GetHandleAddress(Handle::Id handle) { } } -u32 NvMap::PinHandle(NvMap::Handle::Id handle) { +NvResult NvMap::AllocateHandle(Handle::Id handle, Handle::Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress, size_t session_id) { + auto handle_description{GetHandle(handle)}; + if (!handle_description) [[unlikely]] { + return NvResult::BadParameter; + } + + if (handle_description->allocated) [[unlikely]] { + return NvResult::InsufficientMemory; + } + + std::scoped_lock lock(handle_description->mutex); + NvResult result = handle_description->Alloc(pFlags, pAlign, pKind, pAddress); + if (result != NvResult::Success) { + return result; + } + auto& smmu = host1x.MemoryManager(); + size_t total_size = static_cast<size_t>(handle_description->aligned_size); + handle_description->d_address = smmu.Allocate(total_size); + if (handle_description->d_address == 0) { + return NvResult::InsufficientMemory; + } + smmu.Map(handle_description->d_address, handle_description->address, total_size, session_id); + return NvResult::Success; +} + +u32 NvMap::PinHandle(NvMap::Handle::Id handle, size_t session_id) { auto handle_description{GetHandle(handle)}; if (!handle_description) [[unlikely]] { return 0; @@ -157,11 +181,10 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle) { } // If not then allocate some space and map it - u32 address{}; - auto& smmu_allocator = host1x.Allocator(); - auto& smmu_memory_manager = host1x.MemoryManager(); - while ((address = smmu_allocator.Allocate( - static_cast<u32>(handle_description->aligned_size))) == 0) { + DAddr address{}; + auto& smmu = host1x.MemoryManager(); + while ((address = smmu.AllocatePinned( + static_cast<size_t>(handle_description->aligned_size))) == 0) { // Free handles until the allocation succeeds std::scoped_lock queueLock(unmap_queue_lock); if (auto freeHandleDesc{unmap_queue.front()}) { @@ -175,9 +198,9 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle) { } } - smmu_memory_manager.Map(static_cast<GPUVAddr>(address), handle_description->address, - handle_description->aligned_size); - handle_description->pin_virt_address = address; + smmu.Map(address, handle_description->address, handle_description->aligned_size, + session_id); + handle_description->pin_virt_address = static_cast<u32>(address); } handle_description->pins++; @@ -236,6 +259,11 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna std::scoped_lock queueLock(unmap_queue_lock); UnmapHandle(*handle_description); } + if (handle_description->allocated) { + auto& smmu = host1x.MemoryManager(); + smmu.Free(handle_description->d_address, handle_description->aligned_size); + smmu.Unmap(handle_description->d_address, handle_description->aligned_size); + } handle_description->pins = 0; } |