summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp33
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h17
-rw-r--r--src/video_core/memory_manager.cpp19
-rw-r--r--src/video_core/memory_manager.h1
4 files changed, 70 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
26 return BindChannel(input, output); 26 return BindChannel(input, output);
27 case IoctlCommand::IocGetVaRegionsCommand: 27 case IoctlCommand::IocGetVaRegionsCommand:
28 return GetVARegions(input, output); 28 return GetVARegions(input, output);
29 case IoctlCommand::IocUnmapBufferCommand:
30 return UnmapBuffer(input, output);
29 } 31 }
30 32
31 if (static_cast<IoctlCommand>(command.cmd.Value()) == IoctlCommand::IocRemapCommand) 33 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
125 params.offset = gpu.memory_manager->MapBufferEx(object->addr, object->size); 127 params.offset = gpu.memory_manager->MapBufferEx(object->addr, object->size);
126 } 128 }
127 129
130 // Create a new mapping entry for this operation.
131 ASSERT_MSG(buffer_mappings.find(params.offset) == buffer_mappings.end(),
132 "Offset is already mapped");
133
134 BufferMapping mapping{};
135 mapping.nvmap_handle = params.nvmap_handle;
136 mapping.offset = params.offset;
137 mapping.size = object->size;
138
139 buffer_mappings[params.offset] = mapping;
140
141 std::memcpy(output.data(), &params, output.size());
142 return 0;
143}
144
145u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
146 IoctlUnmapBuffer params{};
147 std::memcpy(&params, input.data(), input.size());
148
149 NGLOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset);
150
151 auto& gpu = Core::System::GetInstance().GPU();
152
153 auto itr = buffer_mappings.find(params.offset);
154
155 ASSERT_MSG(itr != buffer_mappings.end(), "Tried to unmap invalid mapping");
156
157 params.offset = gpu.memory_manager->UnmapBuffer(params.offset, itr->second.size);
158
159 buffer_mappings.erase(itr->second.offset);
160
128 std::memcpy(output.data(), &params, output.size()); 161 std::memcpy(output.data(), &params, output.size());
129 return 0; 162 return 0;
130} 163}
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 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <unordered_map>
8#include <utility> 9#include <utility>
9#include <vector> 10#include <vector>
10#include "common/common_types.h" 11#include "common/common_types.h"
@@ -30,6 +31,7 @@ private:
30 IocMapBufferExCommand = 0xC0284106, 31 IocMapBufferExCommand = 0xC0284106,
31 IocBindChannelCommand = 0x40044101, 32 IocBindChannelCommand = 0x40044101,
32 IocGetVaRegionsCommand = 0xC0404108, 33 IocGetVaRegionsCommand = 0xC0404108,
34 IocUnmapBufferCommand = 0xC0084105,
33 }; 35 };
34 36
35 struct IoctlInitalizeEx { 37 struct IoctlInitalizeEx {
@@ -76,6 +78,11 @@ private:
76 }; 78 };
77 static_assert(sizeof(IoctlMapBufferEx) == 40, "IoctlMapBufferEx is incorrect size"); 79 static_assert(sizeof(IoctlMapBufferEx) == 40, "IoctlMapBufferEx is incorrect size");
78 80
81 struct IoctlUnmapBuffer {
82 u64_le offset;
83 };
84 static_assert(sizeof(IoctlUnmapBuffer) == 8, "IoctlUnmapBuffer is incorrect size");
85
79 struct IoctlBindChannel { 86 struct IoctlBindChannel {
80 u32_le fd; 87 u32_le fd;
81 }; 88 };
@@ -98,12 +105,22 @@ private:
98 static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(IoctlVaRegion) * 2, 105 static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(IoctlVaRegion) * 2,
99 "IoctlGetVaRegions is incorrect size"); 106 "IoctlGetVaRegions is incorrect size");
100 107
108 struct BufferMapping {
109 u64 offset;
110 u64 size;
111 u32 nvmap_handle;
112 };
113
114 /// Map containing the nvmap object mappings in GPU memory.
115 std::unordered_map<u64, BufferMapping> buffer_mappings;
116
101 u32 channel{}; 117 u32 channel{};
102 118
103 u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output); 119 u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output);
104 u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); 120 u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output);
105 u32 Remap(const std::vector<u8>& input, std::vector<u8>& output); 121 u32 Remap(const std::vector<u8>& input, std::vector<u8>& output);
106 u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); 122 u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
123 u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
107 u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output); 124 u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output);
108 u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); 125 u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output);
109 126
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 25984439d..5cefce9fc 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -58,6 +58,25 @@ GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size)
58 return gpu_addr; 58 return gpu_addr;
59} 59}
60 60
61GPUVAddr MemoryManager::UnmapBuffer(GPUVAddr gpu_addr, u64 size) {
62 ASSERT((gpu_addr & PAGE_MASK) == 0);
63
64 for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
65 ASSERT(PageSlot(gpu_addr + offset) != static_cast<u64>(PageStatus::Allocated) &&
66 PageSlot(gpu_addr + offset) != static_cast<u64>(PageStatus::Unmapped));
67 PageSlot(gpu_addr + offset) = static_cast<u64>(PageStatus::Unmapped);
68 }
69
70 // Delete the region mappings that are contained within the unmapped region
71 mapped_regions.erase(std::remove_if(mapped_regions.begin(), mapped_regions.end(),
72 [&](const MappedRegion& region) {
73 return region.gpu_addr <= gpu_addr &&
74 region.gpu_addr + region.size < gpu_addr + size;
75 }),
76 mapped_regions.end());
77 return gpu_addr;
78}
79
61boost::optional<GPUVAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) { 80boost::optional<GPUVAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) {
62 GPUVAddr gpu_addr = 0; 81 GPUVAddr gpu_addr = 0;
63 u64 free_space = 0; 82 u64 free_space = 0;
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 08140c83a..86765e72a 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -25,6 +25,7 @@ public:
25 GPUVAddr AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align); 25 GPUVAddr AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align);
26 GPUVAddr MapBufferEx(VAddr cpu_addr, u64 size); 26 GPUVAddr MapBufferEx(VAddr cpu_addr, u64 size);
27 GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size); 27 GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size);
28 GPUVAddr UnmapBuffer(GPUVAddr gpu_addr, u64 size);
28 boost::optional<VAddr> GpuToCpuAddress(GPUVAddr gpu_addr); 29 boost::optional<VAddr> GpuToCpuAddress(GPUVAddr gpu_addr);
29 std::vector<GPUVAddr> CpuToGpuAddress(VAddr cpu_addr) const; 30 std::vector<GPUVAddr> CpuToGpuAddress(VAddr cpu_addr) const;
30 31