summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar bunnei2018-05-20 23:54:50 -0400
committerGravatar GitHub2018-05-20 23:54:50 -0400
commit58857b9f46992753059aa8a6c31aff0ee14c9f99 (patch)
treed49a9d594878a2c2a948b13109e1a6e6c07ffaba /src/core
parentCorrect audio command numbers & add or rename some functions (#455) (diff)
parentGPU: Implemented the nvmap Free ioctl. (diff)
downloadyuzu-58857b9f46992753059aa8a6c31aff0ee14c9f99.tar.gz
yuzu-58857b9f46992753059aa8a6c31aff0ee14c9f99.tar.xz
yuzu-58857b9f46992753059aa8a6c31aff0ee14c9f99.zip
Merge pull request #456 from Subv/unmap_buffer
Implemented nvhost-as-gpu's UnmapBuffer and nvmap's Free ioctls.
Diffstat (limited to 'src/core')
-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/core/hle/service/nvdrv/devices/nvmap.cpp35
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h14
4 files changed, 98 insertions, 1 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/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 8d883209f..d66fb3a9c 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -30,6 +30,8 @@ u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& o
30 return IocFromId(input, output); 30 return IocFromId(input, output);
31 case IoctlCommand::Param: 31 case IoctlCommand::Param:
32 return IocParam(input, output); 32 return IocParam(input, output);
33 case IoctlCommand::Free:
34 return IocFree(input, output);
33 } 35 }
34 36
35 UNIMPLEMENTED_MSG("Unimplemented ioctl"); 37 UNIMPLEMENTED_MSG("Unimplemented ioctl");
@@ -45,6 +47,7 @@ u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
45 object->id = next_id++; 47 object->id = next_id++;
46 object->size = params.size; 48 object->size = params.size;
47 object->status = Object::Status::Created; 49 object->status = Object::Status::Created;
50 object->refcount = 1;
48 51
49 u32 handle = next_handle++; 52 u32 handle = next_handle++;
50 handles[handle] = std::move(object); 53 handles[handle] = std::move(object);
@@ -101,6 +104,8 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) {
101 [&](const auto& entry) { return entry.second->id == params.id; }); 104 [&](const auto& entry) { return entry.second->id == params.id; });
102 ASSERT(itr != handles.end()); 105 ASSERT(itr != handles.end());
103 106
107 itr->second->refcount++;
108
104 // Return the existing handle instead of creating a new one. 109 // Return the existing handle instead of creating a new one.
105 params.handle = itr->first; 110 params.handle = itr->first;
106 111
@@ -142,4 +147,34 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
142 return 0; 147 return 0;
143} 148}
144 149
150u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) {
151 enum FreeFlags {
152 Freed = 0,
153 NotFreedYet = 1,
154 };
155
156 IocFreeParams params;
157 std::memcpy(&params, input.data(), sizeof(params));
158
159 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
160
161 auto itr = handles.find(params.handle);
162 ASSERT(itr != handles.end());
163
164 itr->second->refcount--;
165
166 params.refcount = itr->second->refcount;
167 params.size = itr->second->size;
168
169 if (itr->second->refcount == 0)
170 params.flags = Freed;
171 else
172 params.flags = NotFreedYet;
173
174 handles.erase(params.handle);
175
176 std::memcpy(output.data(), &params, sizeof(params));
177 return 0;
178}
179
145} // namespace Service::Nvidia::Devices 180} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index 431eb3773..5a3044167 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -34,6 +34,7 @@ public:
34 u8 kind; 34 u8 kind;
35 VAddr addr; 35 VAddr addr;
36 Status status; 36 Status status;
37 u32 refcount;
37 }; 38 };
38 39
39 std::shared_ptr<Object> GetObject(u32 handle) const { 40 std::shared_ptr<Object> GetObject(u32 handle) const {
@@ -59,7 +60,8 @@ private:
59 FromId = 0xC0080103, 60 FromId = 0xC0080103,
60 Alloc = 0xC0200104, 61 Alloc = 0xC0200104,
61 Param = 0xC00C0109, 62 Param = 0xC00C0109,
62 GetId = 0xC008010E 63 GetId = 0xC008010E,
64 Free = 0xC0180105,
63 }; 65 };
64 66
65 struct IocCreateParams { 67 struct IocCreateParams {
@@ -102,11 +104,21 @@ private:
102 u32_le value; 104 u32_le value;
103 }; 105 };
104 106
107 struct IocFreeParams {
108 u32_le handle;
109 INSERT_PADDING_BYTES(4);
110 u64_le refcount;
111 u32_le size;
112 u32_le flags;
113 };
114 static_assert(sizeof(IocFreeParams) == 24, "IocFreeParams has wrong size");
115
105 u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output); 116 u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output);
106 u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); 117 u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output);
107 u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output); 118 u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output);
108 u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output); 119 u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output);
109 u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output); 120 u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output);
121 u32 IocFree(const std::vector<u8>& input, std::vector<u8>& output);
110}; 122};
111 123
112} // namespace Service::Nvidia::Devices 124} // namespace Service::Nvidia::Devices