diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 33 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | 17 |
2 files changed, 50 insertions, 0 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 cb4913b07..c1eea861d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -26,6 +26,8 @@ u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vecto return BindChannel(input, output); case IoctlCommand::IocGetVaRegionsCommand: return GetVARegions(input, output); + case IoctlCommand::IocUnmapBufferCommand: + return UnmapBuffer(input, output); } if (static_cast<IoctlCommand>(command.cmd.Value()) == IoctlCommand::IocRemapCommand) @@ -125,6 +127,37 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou params.offset = gpu.memory_manager->MapBufferEx(object->addr, object->size); } + // Create a new mapping entry for this operation. + ASSERT_MSG(buffer_mappings.find(params.offset) == buffer_mappings.end(), + "Offset is already mapped"); + + BufferMapping mapping{}; + mapping.nvmap_handle = params.nvmap_handle; + mapping.offset = params.offset; + mapping.size = object->size; + + buffer_mappings[params.offset] = mapping; + + std::memcpy(output.data(), ¶ms, output.size()); + return 0; +} + +u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { + IoctlUnmapBuffer params{}; + std::memcpy(¶ms, input.data(), input.size()); + + NGLOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset); + + auto& gpu = Core::System::GetInstance().GPU(); + + auto itr = buffer_mappings.find(params.offset); + + ASSERT_MSG(itr != buffer_mappings.end(), "Tried to unmap invalid mapping"); + + params.offset = gpu.memory_manager->UnmapBuffer(params.offset, itr->second.size); + + buffer_mappings.erase(itr->second.offset); + std::memcpy(output.data(), ¶ms, output.size()); return 0; } 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 f2dd0c3b3..d4c4b4db3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -5,6 +5,7 @@ #pragma once #include <memory> +#include <unordered_map> #include <utility> #include <vector> #include "common/common_types.h" @@ -30,6 +31,7 @@ private: IocMapBufferExCommand = 0xC0284106, IocBindChannelCommand = 0x40044101, IocGetVaRegionsCommand = 0xC0404108, + IocUnmapBufferCommand = 0xC0084105, }; struct IoctlInitalizeEx { @@ -76,6 +78,11 @@ private: }; static_assert(sizeof(IoctlMapBufferEx) == 40, "IoctlMapBufferEx is incorrect size"); + struct IoctlUnmapBuffer { + u64_le offset; + }; + static_assert(sizeof(IoctlUnmapBuffer) == 8, "IoctlUnmapBuffer is incorrect size"); + struct IoctlBindChannel { u32_le fd; }; @@ -98,12 +105,22 @@ private: static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(IoctlVaRegion) * 2, "IoctlGetVaRegions is incorrect size"); + struct BufferMapping { + u64 offset; + u64 size; + u32 nvmap_handle; + }; + + /// Map containing the nvmap object mappings in GPU memory. + std::unordered_map<u64, BufferMapping> buffer_mappings; + u32 channel{}; u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output); u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); u32 Remap(const std::vector<u8>& input, std::vector<u8>& output); u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); + u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output); u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); |