diff options
Diffstat (limited to 'src')
18 files changed, 407 insertions, 428 deletions
diff --git a/src/core/hle/service/nvdrv/devices/ioctl_serialization.h b/src/core/hle/service/nvdrv/devices/ioctl_serialization.h new file mode 100644 index 000000000..b12bcd138 --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/ioctl_serialization.h | |||
| @@ -0,0 +1,159 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <span> | ||
| 7 | #include <vector> | ||
| 8 | |||
| 9 | #include "common/concepts.h" | ||
| 10 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||
| 11 | |||
| 12 | namespace Service::Nvidia::Devices { | ||
| 13 | |||
| 14 | struct IoctlOneArgTraits { | ||
| 15 | template <typename T, typename R, typename A, typename... B> | ||
| 16 | static A GetFirstArgImpl(R (T::*)(A, B...)); | ||
| 17 | }; | ||
| 18 | |||
| 19 | struct IoctlTwoArgTraits { | ||
| 20 | template <typename T, typename R, typename A, typename B, typename... C> | ||
| 21 | static A GetFirstArgImpl(R (T::*)(A, B, C...)); | ||
| 22 | |||
| 23 | template <typename T, typename R, typename A, typename B, typename... C> | ||
| 24 | static B GetSecondArgImpl(R (T::*)(A, B, C...)); | ||
| 25 | }; | ||
| 26 | |||
| 27 | struct Null {}; | ||
| 28 | |||
| 29 | // clang-format off | ||
| 30 | |||
| 31 | template <typename FixedArg, typename VarArg, typename InlInVarArg, typename InlOutVarArg, typename F> | ||
| 32 | NvResult WrapGeneric(F&& callable, std::span<const u8> input, std::span<const u8> inline_input, std::span<u8> output, std::span<u8> inline_output) { | ||
| 33 | constexpr bool HasFixedArg = !std::is_same_v<FixedArg, Null>; | ||
| 34 | constexpr bool HasVarArg = !std::is_same_v<VarArg, Null>; | ||
| 35 | constexpr bool HasInlInVarArg = !std::is_same_v<InlInVarArg, Null>; | ||
| 36 | constexpr bool HasInlOutVarArg = !std::is_same_v<InlOutVarArg, Null>; | ||
| 37 | |||
| 38 | // Declare the fixed-size input value. | ||
| 39 | FixedArg fixed{}; | ||
| 40 | size_t var_offset = 0; | ||
| 41 | |||
| 42 | if constexpr (HasFixedArg) { | ||
| 43 | // Read the fixed-size input value. | ||
| 44 | var_offset = std::min(sizeof(FixedArg), input.size()); | ||
| 45 | if (var_offset > 0) { | ||
| 46 | std::memcpy(&fixed, input.data(), var_offset); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | // Read the variable-sized inputs. | ||
| 51 | const size_t num_var_args = HasVarArg ? ((input.size() - var_offset) / sizeof(VarArg)) : 0; | ||
| 52 | std::vector<VarArg> var_args(num_var_args); | ||
| 53 | if constexpr (HasVarArg) { | ||
| 54 | if (num_var_args > 0) { | ||
| 55 | std::memcpy(var_args.data(), input.data() + var_offset, num_var_args * sizeof(VarArg)); | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | const size_t num_inl_in_var_args = HasInlInVarArg ? (inline_input.size() / sizeof(InlInVarArg)) : 0; | ||
| 60 | std::vector<InlInVarArg> inl_in_var_args(num_inl_in_var_args); | ||
| 61 | if constexpr (HasInlInVarArg) { | ||
| 62 | if (num_inl_in_var_args > 0) { | ||
| 63 | std::memcpy(inl_in_var_args.data(), inline_input.data(), num_inl_in_var_args * sizeof(InlInVarArg)); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | // Construct inline output data. | ||
| 68 | const size_t num_inl_out_var_args = HasInlOutVarArg ? (inline_output.size() / sizeof(InlOutVarArg)) : 0; | ||
| 69 | std::vector<InlOutVarArg> inl_out_var_args(num_inl_out_var_args); | ||
| 70 | |||
| 71 | // Perform the call. | ||
| 72 | NvResult result = callable(fixed, var_args, inl_in_var_args, inl_out_var_args); | ||
| 73 | |||
| 74 | // Copy outputs. | ||
| 75 | if constexpr (HasFixedArg) { | ||
| 76 | if (output.size() > 0) { | ||
| 77 | std::memcpy(output.data(), &fixed, std::min(output.size(), sizeof(FixedArg))); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | if constexpr (HasVarArg) { | ||
| 82 | if (num_var_args > 0 && output.size() > var_offset) { | ||
| 83 | const size_t max_var_size = output.size() - var_offset; | ||
| 84 | std::memcpy(output.data() + var_offset, var_args.data(), std::min(max_var_size, num_var_args * sizeof(VarArg))); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | // Copy inline outputs. | ||
| 89 | if constexpr (HasInlOutVarArg) { | ||
| 90 | if (num_inl_out_var_args > 0) { | ||
| 91 | std::memcpy(inline_output.data(), inl_out_var_args.data(), num_inl_out_var_args * sizeof(InlOutVarArg)); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | // We're done. | ||
| 96 | return result; | ||
| 97 | } | ||
| 98 | |||
| 99 | template <typename Self, typename F, typename... Rest> | ||
| 100 | NvResult WrapFixed(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) { | ||
| 101 | using FixedArg = typename std::remove_reference_t<decltype(IoctlOneArgTraits::GetFirstArgImpl(callable))>; | ||
| 102 | |||
| 103 | const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||
| 104 | return (self->*callable)(fixed, std::forward<Rest>(rest)...); | ||
| 105 | }; | ||
| 106 | |||
| 107 | return WrapGeneric<FixedArg, Null, Null, Null>(std::move(Callable), input, {}, output, {}); | ||
| 108 | } | ||
| 109 | |||
| 110 | template <typename Self, typename F, typename... Rest> | ||
| 111 | NvResult WrapFixedInlOut(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, std::span<u8> inline_output, Rest&&... rest) { | ||
| 112 | using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>; | ||
| 113 | using InlOutVarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type; | ||
| 114 | |||
| 115 | const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||
| 116 | return (self->*callable)(fixed, inl_out, std::forward<Rest>(rest)...); | ||
| 117 | }; | ||
| 118 | |||
| 119 | return WrapGeneric<FixedArg, Null, Null, InlOutVarArg>(std::move(Callable), input, {}, output, inline_output); | ||
| 120 | } | ||
| 121 | |||
| 122 | template <typename Self, typename F, typename... Rest> | ||
| 123 | NvResult WrapVariable(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) { | ||
| 124 | using VarArg = typename std::remove_reference_t<decltype(IoctlOneArgTraits::GetFirstArgImpl(callable))>::value_type; | ||
| 125 | |||
| 126 | const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||
| 127 | return (self->*callable)(var, std::forward<Rest>(rest)...); | ||
| 128 | }; | ||
| 129 | |||
| 130 | return WrapGeneric<Null, VarArg, Null, Null>(std::move(Callable), input, {}, output, {}); | ||
| 131 | } | ||
| 132 | |||
| 133 | template <typename Self, typename F, typename... Rest> | ||
| 134 | NvResult WrapFixedVariable(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) { | ||
| 135 | using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>; | ||
| 136 | using VarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type; | ||
| 137 | |||
| 138 | const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||
| 139 | return (self->*callable)(fixed, var, std::forward<Rest>(rest)...); | ||
| 140 | }; | ||
| 141 | |||
| 142 | return WrapGeneric<FixedArg, VarArg, Null, Null>(std::move(Callable), input, {}, output, {}); | ||
| 143 | } | ||
| 144 | |||
| 145 | template <typename Self, typename F, typename... Rest> | ||
| 146 | NvResult WrapFixedInlIn(Self* self, F&& callable, std::span<const u8> input, std::span<const u8> inline_input, std::span<u8> output, Rest&&... rest) { | ||
| 147 | using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>; | ||
| 148 | using InlInVarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type; | ||
| 149 | |||
| 150 | const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||
| 151 | return (self->*callable)(fixed, inl_in, std::forward<Rest>(rest)...); | ||
| 152 | }; | ||
| 153 | |||
| 154 | return WrapGeneric<FixedArg, Null, InlInVarArg, Null>(std::move(Callable), input, inline_input, output, {}); | ||
| 155 | } | ||
| 156 | |||
| 157 | // clang-format on | ||
| 158 | |||
| 159 | } // namespace Service::Nvidia::Devices | ||
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 7d7bb8687..6b3639008 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "core/hle/service/nvdrv/core/container.h" | 12 | #include "core/hle/service/nvdrv/core/container.h" |
| 13 | #include "core/hle/service/nvdrv/core/nvmap.h" | 13 | #include "core/hle/service/nvdrv/core/nvmap.h" |
| 14 | #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||
| 14 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | 15 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" |
| 15 | #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" | 16 | #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" |
| 16 | #include "core/hle/service/nvdrv/nvdrv.h" | 17 | #include "core/hle/service/nvdrv/nvdrv.h" |
| @@ -33,21 +34,21 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> i | |||
| 33 | case 'A': | 34 | case 'A': |
| 34 | switch (command.cmd) { | 35 | switch (command.cmd) { |
| 35 | case 0x1: | 36 | case 0x1: |
| 36 | return BindChannel(input, output); | 37 | return WrapFixed(this, &nvhost_as_gpu::BindChannel, input, output); |
| 37 | case 0x2: | 38 | case 0x2: |
| 38 | return AllocateSpace(input, output); | 39 | return WrapFixed(this, &nvhost_as_gpu::AllocateSpace, input, output); |
| 39 | case 0x3: | 40 | case 0x3: |
| 40 | return FreeSpace(input, output); | 41 | return WrapFixed(this, &nvhost_as_gpu::FreeSpace, input, output); |
| 41 | case 0x5: | 42 | case 0x5: |
| 42 | return UnmapBuffer(input, output); | 43 | return WrapFixed(this, &nvhost_as_gpu::UnmapBuffer, input, output); |
| 43 | case 0x6: | 44 | case 0x6: |
| 44 | return MapBufferEx(input, output); | 45 | return WrapFixed(this, &nvhost_as_gpu::MapBufferEx, input, output); |
| 45 | case 0x8: | 46 | case 0x8: |
| 46 | return GetVARegions(input, output); | 47 | return WrapFixed(this, &nvhost_as_gpu::GetVARegions1, input, output); |
| 47 | case 0x9: | 48 | case 0x9: |
| 48 | return AllocAsEx(input, output); | 49 | return WrapFixed(this, &nvhost_as_gpu::AllocAsEx, input, output); |
| 49 | case 0x14: | 50 | case 0x14: |
| 50 | return Remap(input, output); | 51 | return WrapVariable(this, &nvhost_as_gpu::Remap, input, output); |
| 51 | default: | 52 | default: |
| 52 | break; | 53 | break; |
| 53 | } | 54 | } |
| @@ -72,7 +73,8 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i | |||
| 72 | case 'A': | 73 | case 'A': |
| 73 | switch (command.cmd) { | 74 | switch (command.cmd) { |
| 74 | case 0x8: | 75 | case 0x8: |
| 75 | return GetVARegions(input, output, inline_output); | 76 | return WrapFixedInlOut(this, &nvhost_as_gpu::GetVARegions3, input, output, |
| 77 | inline_output); | ||
| 76 | default: | 78 | default: |
| 77 | break; | 79 | break; |
| 78 | } | 80 | } |
| @@ -87,10 +89,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i | |||
| 87 | void nvhost_as_gpu::OnOpen(DeviceFD fd) {} | 89 | void nvhost_as_gpu::OnOpen(DeviceFD fd) {} |
| 88 | void nvhost_as_gpu::OnClose(DeviceFD fd) {} | 90 | void nvhost_as_gpu::OnClose(DeviceFD fd) {} |
| 89 | 91 | ||
| 90 | NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> output) { | 92 | NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { |
| 91 | IoctlAllocAsEx params{}; | ||
| 92 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 93 | |||
| 94 | LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size); | 93 | LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size); |
| 95 | 94 | ||
| 96 | std::scoped_lock lock(mutex); | 95 | std::scoped_lock lock(mutex); |
| @@ -141,10 +140,7 @@ NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> outpu | |||
| 141 | return NvResult::Success; | 140 | return NvResult::Success; |
| 142 | } | 141 | } |
| 143 | 142 | ||
| 144 | NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> output) { | 143 | NvResult nvhost_as_gpu::AllocateSpace(IoctlAllocSpace& params) { |
| 145 | IoctlAllocSpace params{}; | ||
| 146 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 147 | |||
| 148 | LOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages, | 144 | LOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages, |
| 149 | params.page_size, params.flags); | 145 | params.page_size, params.flags); |
| 150 | 146 | ||
| @@ -194,7 +190,6 @@ NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> o | |||
| 194 | .big_pages = params.page_size != VM::YUZU_PAGESIZE, | 190 | .big_pages = params.page_size != VM::YUZU_PAGESIZE, |
| 195 | }; | 191 | }; |
| 196 | 192 | ||
| 197 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 198 | return NvResult::Success; | 193 | return NvResult::Success; |
| 199 | } | 194 | } |
| 200 | 195 | ||
| @@ -222,10 +217,7 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) { | |||
| 222 | mapping_map.erase(offset); | 217 | mapping_map.erase(offset); |
| 223 | } | 218 | } |
| 224 | 219 | ||
| 225 | NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> output) { | 220 | NvResult nvhost_as_gpu::FreeSpace(IoctlFreeSpace& params) { |
| 226 | IoctlFreeSpace params{}; | ||
| 227 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 228 | |||
| 229 | LOG_DEBUG(Service_NVDRV, "called, offset={:X}, pages={:X}, page_size={:X}", params.offset, | 221 | LOG_DEBUG(Service_NVDRV, "called, offset={:X}, pages={:X}, page_size={:X}", params.offset, |
| 230 | params.pages, params.page_size); | 222 | params.pages, params.page_size); |
| 231 | 223 | ||
| @@ -264,18 +256,11 @@ NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> outpu | |||
| 264 | return NvResult::BadValue; | 256 | return NvResult::BadValue; |
| 265 | } | 257 | } |
| 266 | 258 | ||
| 267 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 268 | return NvResult::Success; | 259 | return NvResult::Success; |
| 269 | } | 260 | } |
| 270 | 261 | ||
| 271 | NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) { | 262 | NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) { |
| 272 | const auto num_entries = input.size() / sizeof(IoctlRemapEntry); | 263 | LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", entries.size()); |
| 273 | |||
| 274 | LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries); | ||
| 275 | |||
| 276 | std::scoped_lock lock(mutex); | ||
| 277 | entries.resize_destructive(num_entries); | ||
| 278 | std::memcpy(entries.data(), input.data(), input.size()); | ||
| 279 | 264 | ||
| 280 | if (!vm.initialised) { | 265 | if (!vm.initialised) { |
| 281 | return NvResult::BadValue; | 266 | return NvResult::BadValue; |
| @@ -317,14 +302,10 @@ NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) { | |||
| 317 | } | 302 | } |
| 318 | } | 303 | } |
| 319 | 304 | ||
| 320 | std::memcpy(output.data(), entries.data(), output.size()); | ||
| 321 | return NvResult::Success; | 305 | return NvResult::Success; |
| 322 | } | 306 | } |
| 323 | 307 | ||
| 324 | NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> output) { | 308 | NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { |
| 325 | IoctlMapBufferEx params{}; | ||
| 326 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 327 | |||
| 328 | LOG_DEBUG(Service_NVDRV, | 309 | LOG_DEBUG(Service_NVDRV, |
| 329 | "called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}" | 310 | "called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}" |
| 330 | ", offset={}", | 311 | ", offset={}", |
| @@ -421,14 +402,10 @@ NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> out | |||
| 421 | mapping_map[params.offset] = mapping; | 402 | mapping_map[params.offset] = mapping; |
| 422 | } | 403 | } |
| 423 | 404 | ||
| 424 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 425 | return NvResult::Success; | 405 | return NvResult::Success; |
| 426 | } | 406 | } |
| 427 | 407 | ||
| 428 | NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> output) { | 408 | NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) { |
| 429 | IoctlUnmapBuffer params{}; | ||
| 430 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 431 | |||
| 432 | LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset); | 409 | LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset); |
| 433 | 410 | ||
| 434 | std::scoped_lock lock(mutex); | 411 | std::scoped_lock lock(mutex); |
| @@ -464,9 +441,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> out | |||
| 464 | return NvResult::Success; | 441 | return NvResult::Success; |
| 465 | } | 442 | } |
| 466 | 443 | ||
| 467 | NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::span<u8> output) { | 444 | NvResult nvhost_as_gpu::BindChannel(IoctlBindChannel& params) { |
| 468 | IoctlBindChannel params{}; | ||
| 469 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 470 | LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); | 445 | LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); |
| 471 | 446 | ||
| 472 | auto gpu_channel_device = module.GetDevice<nvhost_gpu>(params.fd); | 447 | auto gpu_channel_device = module.GetDevice<nvhost_gpu>(params.fd); |
| @@ -493,10 +468,7 @@ void nvhost_as_gpu::GetVARegionsImpl(IoctlGetVaRegions& params) { | |||
| 493 | }; | 468 | }; |
| 494 | } | 469 | } |
| 495 | 470 | ||
| 496 | NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output) { | 471 | NvResult nvhost_as_gpu::GetVARegions1(IoctlGetVaRegions& params) { |
| 497 | IoctlGetVaRegions params{}; | ||
| 498 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 499 | |||
| 500 | LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr, | 472 | LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr, |
| 501 | params.buf_size); | 473 | params.buf_size); |
| 502 | 474 | ||
| @@ -508,15 +480,10 @@ NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> ou | |||
| 508 | 480 | ||
| 509 | GetVARegionsImpl(params); | 481 | GetVARegionsImpl(params); |
| 510 | 482 | ||
| 511 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 512 | return NvResult::Success; | 483 | return NvResult::Success; |
| 513 | } | 484 | } |
| 514 | 485 | ||
| 515 | NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output, | 486 | NvResult nvhost_as_gpu::GetVARegions3(IoctlGetVaRegions& params, std::span<VaRegion> regions) { |
| 516 | std::span<u8> inline_output) { | ||
| 517 | IoctlGetVaRegions params{}; | ||
| 518 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 519 | |||
| 520 | LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr, | 487 | LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr, |
| 521 | params.buf_size); | 488 | params.buf_size); |
| 522 | 489 | ||
| @@ -528,9 +495,10 @@ NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> ou | |||
| 528 | 495 | ||
| 529 | GetVARegionsImpl(params); | 496 | GetVARegionsImpl(params); |
| 530 | 497 | ||
| 531 | std::memcpy(output.data(), ¶ms, output.size()); | 498 | const size_t num_regions = std::min(params.regions.size(), regions.size()); |
| 532 | std::memcpy(inline_output.data(), ¶ms.regions[0], sizeof(VaRegion)); | 499 | for (size_t i = 0; i < num_regions; i++) { |
| 533 | std::memcpy(inline_output.data() + sizeof(VaRegion), ¶ms.regions[1], sizeof(VaRegion)); | 500 | regions[i] = params.regions[i]; |
| 501 | } | ||
| 534 | 502 | ||
| 535 | return NvResult::Success; | 503 | return NvResult::Success; |
| 536 | } | 504 | } |
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 2af3e1260..932997e75 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | |||
| @@ -139,18 +139,17 @@ private: | |||
| 139 | static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2, | 139 | static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2, |
| 140 | "IoctlGetVaRegions is incorrect size"); | 140 | "IoctlGetVaRegions is incorrect size"); |
| 141 | 141 | ||
| 142 | NvResult AllocAsEx(std::span<const u8> input, std::span<u8> output); | 142 | NvResult AllocAsEx(IoctlAllocAsEx& params); |
| 143 | NvResult AllocateSpace(std::span<const u8> input, std::span<u8> output); | 143 | NvResult AllocateSpace(IoctlAllocSpace& params); |
| 144 | NvResult Remap(std::span<const u8> input, std::span<u8> output); | 144 | NvResult Remap(std::span<IoctlRemapEntry> params); |
| 145 | NvResult MapBufferEx(std::span<const u8> input, std::span<u8> output); | 145 | NvResult MapBufferEx(IoctlMapBufferEx& params); |
| 146 | NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); | 146 | NvResult UnmapBuffer(IoctlUnmapBuffer& params); |
| 147 | NvResult FreeSpace(std::span<const u8> input, std::span<u8> output); | 147 | NvResult FreeSpace(IoctlFreeSpace& params); |
| 148 | NvResult BindChannel(std::span<const u8> input, std::span<u8> output); | 148 | NvResult BindChannel(IoctlBindChannel& params); |
| 149 | 149 | ||
| 150 | void GetVARegionsImpl(IoctlGetVaRegions& params); | 150 | void GetVARegionsImpl(IoctlGetVaRegions& params); |
| 151 | NvResult GetVARegions(std::span<const u8> input, std::span<u8> output); | 151 | NvResult GetVARegions1(IoctlGetVaRegions& params); |
| 152 | NvResult GetVARegions(std::span<const u8> input, std::span<u8> output, | 152 | NvResult GetVARegions3(IoctlGetVaRegions& params, std::span<VaRegion> regions); |
| 153 | std::span<u8> inline_output); | ||
| 154 | 153 | ||
| 155 | void FreeMappingLocked(u64 offset); | 154 | void FreeMappingLocked(u64 offset); |
| 156 | 155 | ||
| @@ -213,7 +212,6 @@ private: | |||
| 213 | bool initialised{}; | 212 | bool initialised{}; |
| 214 | } vm; | 213 | } vm; |
| 215 | std::shared_ptr<Tegra::MemoryManager> gmmu; | 214 | std::shared_ptr<Tegra::MemoryManager> gmmu; |
| 216 | Common::ScratchBuffer<IoctlRemapEntry> entries; | ||
| 217 | 215 | ||
| 218 | // s32 channel{}; | 216 | // s32 channel{}; |
| 219 | // u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE}; | 217 | // u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE}; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 4d55554b4..b8dd34e24 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "core/hle/kernel/k_event.h" | 14 | #include "core/hle/kernel/k_event.h" |
| 15 | #include "core/hle/service/nvdrv/core/container.h" | 15 | #include "core/hle/service/nvdrv/core/container.h" |
| 16 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | 16 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" |
| 17 | #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||
| 17 | #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" | 18 | #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" |
| 18 | #include "video_core/gpu.h" | 19 | #include "video_core/gpu.h" |
| 19 | #include "video_core/host1x/host1x.h" | 20 | #include "video_core/host1x/host1x.h" |
| @@ -40,19 +41,19 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inp | |||
| 40 | case 0x0: | 41 | case 0x0: |
| 41 | switch (command.cmd) { | 42 | switch (command.cmd) { |
| 42 | case 0x1b: | 43 | case 0x1b: |
| 43 | return NvOsGetConfigU32(input, output); | 44 | return WrapFixed(this, &nvhost_ctrl::NvOsGetConfigU32, input, output); |
| 44 | case 0x1c: | 45 | case 0x1c: |
| 45 | return IocCtrlClearEventWait(input, output); | 46 | return WrapFixed(this, &nvhost_ctrl::IocCtrlClearEventWait, input, output); |
| 46 | case 0x1d: | 47 | case 0x1d: |
| 47 | return IocCtrlEventWait(input, output, true); | 48 | return WrapFixed(this, &nvhost_ctrl::IocCtrlEventWait, input, output, true); |
| 48 | case 0x1e: | 49 | case 0x1e: |
| 49 | return IocCtrlEventWait(input, output, false); | 50 | return WrapFixed(this, &nvhost_ctrl::IocCtrlEventWait, input, output, false); |
| 50 | case 0x1f: | 51 | case 0x1f: |
| 51 | return IocCtrlEventRegister(input, output); | 52 | return WrapFixed(this, &nvhost_ctrl::IocCtrlEventRegister, input, output); |
| 52 | case 0x20: | 53 | case 0x20: |
| 53 | return IocCtrlEventUnregister(input, output); | 54 | return WrapFixed(this, &nvhost_ctrl::IocCtrlEventUnregister, input, output); |
| 54 | case 0x21: | 55 | case 0x21: |
| 55 | return IocCtrlEventUnregisterBatch(input, output); | 56 | return WrapFixed(this, &nvhost_ctrl::IocCtrlEventUnregisterBatch, input, output); |
| 56 | } | 57 | } |
| 57 | break; | 58 | break; |
| 58 | default: | 59 | default: |
| @@ -79,25 +80,19 @@ void nvhost_ctrl::OnOpen(DeviceFD fd) {} | |||
| 79 | 80 | ||
| 80 | void nvhost_ctrl::OnClose(DeviceFD fd) {} | 81 | void nvhost_ctrl::OnClose(DeviceFD fd) {} |
| 81 | 82 | ||
| 82 | NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output) { | 83 | NvResult nvhost_ctrl::NvOsGetConfigU32(IocGetConfigParams& params) { |
| 83 | IocGetConfigParams params{}; | ||
| 84 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 85 | LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), | 84 | LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), |
| 86 | params.param_str.data()); | 85 | params.param_str.data()); |
| 87 | return NvResult::ConfigVarNotFound; // Returns error on production mode | 86 | return NvResult::ConfigVarNotFound; // Returns error on production mode |
| 88 | } | 87 | } |
| 89 | 88 | ||
| 90 | NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, | 89 | NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_allocation) { |
| 91 | bool is_allocation) { | ||
| 92 | IocCtrlEventWaitParams params{}; | ||
| 93 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 94 | LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_allocation={}", | 90 | LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_allocation={}", |
| 95 | params.fence.id, params.fence.value, params.timeout, is_allocation); | 91 | params.fence.id, params.fence.value, params.timeout, is_allocation); |
| 96 | 92 | ||
| 97 | bool must_unmark_fail = !is_allocation; | 93 | bool must_unmark_fail = !is_allocation; |
| 98 | const u32 event_id = params.value.raw; | 94 | const u32 event_id = params.value.raw; |
| 99 | SCOPE_EXIT({ | 95 | SCOPE_EXIT({ |
| 100 | std::memcpy(output.data(), ¶ms, sizeof(params)); | ||
| 101 | if (must_unmark_fail) { | 96 | if (must_unmark_fail) { |
| 102 | events[event_id].fails = 0; | 97 | events[event_id].fails = 0; |
| 103 | } | 98 | } |
| @@ -231,9 +226,7 @@ NvResult nvhost_ctrl::FreeEvent(u32 slot) { | |||
| 231 | return NvResult::Success; | 226 | return NvResult::Success; |
| 232 | } | 227 | } |
| 233 | 228 | ||
| 234 | NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output) { | 229 | NvResult nvhost_ctrl::IocCtrlEventRegister(IocCtrlEventRegisterParams& params) { |
| 235 | IocCtrlEventRegisterParams params{}; | ||
| 236 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 237 | const u32 event_id = params.user_event_id; | 230 | const u32 event_id = params.user_event_id; |
| 238 | LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); | 231 | LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); |
| 239 | if (event_id >= MaxNvEvents) { | 232 | if (event_id >= MaxNvEvents) { |
| @@ -252,9 +245,7 @@ NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span< | |||
| 252 | return NvResult::Success; | 245 | return NvResult::Success; |
| 253 | } | 246 | } |
| 254 | 247 | ||
| 255 | NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output) { | 248 | NvResult nvhost_ctrl::IocCtrlEventUnregister(IocCtrlEventUnregisterParams& params) { |
| 256 | IocCtrlEventUnregisterParams params{}; | ||
| 257 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 258 | const u32 event_id = params.user_event_id & 0x00FF; | 249 | const u32 event_id = params.user_event_id & 0x00FF; |
| 259 | LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); | 250 | LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); |
| 260 | 251 | ||
| @@ -262,9 +253,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::spa | |||
| 262 | return FreeEvent(event_id); | 253 | return FreeEvent(event_id); |
| 263 | } | 254 | } |
| 264 | 255 | ||
| 265 | NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output) { | 256 | NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(IocCtrlEventUnregisterBatchParams& params) { |
| 266 | IocCtrlEventUnregisterBatchParams params{}; | ||
| 267 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 268 | u64 event_mask = params.user_events; | 257 | u64 event_mask = params.user_events; |
| 269 | LOG_DEBUG(Service_NVDRV, " called, event_mask: {:X}", event_mask); | 258 | LOG_DEBUG(Service_NVDRV, " called, event_mask: {:X}", event_mask); |
| 270 | 259 | ||
| @@ -280,10 +269,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std | |||
| 280 | return NvResult::Success; | 269 | return NvResult::Success; |
| 281 | } | 270 | } |
| 282 | 271 | ||
| 283 | NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output) { | 272 | NvResult nvhost_ctrl::IocCtrlClearEventWait(IocCtrlEventClearParams& params) { |
| 284 | IocCtrlEventClearParams params{}; | ||
| 285 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 286 | |||
| 287 | u32 event_id = params.event_id.slot; | 273 | u32 event_id = params.event_id.slot; |
| 288 | LOG_DEBUG(Service_NVDRV, "called, event_id: {:X}", event_id); | 274 | LOG_DEBUG(Service_NVDRV, "called, event_id: {:X}", event_id); |
| 289 | 275 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 2efed4862..992124b60 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | |||
| @@ -186,12 +186,12 @@ private: | |||
| 186 | static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8, | 186 | static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8, |
| 187 | "IocCtrlEventKill is incorrect size"); | 187 | "IocCtrlEventKill is incorrect size"); |
| 188 | 188 | ||
| 189 | NvResult NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output); | 189 | NvResult NvOsGetConfigU32(IocGetConfigParams& params); |
| 190 | NvResult IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, bool is_allocation); | 190 | NvResult IocCtrlEventRegister(IocCtrlEventRegisterParams& params); |
| 191 | NvResult IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output); | 191 | NvResult IocCtrlEventUnregister(IocCtrlEventUnregisterParams& params); |
| 192 | NvResult IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output); | 192 | NvResult IocCtrlEventUnregisterBatch(IocCtrlEventUnregisterBatchParams& params); |
| 193 | NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output); | 193 | NvResult IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_allocation); |
| 194 | NvResult IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output); | 194 | NvResult IocCtrlClearEventWait(IocCtrlEventClearParams& params); |
| 195 | 195 | ||
| 196 | NvResult FreeEvent(u32 slot); | 196 | NvResult FreeEvent(u32 slot); |
| 197 | 197 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 6081d92e9..61a2df121 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 9 | #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" | 10 | #include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" |
| 10 | #include "core/hle/service/nvdrv/nvdrv.h" | 11 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 11 | 12 | ||
| @@ -27,23 +28,23 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> | |||
| 27 | case 'G': | 28 | case 'G': |
| 28 | switch (command.cmd) { | 29 | switch (command.cmd) { |
| 29 | case 0x1: | 30 | case 0x1: |
| 30 | return ZCullGetCtxSize(input, output); | 31 | return WrapFixed(this, &nvhost_ctrl_gpu::ZCullGetCtxSize, input, output); |
| 31 | case 0x2: | 32 | case 0x2: |
| 32 | return ZCullGetInfo(input, output); | 33 | return WrapFixed(this, &nvhost_ctrl_gpu::ZCullGetInfo, input, output); |
| 33 | case 0x3: | 34 | case 0x3: |
| 34 | return ZBCSetTable(input, output); | 35 | return WrapFixed(this, &nvhost_ctrl_gpu::ZBCSetTable, input, output); |
| 35 | case 0x4: | 36 | case 0x4: |
| 36 | return ZBCQueryTable(input, output); | 37 | return WrapFixed(this, &nvhost_ctrl_gpu::ZBCQueryTable, input, output); |
| 37 | case 0x5: | 38 | case 0x5: |
| 38 | return GetCharacteristics(input, output); | 39 | return WrapFixed(this, &nvhost_ctrl_gpu::GetCharacteristics1, input, output); |
| 39 | case 0x6: | 40 | case 0x6: |
| 40 | return GetTPCMasks(input, output); | 41 | return WrapFixed(this, &nvhost_ctrl_gpu::GetTPCMasks1, input, output); |
| 41 | case 0x7: | 42 | case 0x7: |
| 42 | return FlushL2(input, output); | 43 | return WrapFixed(this, &nvhost_ctrl_gpu::FlushL2, input, output); |
| 43 | case 0x14: | 44 | case 0x14: |
| 44 | return GetActiveSlotMask(input, output); | 45 | return WrapFixed(this, &nvhost_ctrl_gpu::GetActiveSlotMask, input, output); |
| 45 | case 0x1c: | 46 | case 0x1c: |
| 46 | return GetGpuTime(input, output); | 47 | return WrapFixed(this, &nvhost_ctrl_gpu::GetGpuTime, input, output); |
| 47 | default: | 48 | default: |
| 48 | break; | 49 | break; |
| 49 | } | 50 | } |
| @@ -65,9 +66,11 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> | |||
| 65 | case 'G': | 66 | case 'G': |
| 66 | switch (command.cmd) { | 67 | switch (command.cmd) { |
| 67 | case 0x5: | 68 | case 0x5: |
| 68 | return GetCharacteristics(input, output, inline_output); | 69 | return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetCharacteristics3, input, output, |
| 70 | inline_output); | ||
| 69 | case 0x6: | 71 | case 0x6: |
| 70 | return GetTPCMasks(input, output, inline_output); | 72 | return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetTPCMasks3, input, output, |
| 73 | inline_output); | ||
| 71 | default: | 74 | default: |
| 72 | break; | 75 | break; |
| 73 | } | 76 | } |
| @@ -82,10 +85,8 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> | |||
| 82 | void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {} | 85 | void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {} |
| 83 | void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} | 86 | void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} |
| 84 | 87 | ||
| 85 | NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output) { | 88 | NvResult nvhost_ctrl_gpu::GetCharacteristics1(IoctlCharacteristics& params) { |
| 86 | LOG_DEBUG(Service_NVDRV, "called"); | 89 | LOG_DEBUG(Service_NVDRV, "called"); |
| 87 | IoctlCharacteristics params{}; | ||
| 88 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 89 | params.gc.arch = 0x120; | 90 | params.gc.arch = 0x120; |
| 90 | params.gc.impl = 0xb; | 91 | params.gc.impl = 0xb; |
| 91 | params.gc.rev = 0xa1; | 92 | params.gc.rev = 0xa1; |
| @@ -123,15 +124,13 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::spa | |||
| 123 | params.gc.gr_compbit_store_base_hw = 0x0; | 124 | params.gc.gr_compbit_store_base_hw = 0x0; |
| 124 | params.gpu_characteristics_buf_size = 0xA0; | 125 | params.gpu_characteristics_buf_size = 0xA0; |
| 125 | params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) | 126 | params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) |
| 126 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 127 | return NvResult::Success; | 127 | return NvResult::Success; |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output, | 130 | NvResult nvhost_ctrl_gpu::GetCharacteristics3( |
| 131 | std::span<u8> inline_output) { | 131 | IoctlCharacteristics& params, std::span<IoctlGpuCharacteristics> gpu_characteristics) { |
| 132 | LOG_DEBUG(Service_NVDRV, "called"); | 132 | LOG_DEBUG(Service_NVDRV, "called"); |
| 133 | IoctlCharacteristics params{}; | 133 | |
| 134 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 135 | params.gc.arch = 0x120; | 134 | params.gc.arch = 0x120; |
| 136 | params.gc.impl = 0xb; | 135 | params.gc.impl = 0xb; |
| 137 | params.gc.rev = 0xa1; | 136 | params.gc.rev = 0xa1; |
| @@ -169,70 +168,47 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::spa | |||
| 169 | params.gc.gr_compbit_store_base_hw = 0x0; | 168 | params.gc.gr_compbit_store_base_hw = 0x0; |
| 170 | params.gpu_characteristics_buf_size = 0xA0; | 169 | params.gpu_characteristics_buf_size = 0xA0; |
| 171 | params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) | 170 | params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) |
| 172 | 171 | if (!gpu_characteristics.empty()) { | |
| 173 | std::memcpy(output.data(), ¶ms, output.size()); | 172 | gpu_characteristics.front() = params.gc; |
| 174 | std::memcpy(inline_output.data(), ¶ms.gc, inline_output.size()); | 173 | } |
| 175 | return NvResult::Success; | 174 | return NvResult::Success; |
| 176 | } | 175 | } |
| 177 | 176 | ||
| 178 | NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output) { | 177 | NvResult nvhost_ctrl_gpu::GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params) { |
| 179 | IoctlGpuGetTpcMasksArgs params{}; | ||
| 180 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 181 | LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); | 178 | LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); |
| 182 | if (params.mask_buffer_size != 0) { | 179 | if (params.mask_buffer_size != 0) { |
| 183 | params.tcp_mask = 3; | 180 | params.tcp_mask = 3; |
| 184 | } | 181 | } |
| 185 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 186 | return NvResult::Success; | 182 | return NvResult::Success; |
| 187 | } | 183 | } |
| 188 | 184 | ||
| 189 | NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output, | 185 | NvResult nvhost_ctrl_gpu::GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask) { |
| 190 | std::span<u8> inline_output) { | ||
| 191 | IoctlGpuGetTpcMasksArgs params{}; | ||
| 192 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 193 | LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); | 186 | LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); |
| 194 | if (params.mask_buffer_size != 0) { | 187 | if (params.mask_buffer_size != 0) { |
| 195 | params.tcp_mask = 3; | 188 | params.tcp_mask = 3; |
| 196 | } | 189 | } |
| 197 | std::memcpy(output.data(), ¶ms, output.size()); | 190 | if (!tpc_mask.empty()) { |
| 198 | std::memcpy(inline_output.data(), ¶ms.tcp_mask, inline_output.size()); | 191 | tpc_mask.front() = params.tcp_mask; |
| 192 | } | ||
| 199 | return NvResult::Success; | 193 | return NvResult::Success; |
| 200 | } | 194 | } |
| 201 | 195 | ||
| 202 | NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::span<u8> output) { | 196 | NvResult nvhost_ctrl_gpu::GetActiveSlotMask(IoctlActiveSlotMask& params) { |
| 203 | LOG_DEBUG(Service_NVDRV, "called"); | 197 | LOG_DEBUG(Service_NVDRV, "called"); |
| 204 | 198 | ||
| 205 | IoctlActiveSlotMask params{}; | ||
| 206 | if (input.size() > 0) { | ||
| 207 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 208 | } | ||
| 209 | params.slot = 0x07; | 199 | params.slot = 0x07; |
| 210 | params.mask = 0x01; | 200 | params.mask = 0x01; |
| 211 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 212 | return NvResult::Success; | 201 | return NvResult::Success; |
| 213 | } | 202 | } |
| 214 | 203 | ||
| 215 | NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output) { | 204 | NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(IoctlZcullGetCtxSize& params) { |
| 216 | LOG_DEBUG(Service_NVDRV, "called"); | 205 | LOG_DEBUG(Service_NVDRV, "called"); |
| 217 | |||
| 218 | IoctlZcullGetCtxSize params{}; | ||
| 219 | if (input.size() > 0) { | ||
| 220 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 221 | } | ||
| 222 | params.size = 0x1; | 206 | params.size = 0x1; |
| 223 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 224 | return NvResult::Success; | 207 | return NvResult::Success; |
| 225 | } | 208 | } |
| 226 | 209 | ||
| 227 | NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8> output) { | 210 | NvResult nvhost_ctrl_gpu::ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params) { |
| 228 | LOG_DEBUG(Service_NVDRV, "called"); | 211 | LOG_DEBUG(Service_NVDRV, "called"); |
| 229 | |||
| 230 | IoctlNvgpuGpuZcullGetInfoArgs params{}; | ||
| 231 | |||
| 232 | if (input.size() > 0) { | ||
| 233 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 234 | } | ||
| 235 | |||
| 236 | params.width_align_pixels = 0x20; | 212 | params.width_align_pixels = 0x20; |
| 237 | params.height_align_pixels = 0x20; | 213 | params.height_align_pixels = 0x20; |
| 238 | params.pixel_squares_by_aliquots = 0x400; | 214 | params.pixel_squares_by_aliquots = 0x400; |
| @@ -243,53 +219,28 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8> | |||
| 243 | params.subregion_width_align_pixels = 0x20; | 219 | params.subregion_width_align_pixels = 0x20; |
| 244 | params.subregion_height_align_pixels = 0x40; | 220 | params.subregion_height_align_pixels = 0x40; |
| 245 | params.subregion_count = 0x10; | 221 | params.subregion_count = 0x10; |
| 246 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 247 | return NvResult::Success; | 222 | return NvResult::Success; |
| 248 | } | 223 | } |
| 249 | 224 | ||
| 250 | NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::span<u8> output) { | 225 | NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) { |
| 251 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 226 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 252 | |||
| 253 | IoctlZbcSetTable params{}; | ||
| 254 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 255 | // TODO(ogniK): What does this even actually do? | 227 | // TODO(ogniK): What does this even actually do? |
| 256 | |||
| 257 | // Prevent null pointer being passed as arg 1 | ||
| 258 | if (output.empty()) { | ||
| 259 | LOG_WARNING(Service_NVDRV, "Avoiding passing null pointer to memcpy"); | ||
| 260 | } else { | ||
| 261 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 262 | } | ||
| 263 | return NvResult::Success; | 228 | return NvResult::Success; |
| 264 | } | 229 | } |
| 265 | 230 | ||
| 266 | NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::span<u8> output) { | 231 | NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) { |
| 267 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 232 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 268 | |||
| 269 | IoctlZbcQueryTable params{}; | ||
| 270 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 271 | // TODO : To implement properly | ||
| 272 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 273 | return NvResult::Success; | 233 | return NvResult::Success; |
| 274 | } | 234 | } |
| 275 | 235 | ||
| 276 | NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::span<u8> output) { | 236 | NvResult nvhost_ctrl_gpu::FlushL2(IoctlFlushL2& params) { |
| 277 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 237 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 278 | |||
| 279 | IoctlFlushL2 params{}; | ||
| 280 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 281 | // TODO : To implement properly | ||
| 282 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 283 | return NvResult::Success; | 238 | return NvResult::Success; |
| 284 | } | 239 | } |
| 285 | 240 | ||
| 286 | NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::span<u8> output) { | 241 | NvResult nvhost_ctrl_gpu::GetGpuTime(IoctlGetGpuTime& params) { |
| 287 | LOG_DEBUG(Service_NVDRV, "called"); | 242 | LOG_DEBUG(Service_NVDRV, "called"); |
| 288 | |||
| 289 | IoctlGetGpuTime params{}; | ||
| 290 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 291 | params.gpu_time = static_cast<u64_le>(system.CoreTiming().GetGlobalTimeNs().count()); | 243 | params.gpu_time = static_cast<u64_le>(system.CoreTiming().GetGlobalTimeNs().count()); |
| 292 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 293 | return NvResult::Success; | 244 | return NvResult::Success; |
| 294 | } | 245 | } |
| 295 | 246 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index 97995551c..d170299bd 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h | |||
| @@ -151,21 +151,20 @@ private: | |||
| 151 | }; | 151 | }; |
| 152 | static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); | 152 | static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); |
| 153 | 153 | ||
| 154 | NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output); | 154 | NvResult GetCharacteristics1(IoctlCharacteristics& params); |
| 155 | NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output, | 155 | NvResult GetCharacteristics3(IoctlCharacteristics& params, |
| 156 | std::span<u8> inline_output); | 156 | std::span<IoctlGpuCharacteristics> gpu_characteristics); |
| 157 | 157 | ||
| 158 | NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output); | 158 | NvResult GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params); |
| 159 | NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output, | 159 | NvResult GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask); |
| 160 | std::span<u8> inline_output); | 160 | |
| 161 | 161 | NvResult GetActiveSlotMask(IoctlActiveSlotMask& params); | |
| 162 | NvResult GetActiveSlotMask(std::span<const u8> input, std::span<u8> output); | 162 | NvResult ZCullGetCtxSize(IoctlZcullGetCtxSize& params); |
| 163 | NvResult ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output); | 163 | NvResult ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params); |
| 164 | NvResult ZCullGetInfo(std::span<const u8> input, std::span<u8> output); | 164 | NvResult ZBCSetTable(IoctlZbcSetTable& params); |
| 165 | NvResult ZBCSetTable(std::span<const u8> input, std::span<u8> output); | 165 | NvResult ZBCQueryTable(IoctlZbcQueryTable& params); |
| 166 | NvResult ZBCQueryTable(std::span<const u8> input, std::span<u8> output); | 166 | NvResult FlushL2(IoctlFlushL2& params); |
| 167 | NvResult FlushL2(std::span<const u8> input, std::span<u8> output); | 167 | NvResult GetGpuTime(IoctlGetGpuTime& params); |
| 168 | NvResult GetGpuTime(std::span<const u8> input, std::span<u8> output); | ||
| 169 | 168 | ||
| 170 | EventInterface& events_interface; | 169 | EventInterface& events_interface; |
| 171 | 170 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 46a25fcab..b0395c2f0 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "core/hle/service/nvdrv/core/container.h" | 8 | #include "core/hle/service/nvdrv/core/container.h" |
| 9 | #include "core/hle/service/nvdrv/core/nvmap.h" | 9 | #include "core/hle/service/nvdrv/core/nvmap.h" |
| 10 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | 10 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" |
| 11 | #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||
| 11 | #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" | 12 | #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" |
| 12 | #include "core/hle/service/nvdrv/nvdrv.h" | 13 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 13 | #include "core/memory.h" | 14 | #include "core/memory.h" |
| @@ -52,7 +53,7 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 52 | case 0x0: | 53 | case 0x0: |
| 53 | switch (command.cmd) { | 54 | switch (command.cmd) { |
| 54 | case 0x3: | 55 | case 0x3: |
| 55 | return GetWaitbase(input, output); | 56 | return WrapFixed(this, &nvhost_gpu::GetWaitbase, input, output); |
| 56 | default: | 57 | default: |
| 57 | break; | 58 | break; |
| 58 | } | 59 | } |
| @@ -60,25 +61,25 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 60 | case 'H': | 61 | case 'H': |
| 61 | switch (command.cmd) { | 62 | switch (command.cmd) { |
| 62 | case 0x1: | 63 | case 0x1: |
| 63 | return SetNVMAPfd(input, output); | 64 | return WrapFixed(this, &nvhost_gpu::SetNVMAPfd, input, output); |
| 64 | case 0x3: | 65 | case 0x3: |
| 65 | return ChannelSetTimeout(input, output); | 66 | return WrapFixed(this, &nvhost_gpu::ChannelSetTimeout, input, output); |
| 66 | case 0x8: | 67 | case 0x8: |
| 67 | return SubmitGPFIFOBase(input, output, false); | 68 | return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, false); |
| 68 | case 0x9: | 69 | case 0x9: |
| 69 | return AllocateObjectContext(input, output); | 70 | return WrapFixed(this, &nvhost_gpu::AllocateObjectContext, input, output); |
| 70 | case 0xb: | 71 | case 0xb: |
| 71 | return ZCullBind(input, output); | 72 | return WrapFixed(this, &nvhost_gpu::ZCullBind, input, output); |
| 72 | case 0xc: | 73 | case 0xc: |
| 73 | return SetErrorNotifier(input, output); | 74 | return WrapFixed(this, &nvhost_gpu::SetErrorNotifier, input, output); |
| 74 | case 0xd: | 75 | case 0xd: |
| 75 | return SetChannelPriority(input, output); | 76 | return WrapFixed(this, &nvhost_gpu::SetChannelPriority, input, output); |
| 76 | case 0x1a: | 77 | case 0x1a: |
| 77 | return AllocGPFIFOEx2(input, output); | 78 | return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx2, input, output); |
| 78 | case 0x1b: | 79 | case 0x1b: |
| 79 | return SubmitGPFIFOBase(input, output, true); | 80 | return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, true); |
| 80 | case 0x1d: | 81 | case 0x1d: |
| 81 | return ChannelSetTimeslice(input, output); | 82 | return WrapFixed(this, &nvhost_gpu::ChannelSetTimeslice, input, output); |
| 82 | default: | 83 | default: |
| 83 | break; | 84 | break; |
| 84 | } | 85 | } |
| @@ -86,9 +87,9 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 86 | case 'G': | 87 | case 'G': |
| 87 | switch (command.cmd) { | 88 | switch (command.cmd) { |
| 88 | case 0x14: | 89 | case 0x14: |
| 89 | return SetClientData(input, output); | 90 | return WrapFixed(this, &nvhost_gpu::SetClientData, input, output); |
| 90 | case 0x15: | 91 | case 0x15: |
| 91 | return GetClientData(input, output); | 92 | return WrapFixed(this, &nvhost_gpu::GetClientData, input, output); |
| 92 | default: | 93 | default: |
| 93 | break; | 94 | break; |
| 94 | } | 95 | } |
| @@ -104,7 +105,8 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 104 | case 'H': | 105 | case 'H': |
| 105 | switch (command.cmd) { | 106 | switch (command.cmd) { |
| 106 | case 0x1b: | 107 | case 0x1b: |
| 107 | return SubmitGPFIFOBase(input, inline_input, output); | 108 | return WrapFixedInlIn(this, &nvhost_gpu::SubmitGPFIFOBase2, input, inline_input, |
| 109 | output); | ||
| 108 | } | 110 | } |
| 109 | break; | 111 | break; |
| 110 | } | 112 | } |
| @@ -121,63 +123,45 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 121 | void nvhost_gpu::OnOpen(DeviceFD fd) {} | 123 | void nvhost_gpu::OnOpen(DeviceFD fd) {} |
| 122 | void nvhost_gpu::OnClose(DeviceFD fd) {} | 124 | void nvhost_gpu::OnClose(DeviceFD fd) {} |
| 123 | 125 | ||
| 124 | NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) { | 126 | NvResult nvhost_gpu::SetNVMAPfd(IoctlSetNvmapFD& params) { |
| 125 | IoctlSetNvmapFD params{}; | ||
| 126 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 127 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | 127 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); |
| 128 | 128 | ||
| 129 | nvmap_fd = params.nvmap_fd; | 129 | nvmap_fd = params.nvmap_fd; |
| 130 | return NvResult::Success; | 130 | return NvResult::Success; |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::span<u8> output) { | 133 | NvResult nvhost_gpu::SetClientData(IoctlClientData& params) { |
| 134 | LOG_DEBUG(Service_NVDRV, "called"); | 134 | LOG_DEBUG(Service_NVDRV, "called"); |
| 135 | |||
| 136 | IoctlClientData params{}; | ||
| 137 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 138 | user_data = params.data; | 135 | user_data = params.data; |
| 139 | return NvResult::Success; | 136 | return NvResult::Success; |
| 140 | } | 137 | } |
| 141 | 138 | ||
| 142 | NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::span<u8> output) { | 139 | NvResult nvhost_gpu::GetClientData(IoctlClientData& params) { |
| 143 | LOG_DEBUG(Service_NVDRV, "called"); | 140 | LOG_DEBUG(Service_NVDRV, "called"); |
| 144 | |||
| 145 | IoctlClientData params{}; | ||
| 146 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 147 | params.data = user_data; | 141 | params.data = user_data; |
| 148 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 149 | return NvResult::Success; | 142 | return NvResult::Success; |
| 150 | } | 143 | } |
| 151 | 144 | ||
| 152 | NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::span<u8> output) { | 145 | NvResult nvhost_gpu::ZCullBind(IoctlZCullBind& params) { |
| 153 | std::memcpy(&zcull_params, input.data(), input.size()); | 146 | zcull_params = params; |
| 154 | LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va, | 147 | LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va, |
| 155 | zcull_params.mode); | 148 | zcull_params.mode); |
| 156 | |||
| 157 | std::memcpy(output.data(), &zcull_params, output.size()); | ||
| 158 | return NvResult::Success; | 149 | return NvResult::Success; |
| 159 | } | 150 | } |
| 160 | 151 | ||
| 161 | NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::span<u8> output) { | 152 | NvResult nvhost_gpu::SetErrorNotifier(IoctlSetErrorNotifier& params) { |
| 162 | IoctlSetErrorNotifier params{}; | ||
| 163 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 164 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, | 153 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, |
| 165 | params.size, params.mem); | 154 | params.size, params.mem); |
| 166 | |||
| 167 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 168 | return NvResult::Success; | 155 | return NvResult::Success; |
| 169 | } | 156 | } |
| 170 | 157 | ||
| 171 | NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::span<u8> output) { | 158 | NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) { |
| 172 | std::memcpy(&channel_priority, input.data(), input.size()); | 159 | channel_priority = params.priority; |
| 173 | LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); | 160 | LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); |
| 174 | |||
| 175 | return NvResult::Success; | 161 | return NvResult::Success; |
| 176 | } | 162 | } |
| 177 | 163 | ||
| 178 | NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output) { | 164 | NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params) { |
| 179 | IoctlAllocGpfifoEx2 params{}; | ||
| 180 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 181 | LOG_WARNING(Service_NVDRV, | 165 | LOG_WARNING(Service_NVDRV, |
| 182 | "(STUBBED) called, num_entries={:X}, flags={:X}, unk0={:X}, " | 166 | "(STUBBED) called, num_entries={:X}, flags={:X}, unk0={:X}, " |
| 183 | "unk1={:X}, unk2={:X}, unk3={:X}", | 167 | "unk1={:X}, unk2={:X}, unk3={:X}", |
| @@ -193,18 +177,14 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> out | |||
| 193 | 177 | ||
| 194 | params.fence_out = syncpoint_manager.GetSyncpointFence(channel_syncpoint); | 178 | params.fence_out = syncpoint_manager.GetSyncpointFence(channel_syncpoint); |
| 195 | 179 | ||
| 196 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 197 | return NvResult::Success; | 180 | return NvResult::Success; |
| 198 | } | 181 | } |
| 199 | 182 | ||
| 200 | NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::span<u8> output) { | 183 | NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) { |
| 201 | IoctlAllocObjCtx params{}; | ||
| 202 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 203 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, | 184 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, |
| 204 | params.flags); | 185 | params.flags); |
| 205 | 186 | ||
| 206 | params.obj_id = 0x0; | 187 | params.obj_id = 0x0; |
| 207 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 208 | return NvResult::Success; | 188 | return NvResult::Success; |
| 209 | } | 189 | } |
| 210 | 190 | ||
| @@ -248,8 +228,7 @@ static boost::container::small_vector<Tegra::CommandHeader, 512> BuildIncrementW | |||
| 248 | return result; | 228 | return result; |
| 249 | } | 229 | } |
| 250 | 230 | ||
| 251 | NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output, | 231 | NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries) { |
| 252 | Tegra::CommandList&& entries) { | ||
| 253 | LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address, | 232 | LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address, |
| 254 | params.num_entries, params.flags.raw); | 233 | params.num_entries, params.flags.raw); |
| 255 | 234 | ||
| @@ -290,65 +269,55 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> o | |||
| 290 | 269 | ||
| 291 | flags.raw = 0; | 270 | flags.raw = 0; |
| 292 | 271 | ||
| 293 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmitGpfifo)); | ||
| 294 | return NvResult::Success; | 272 | return NvResult::Success; |
| 295 | } | 273 | } |
| 296 | 274 | ||
| 297 | NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output, | 275 | NvResult nvhost_gpu::SubmitGPFIFOBase1(IoctlSubmitGpfifo& params, |
| 298 | bool kickoff) { | 276 | std::span<Tegra::CommandListHeader> commands, bool kickoff) { |
| 299 | if (input.size() < sizeof(IoctlSubmitGpfifo)) { | 277 | if (params.num_entries > commands.size()) { |
| 300 | UNIMPLEMENTED(); | 278 | UNIMPLEMENTED(); |
| 301 | return NvResult::InvalidSize; | 279 | return NvResult::InvalidSize; |
| 302 | } | 280 | } |
| 303 | IoctlSubmitGpfifo params{}; | ||
| 304 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | ||
| 305 | Tegra::CommandList entries(params.num_entries); | ||
| 306 | 281 | ||
| 282 | Tegra::CommandList entries(params.num_entries); | ||
| 307 | if (kickoff) { | 283 | if (kickoff) { |
| 308 | system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(), | 284 | system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(), |
| 309 | params.num_entries * sizeof(Tegra::CommandListHeader)); | 285 | params.num_entries * sizeof(Tegra::CommandListHeader)); |
| 310 | } else { | 286 | } else { |
| 311 | std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], | 287 | std::memcpy(entries.command_lists.data(), commands.data(), |
| 312 | params.num_entries * sizeof(Tegra::CommandListHeader)); | 288 | params.num_entries * sizeof(Tegra::CommandListHeader)); |
| 313 | } | 289 | } |
| 314 | 290 | ||
| 315 | return SubmitGPFIFOImpl(params, output, std::move(entries)); | 291 | return SubmitGPFIFOImpl(params, std::move(entries)); |
| 316 | } | 292 | } |
| 317 | 293 | ||
| 318 | NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, | 294 | NvResult nvhost_gpu::SubmitGPFIFOBase2(IoctlSubmitGpfifo& params, |
| 319 | std::span<u8> output) { | 295 | std::span<const Tegra::CommandListHeader> commands) { |
| 320 | if (input.size() < sizeof(IoctlSubmitGpfifo)) { | 296 | if (params.num_entries > commands.size()) { |
| 321 | UNIMPLEMENTED(); | 297 | UNIMPLEMENTED(); |
| 322 | return NvResult::InvalidSize; | 298 | return NvResult::InvalidSize; |
| 323 | } | 299 | } |
| 324 | IoctlSubmitGpfifo params{}; | 300 | |
| 325 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | ||
| 326 | Tegra::CommandList entries(params.num_entries); | 301 | Tegra::CommandList entries(params.num_entries); |
| 327 | std::memcpy(entries.command_lists.data(), input_inline.data(), input_inline.size()); | 302 | std::memcpy(entries.command_lists.data(), commands.data(), |
| 328 | return SubmitGPFIFOImpl(params, output, std::move(entries)); | 303 | params.num_entries * sizeof(Tegra::CommandListHeader)); |
| 304 | return SubmitGPFIFOImpl(params, std::move(entries)); | ||
| 329 | } | 305 | } |
| 330 | 306 | ||
| 331 | NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::span<u8> output) { | 307 | NvResult nvhost_gpu::GetWaitbase(IoctlGetWaitbase& params) { |
| 332 | IoctlGetWaitbase params{}; | ||
| 333 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); | ||
| 334 | LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); | 308 | LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); |
| 335 | 309 | ||
| 336 | params.value = 0; // Seems to be hard coded at 0 | 310 | params.value = 0; // Seems to be hard coded at 0 |
| 337 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 338 | return NvResult::Success; | 311 | return NvResult::Success; |
| 339 | } | 312 | } |
| 340 | 313 | ||
| 341 | NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::span<u8> output) { | 314 | NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) { |
| 342 | IoctlChannelSetTimeout params{}; | ||
| 343 | std::memcpy(¶ms, input.data(), sizeof(IoctlChannelSetTimeout)); | ||
| 344 | LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); | 315 | LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); |
| 345 | 316 | ||
| 346 | return NvResult::Success; | 317 | return NvResult::Success; |
| 347 | } | 318 | } |
| 348 | 319 | ||
| 349 | NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output) { | 320 | NvResult nvhost_gpu::ChannelSetTimeslice(IoctlSetTimeslice& params) { |
| 350 | IoctlSetTimeslice params{}; | ||
| 351 | std::memcpy(¶ms, input.data(), sizeof(IoctlSetTimeslice)); | ||
| 352 | LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); | 321 | LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); |
| 353 | 322 | ||
| 354 | channel_timeslice = params.timeslice; | 323 | channel_timeslice = params.timeslice; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 529c20526..88fd228ff 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h | |||
| @@ -186,23 +186,24 @@ private: | |||
| 186 | u32_le channel_priority{}; | 186 | u32_le channel_priority{}; |
| 187 | u32_le channel_timeslice{}; | 187 | u32_le channel_timeslice{}; |
| 188 | 188 | ||
| 189 | NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output); | 189 | NvResult SetNVMAPfd(IoctlSetNvmapFD& params); |
| 190 | NvResult SetClientData(std::span<const u8> input, std::span<u8> output); | 190 | NvResult SetClientData(IoctlClientData& params); |
| 191 | NvResult GetClientData(std::span<const u8> input, std::span<u8> output); | 191 | NvResult GetClientData(IoctlClientData& params); |
| 192 | NvResult ZCullBind(std::span<const u8> input, std::span<u8> output); | 192 | NvResult ZCullBind(IoctlZCullBind& params); |
| 193 | NvResult SetErrorNotifier(std::span<const u8> input, std::span<u8> output); | 193 | NvResult SetErrorNotifier(IoctlSetErrorNotifier& params); |
| 194 | NvResult SetChannelPriority(std::span<const u8> input, std::span<u8> output); | 194 | NvResult SetChannelPriority(IoctlChannelSetPriority& params); |
| 195 | NvResult AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output); | 195 | NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params); |
| 196 | NvResult AllocateObjectContext(std::span<const u8> input, std::span<u8> output); | 196 | NvResult AllocateObjectContext(IoctlAllocObjCtx& params); |
| 197 | NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output, | 197 | |
| 198 | Tegra::CommandList&& entries); | 198 | NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries); |
| 199 | NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output, | 199 | NvResult SubmitGPFIFOBase1(IoctlSubmitGpfifo& params, |
| 200 | bool kickoff = false); | 200 | std::span<Tegra::CommandListHeader> commands, bool kickoff = false); |
| 201 | NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, | 201 | NvResult SubmitGPFIFOBase2(IoctlSubmitGpfifo& params, |
| 202 | std::span<u8> output); | 202 | std::span<const Tegra::CommandListHeader> commands); |
| 203 | NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output); | 203 | |
| 204 | NvResult ChannelSetTimeout(std::span<const u8> input, std::span<u8> output); | 204 | NvResult GetWaitbase(IoctlGetWaitbase& params); |
| 205 | NvResult ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output); | 205 | NvResult ChannelSetTimeout(IoctlChannelSetTimeout& params); |
| 206 | NvResult ChannelSetTimeslice(IoctlSetTimeslice& params); | ||
| 206 | 207 | ||
| 207 | EventInterface& events_interface; | 208 | EventInterface& events_interface; |
| 208 | NvCore::Container& core; | 209 | NvCore::Container& core; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index a174442a6..f43914e1b 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/hle/service/nvdrv/core/container.h" | 8 | #include "core/hle/service/nvdrv/core/container.h" |
| 9 | #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" | 10 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" |
| 10 | #include "video_core/renderer_base.h" | 11 | #include "video_core/renderer_base.h" |
| 11 | 12 | ||
| @@ -25,18 +26,18 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 25 | if (!host1x_file.fd_to_id.contains(fd)) { | 26 | if (!host1x_file.fd_to_id.contains(fd)) { |
| 26 | host1x_file.fd_to_id[fd] = host1x_file.nvdec_next_id++; | 27 | host1x_file.fd_to_id[fd] = host1x_file.nvdec_next_id++; |
| 27 | } | 28 | } |
| 28 | return Submit(fd, input, output); | 29 | return WrapFixedVariable(this, &nvhost_nvdec::Submit, input, output, fd); |
| 29 | } | 30 | } |
| 30 | case 0x2: | 31 | case 0x2: |
| 31 | return GetSyncpoint(input, output); | 32 | return WrapFixed(this, &nvhost_nvdec::GetSyncpoint, input, output); |
| 32 | case 0x3: | 33 | case 0x3: |
| 33 | return GetWaitbase(input, output); | 34 | return WrapFixed(this, &nvhost_nvdec::GetWaitbase, input, output); |
| 34 | case 0x7: | 35 | case 0x7: |
| 35 | return SetSubmitTimeout(input, output); | 36 | return WrapFixed(this, &nvhost_nvdec::SetSubmitTimeout, input, output); |
| 36 | case 0x9: | 37 | case 0x9: |
| 37 | return MapBuffer(input, output); | 38 | return WrapFixedVariable(this, &nvhost_nvdec::MapBuffer, input, output); |
| 38 | case 0xa: | 39 | case 0xa: |
| 39 | return UnmapBuffer(input, output); | 40 | return WrapFixedVariable(this, &nvhost_nvdec::UnmapBuffer, input, output); |
| 40 | default: | 41 | default: |
| 41 | break; | 42 | break; |
| 42 | } | 43 | } |
| @@ -44,7 +45,7 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 44 | case 'H': | 45 | case 'H': |
| 45 | switch (command.cmd) { | 46 | switch (command.cmd) { |
| 46 | case 0x1: | 47 | case 0x1: |
| 47 | return SetNVMAPfd(input); | 48 | return WrapFixed(this, &nvhost_nvdec::SetNVMAPfd, input, output); |
| 48 | default: | 49 | default: |
| 49 | break; | 50 | break; |
| 50 | } | 51 | } |
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 61649aa4a..74c701b95 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -29,6 +29,9 @@ std::size_t SliceVectors(std::span<const u8> input, std::vector<T>& dst, std::si | |||
| 29 | return 0; | 29 | return 0; |
| 30 | } | 30 | } |
| 31 | const size_t bytes_copied = count * sizeof(T); | 31 | const size_t bytes_copied = count * sizeof(T); |
| 32 | if (input.size() < offset + bytes_copied) { | ||
| 33 | return 0; | ||
| 34 | } | ||
| 32 | std::memcpy(dst.data(), input.data() + offset, bytes_copied); | 35 | std::memcpy(dst.data(), input.data() + offset, bytes_copied); |
| 33 | return bytes_copied; | 36 | return bytes_copied; |
| 34 | } | 37 | } |
| @@ -41,6 +44,9 @@ std::size_t WriteVectors(std::span<u8> dst, const std::vector<T>& src, std::size | |||
| 41 | return 0; | 44 | return 0; |
| 42 | } | 45 | } |
| 43 | const size_t bytes_copied = src.size() * sizeof(T); | 46 | const size_t bytes_copied = src.size() * sizeof(T); |
| 47 | if (dst.size() < offset + bytes_copied) { | ||
| 48 | return 0; | ||
| 49 | } | ||
| 44 | std::memcpy(dst.data() + offset, src.data(), bytes_copied); | 50 | std::memcpy(dst.data() + offset, src.data(), bytes_copied); |
| 45 | return bytes_copied; | 51 | return bytes_copied; |
| 46 | } | 52 | } |
| @@ -63,18 +69,14 @@ nvhost_nvdec_common::~nvhost_nvdec_common() { | |||
| 63 | core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint); | 69 | core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint); |
| 64 | } | 70 | } |
| 65 | 71 | ||
| 66 | NvResult nvhost_nvdec_common::SetNVMAPfd(std::span<const u8> input) { | 72 | NvResult nvhost_nvdec_common::SetNVMAPfd(IoctlSetNvmapFD& params) { |
| 67 | IoctlSetNvmapFD params{}; | ||
| 68 | std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD)); | ||
| 69 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | 73 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); |
| 70 | 74 | ||
| 71 | nvmap_fd = params.nvmap_fd; | 75 | nvmap_fd = params.nvmap_fd; |
| 72 | return NvResult::Success; | 76 | return NvResult::Success; |
| 73 | } | 77 | } |
| 74 | 78 | ||
| 75 | NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output) { | 79 | NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, DeviceFD fd) { |
| 76 | IoctlSubmit params{}; | ||
| 77 | std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); | ||
| 78 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); | 80 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); |
| 79 | 81 | ||
| 80 | // Instantiate param buffers | 82 | // Instantiate param buffers |
| @@ -85,12 +87,12 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std | |||
| 85 | std::vector<u32> fence_thresholds(params.fence_count); | 87 | std::vector<u32> fence_thresholds(params.fence_count); |
| 86 | 88 | ||
| 87 | // Slice input into their respective buffers | 89 | // Slice input into their respective buffers |
| 88 | std::size_t offset = sizeof(IoctlSubmit); | 90 | std::size_t offset = 0; |
| 89 | offset += SliceVectors(input, command_buffers, params.cmd_buffer_count, offset); | 91 | offset += SliceVectors(data, command_buffers, params.cmd_buffer_count, offset); |
| 90 | offset += SliceVectors(input, relocs, params.relocation_count, offset); | 92 | offset += SliceVectors(data, relocs, params.relocation_count, offset); |
| 91 | offset += SliceVectors(input, reloc_shifts, params.relocation_count, offset); | 93 | offset += SliceVectors(data, reloc_shifts, params.relocation_count, offset); |
| 92 | offset += SliceVectors(input, syncpt_increments, params.syncpoint_count, offset); | 94 | offset += SliceVectors(data, syncpt_increments, params.syncpoint_count, offset); |
| 93 | offset += SliceVectors(input, fence_thresholds, params.fence_count, offset); | 95 | offset += SliceVectors(data, fence_thresholds, params.fence_count, offset); |
| 94 | 96 | ||
| 95 | auto& gpu = system.GPU(); | 97 | auto& gpu = system.GPU(); |
| 96 | if (gpu.UseNvdec()) { | 98 | if (gpu.UseNvdec()) { |
| @@ -108,72 +110,51 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std | |||
| 108 | cmdlist.size() * sizeof(u32)); | 110 | cmdlist.size() * sizeof(u32)); |
| 109 | gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); | 111 | gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); |
| 110 | } | 112 | } |
| 111 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); | ||
| 112 | // Some games expect command_buffers to be written back | 113 | // Some games expect command_buffers to be written back |
| 113 | offset = sizeof(IoctlSubmit); | 114 | offset = 0; |
| 114 | offset += WriteVectors(output, command_buffers, offset); | 115 | offset += WriteVectors(data, command_buffers, offset); |
| 115 | offset += WriteVectors(output, relocs, offset); | 116 | offset += WriteVectors(data, relocs, offset); |
| 116 | offset += WriteVectors(output, reloc_shifts, offset); | 117 | offset += WriteVectors(data, reloc_shifts, offset); |
| 117 | offset += WriteVectors(output, syncpt_increments, offset); | 118 | offset += WriteVectors(data, syncpt_increments, offset); |
| 118 | offset += WriteVectors(output, fence_thresholds, offset); | 119 | offset += WriteVectors(data, fence_thresholds, offset); |
| 119 | 120 | ||
| 120 | return NvResult::Success; | 121 | return NvResult::Success; |
| 121 | } | 122 | } |
| 122 | 123 | ||
| 123 | NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::span<u8> output) { | 124 | NvResult nvhost_nvdec_common::GetSyncpoint(IoctlGetSyncpoint& params) { |
| 124 | IoctlGetSyncpoint params{}; | ||
| 125 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint)); | ||
| 126 | LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); | 125 | LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); |
| 127 | |||
| 128 | // const u32 id{NvCore::SyncpointManager::channel_syncpoints[static_cast<u32>(channel_type)]}; | ||
| 129 | params.value = channel_syncpoint; | 126 | params.value = channel_syncpoint; |
| 130 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint)); | ||
| 131 | |||
| 132 | return NvResult::Success; | 127 | return NvResult::Success; |
| 133 | } | 128 | } |
| 134 | 129 | ||
| 135 | NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::span<u8> output) { | 130 | NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) { |
| 136 | IoctlGetWaitbase params{}; | ||
| 137 | LOG_CRITICAL(Service_NVDRV, "called WAITBASE"); | 131 | LOG_CRITICAL(Service_NVDRV, "called WAITBASE"); |
| 138 | std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); | ||
| 139 | params.value = 0; // Seems to be hard coded at 0 | 132 | params.value = 0; // Seems to be hard coded at 0 |
| 140 | std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase)); | ||
| 141 | return NvResult::Success; | 133 | return NvResult::Success; |
| 142 | } | 134 | } |
| 143 | 135 | ||
| 144 | NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::span<u8> output) { | 136 | NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries) { |
| 145 | IoctlMapBuffer params{}; | 137 | const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size())); |
| 146 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | 138 | for (size_t i = 0; i < num_entries; i++) { |
| 147 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | 139 | entries[i].map_address = nvmap.PinHandle(entries[i].map_handle); |
| 148 | |||
| 149 | SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | ||
| 150 | |||
| 151 | for (auto& cmd_buffer : cmd_buffer_handles) { | ||
| 152 | cmd_buffer.map_address = nvmap.PinHandle(cmd_buffer.map_handle); | ||
| 153 | } | 140 | } |
| 154 | std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer)); | ||
| 155 | std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(), | ||
| 156 | cmd_buffer_handles.size() * sizeof(MapBufferEntry)); | ||
| 157 | 141 | ||
| 158 | return NvResult::Success; | 142 | return NvResult::Success; |
| 159 | } | 143 | } |
| 160 | 144 | ||
| 161 | NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::span<u8> output) { | 145 | NvResult nvhost_nvdec_common::UnmapBuffer(IoctlMapBuffer& params, |
| 162 | IoctlMapBuffer params{}; | 146 | std::span<MapBufferEntry> entries) { |
| 163 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | 147 | const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size())); |
| 164 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | 148 | for (size_t i = 0; i < num_entries; i++) { |
| 165 | 149 | nvmap.UnpinHandle(entries[i].map_handle); | |
| 166 | SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | 150 | entries[i] = {}; |
| 167 | for (auto& cmd_buffer : cmd_buffer_handles) { | ||
| 168 | nvmap.UnpinHandle(cmd_buffer.map_handle); | ||
| 169 | } | 151 | } |
| 170 | 152 | ||
| 171 | std::memset(output.data(), 0, output.size()); | 153 | params = {}; |
| 172 | return NvResult::Success; | 154 | return NvResult::Success; |
| 173 | } | 155 | } |
| 174 | 156 | ||
| 175 | NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::span<u8> output) { | 157 | NvResult nvhost_nvdec_common::SetSubmitTimeout(u32 timeout) { |
| 176 | std::memcpy(&submit_timeout, input.data(), input.size()); | ||
| 177 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 158 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 178 | return NvResult::Success; | 159 | return NvResult::Success; |
| 179 | } | 160 | } |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index 9bb573bfe..7ce748e18 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | |||
| @@ -107,13 +107,13 @@ protected: | |||
| 107 | static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); | 107 | static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); |
| 108 | 108 | ||
| 109 | /// Ioctl command implementations | 109 | /// Ioctl command implementations |
| 110 | NvResult SetNVMAPfd(std::span<const u8> input); | 110 | NvResult SetNVMAPfd(IoctlSetNvmapFD&); |
| 111 | NvResult Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output); | 111 | NvResult Submit(IoctlSubmit& params, std::span<u8> input, DeviceFD fd); |
| 112 | NvResult GetSyncpoint(std::span<const u8> input, std::span<u8> output); | 112 | NvResult GetSyncpoint(IoctlGetSyncpoint& params); |
| 113 | NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output); | 113 | NvResult GetWaitbase(IoctlGetWaitbase& params); |
| 114 | NvResult MapBuffer(std::span<const u8> input, std::span<u8> output); | 114 | NvResult MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); |
| 115 | NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); | 115 | NvResult UnmapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); |
| 116 | NvResult SetSubmitTimeout(std::span<const u8> input, std::span<u8> output); | 116 | NvResult SetSubmitTimeout(u32 timeout); |
| 117 | 117 | ||
| 118 | Kernel::KEvent* QueryEvent(u32 event_id) override; | 118 | Kernel::KEvent* QueryEvent(u32 event_id) override; |
| 119 | 119 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index a05c8cdae..9e6b86458 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||
| 8 | #include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h" | 9 | #include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h" |
| 9 | 10 | ||
| 10 | namespace Service::Nvidia::Devices { | 11 | namespace Service::Nvidia::Devices { |
| @@ -18,7 +19,7 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 18 | case 'H': | 19 | case 'H': |
| 19 | switch (command.cmd) { | 20 | switch (command.cmd) { |
| 20 | case 0x1: | 21 | case 0x1: |
| 21 | return SetNVMAPfd(input, output); | 22 | return WrapFixed(this, &nvhost_nvjpg::SetNVMAPfd, input, output); |
| 22 | default: | 23 | default: |
| 23 | break; | 24 | break; |
| 24 | } | 25 | } |
| @@ -46,9 +47,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 46 | void nvhost_nvjpg::OnOpen(DeviceFD fd) {} | 47 | void nvhost_nvjpg::OnOpen(DeviceFD fd) {} |
| 47 | void nvhost_nvjpg::OnClose(DeviceFD fd) {} | 48 | void nvhost_nvjpg::OnClose(DeviceFD fd) {} |
| 48 | 49 | ||
| 49 | NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) { | 50 | NvResult nvhost_nvjpg::SetNVMAPfd(IoctlSetNvmapFD& params) { |
| 50 | IoctlSetNvmapFD params{}; | ||
| 51 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 52 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | 51 | LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); |
| 53 | 52 | ||
| 54 | nvmap_fd = params.nvmap_fd; | 53 | nvmap_fd = params.nvmap_fd; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index 5623e0d47..790c97f6a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h | |||
| @@ -33,7 +33,7 @@ private: | |||
| 33 | 33 | ||
| 34 | s32_le nvmap_fd{}; | 34 | s32_le nvmap_fd{}; |
| 35 | 35 | ||
| 36 | NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output); | 36 | NvResult SetNVMAPfd(IoctlSetNvmapFD& params); |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | } // namespace Service::Nvidia::Devices | 39 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index c0b8684c3..87f8d7c22 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/hle/service/nvdrv/core/container.h" | 7 | #include "core/hle/service/nvdrv/core/container.h" |
| 8 | #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||
| 8 | #include "core/hle/service/nvdrv/devices/nvhost_vic.h" | 9 | #include "core/hle/service/nvdrv/devices/nvhost_vic.h" |
| 9 | #include "video_core/renderer_base.h" | 10 | #include "video_core/renderer_base.h" |
| 10 | 11 | ||
| @@ -25,16 +26,16 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 25 | if (!host1x_file.fd_to_id.contains(fd)) { | 26 | if (!host1x_file.fd_to_id.contains(fd)) { |
| 26 | host1x_file.fd_to_id[fd] = host1x_file.vic_next_id++; | 27 | host1x_file.fd_to_id[fd] = host1x_file.vic_next_id++; |
| 27 | } | 28 | } |
| 28 | return Submit(fd, input, output); | 29 | return WrapFixedVariable(this, &nvhost_vic::Submit, input, output, fd); |
| 29 | } | 30 | } |
| 30 | case 0x2: | 31 | case 0x2: |
| 31 | return GetSyncpoint(input, output); | 32 | return WrapFixed(this, &nvhost_vic::GetSyncpoint, input, output); |
| 32 | case 0x3: | 33 | case 0x3: |
| 33 | return GetWaitbase(input, output); | 34 | return WrapFixed(this, &nvhost_vic::GetWaitbase, input, output); |
| 34 | case 0x9: | 35 | case 0x9: |
| 35 | return MapBuffer(input, output); | 36 | return WrapFixedVariable(this, &nvhost_vic::MapBuffer, input, output); |
| 36 | case 0xa: | 37 | case 0xa: |
| 37 | return UnmapBuffer(input, output); | 38 | return WrapFixedVariable(this, &nvhost_vic::UnmapBuffer, input, output); |
| 38 | default: | 39 | default: |
| 39 | break; | 40 | break; |
| 40 | } | 41 | } |
| @@ -42,7 +43,7 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 42 | case 'H': | 43 | case 'H': |
| 43 | switch (command.cmd) { | 44 | switch (command.cmd) { |
| 44 | case 0x1: | 45 | case 0x1: |
| 45 | return SetNVMAPfd(input); | 46 | return WrapFixed(this, &nvhost_vic::SetNVMAPfd, input, output); |
| 46 | default: | 47 | default: |
| 47 | break; | 48 | break; |
| 48 | } | 49 | } |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 968eaa175..71b2e62ec 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "core/hle/kernel/k_process.h" | 13 | #include "core/hle/kernel/k_process.h" |
| 14 | #include "core/hle/service/nvdrv/core/container.h" | 14 | #include "core/hle/service/nvdrv/core/container.h" |
| 15 | #include "core/hle/service/nvdrv/core/nvmap.h" | 15 | #include "core/hle/service/nvdrv/core/nvmap.h" |
| 16 | #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||
| 16 | #include "core/hle/service/nvdrv/devices/nvmap.h" | 17 | #include "core/hle/service/nvdrv/devices/nvmap.h" |
| 17 | #include "core/memory.h" | 18 | #include "core/memory.h" |
| 18 | 19 | ||
| @@ -31,17 +32,17 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, | |||
| 31 | case 0x1: | 32 | case 0x1: |
| 32 | switch (command.cmd) { | 33 | switch (command.cmd) { |
| 33 | case 0x1: | 34 | case 0x1: |
| 34 | return IocCreate(input, output); | 35 | return WrapFixed(this, &nvmap::IocCreate, input, output); |
| 35 | case 0x3: | 36 | case 0x3: |
| 36 | return IocFromId(input, output); | 37 | return WrapFixed(this, &nvmap::IocFromId, input, output); |
| 37 | case 0x4: | 38 | case 0x4: |
| 38 | return IocAlloc(input, output); | 39 | return WrapFixed(this, &nvmap::IocAlloc, input, output); |
| 39 | case 0x5: | 40 | case 0x5: |
| 40 | return IocFree(input, output); | 41 | return WrapFixed(this, &nvmap::IocFree, input, output); |
| 41 | case 0x9: | 42 | case 0x9: |
| 42 | return IocParam(input, output); | 43 | return WrapFixed(this, &nvmap::IocParam, input, output); |
| 43 | case 0xe: | 44 | case 0xe: |
| 44 | return IocGetId(input, output); | 45 | return WrapFixed(this, &nvmap::IocGetId, input, output); |
| 45 | default: | 46 | default: |
| 46 | break; | 47 | break; |
| 47 | } | 48 | } |
| @@ -69,9 +70,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, st | |||
| 69 | void nvmap::OnOpen(DeviceFD fd) {} | 70 | void nvmap::OnOpen(DeviceFD fd) {} |
| 70 | void nvmap::OnClose(DeviceFD fd) {} | 71 | void nvmap::OnClose(DeviceFD fd) {} |
| 71 | 72 | ||
| 72 | NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) { | 73 | NvResult nvmap::IocCreate(IocCreateParams& params) { |
| 73 | IocCreateParams params; | ||
| 74 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 75 | LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); | 74 | LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); |
| 76 | 75 | ||
| 77 | std::shared_ptr<NvCore::NvMap::Handle> handle_description{}; | 76 | std::shared_ptr<NvCore::NvMap::Handle> handle_description{}; |
| @@ -85,13 +84,10 @@ NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) { | |||
| 85 | params.handle = handle_description->id; | 84 | params.handle = handle_description->id; |
| 86 | LOG_DEBUG(Service_NVDRV, "handle: {}, size: 0x{:X}", handle_description->id, params.size); | 85 | LOG_DEBUG(Service_NVDRV, "handle: {}, size: 0x{:X}", handle_description->id, params.size); |
| 87 | 86 | ||
| 88 | std::memcpy(output.data(), ¶ms, sizeof(params)); | ||
| 89 | return NvResult::Success; | 87 | return NvResult::Success; |
| 90 | } | 88 | } |
| 91 | 89 | ||
| 92 | NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) { | 90 | NvResult nvmap::IocAlloc(IocAllocParams& params) { |
| 93 | IocAllocParams params; | ||
| 94 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 95 | LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); | 91 | LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); |
| 96 | 92 | ||
| 97 | if (!params.handle) { | 93 | if (!params.handle) { |
| @@ -133,14 +129,10 @@ NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) { | |||
| 133 | handle_description->size, | 129 | handle_description->size, |
| 134 | Kernel::KMemoryPermission::None, true, false) | 130 | Kernel::KMemoryPermission::None, true, false) |
| 135 | .IsSuccess()); | 131 | .IsSuccess()); |
| 136 | std::memcpy(output.data(), ¶ms, sizeof(params)); | ||
| 137 | return result; | 132 | return result; |
| 138 | } | 133 | } |
| 139 | 134 | ||
| 140 | NvResult nvmap::IocGetId(std::span<const u8> input, std::span<u8> output) { | 135 | NvResult nvmap::IocGetId(IocGetIdParams& params) { |
| 141 | IocGetIdParams params; | ||
| 142 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 143 | |||
| 144 | LOG_DEBUG(Service_NVDRV, "called"); | 136 | LOG_DEBUG(Service_NVDRV, "called"); |
| 145 | 137 | ||
| 146 | // See the comment in FromId for extra info on this function | 138 | // See the comment in FromId for extra info on this function |
| @@ -157,14 +149,10 @@ NvResult nvmap::IocGetId(std::span<const u8> input, std::span<u8> output) { | |||
| 157 | } | 149 | } |
| 158 | 150 | ||
| 159 | params.id = handle_description->id; | 151 | params.id = handle_description->id; |
| 160 | std::memcpy(output.data(), ¶ms, sizeof(params)); | ||
| 161 | return NvResult::Success; | 152 | return NvResult::Success; |
| 162 | } | 153 | } |
| 163 | 154 | ||
| 164 | NvResult nvmap::IocFromId(std::span<const u8> input, std::span<u8> output) { | 155 | NvResult nvmap::IocFromId(IocFromIdParams& params) { |
| 165 | IocFromIdParams params; | ||
| 166 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 167 | |||
| 168 | LOG_DEBUG(Service_NVDRV, "called, id:{}", params.id); | 156 | LOG_DEBUG(Service_NVDRV, "called, id:{}", params.id); |
| 169 | 157 | ||
| 170 | // Handles and IDs are always the same value in nvmap however IDs can be used globally given the | 158 | // Handles and IDs are always the same value in nvmap however IDs can be used globally given the |
| @@ -188,16 +176,12 @@ NvResult nvmap::IocFromId(std::span<const u8> input, std::span<u8> output) { | |||
| 188 | return result; | 176 | return result; |
| 189 | } | 177 | } |
| 190 | params.handle = handle_description->id; | 178 | params.handle = handle_description->id; |
| 191 | std::memcpy(output.data(), ¶ms, sizeof(params)); | ||
| 192 | return NvResult::Success; | 179 | return NvResult::Success; |
| 193 | } | 180 | } |
| 194 | 181 | ||
| 195 | NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) { | 182 | NvResult nvmap::IocParam(IocParamParams& params) { |
| 196 | enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; | 183 | enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; |
| 197 | 184 | ||
| 198 | IocParamParams params; | ||
| 199 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 200 | |||
| 201 | LOG_DEBUG(Service_NVDRV, "called type={}", params.param); | 185 | LOG_DEBUG(Service_NVDRV, "called type={}", params.param); |
| 202 | 186 | ||
| 203 | if (!params.handle) { | 187 | if (!params.handle) { |
| @@ -237,14 +221,10 @@ NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) { | |||
| 237 | return NvResult::BadValue; | 221 | return NvResult::BadValue; |
| 238 | } | 222 | } |
| 239 | 223 | ||
| 240 | std::memcpy(output.data(), ¶ms, sizeof(params)); | ||
| 241 | return NvResult::Success; | 224 | return NvResult::Success; |
| 242 | } | 225 | } |
| 243 | 226 | ||
| 244 | NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) { | 227 | NvResult nvmap::IocFree(IocFreeParams& params) { |
| 245 | IocFreeParams params; | ||
| 246 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 247 | |||
| 248 | LOG_DEBUG(Service_NVDRV, "called"); | 228 | LOG_DEBUG(Service_NVDRV, "called"); |
| 249 | 229 | ||
| 250 | if (!params.handle) { | 230 | if (!params.handle) { |
| @@ -267,7 +247,6 @@ NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) { | |||
| 267 | // This is possible when there's internal dups or other duplicates. | 247 | // This is possible when there's internal dups or other duplicates. |
| 268 | } | 248 | } |
| 269 | 249 | ||
| 270 | std::memcpy(output.data(), ¶ms, sizeof(params)); | ||
| 271 | return NvResult::Success; | 250 | return NvResult::Success; |
| 272 | } | 251 | } |
| 273 | 252 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 4c0cc71cd..049c11028 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h | |||
| @@ -99,12 +99,12 @@ public: | |||
| 99 | }; | 99 | }; |
| 100 | static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); | 100 | static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); |
| 101 | 101 | ||
| 102 | NvResult IocCreate(std::span<const u8> input, std::span<u8> output); | 102 | NvResult IocCreate(IocCreateParams& params); |
| 103 | NvResult IocAlloc(std::span<const u8> input, std::span<u8> output); | 103 | NvResult IocAlloc(IocAllocParams& params); |
| 104 | NvResult IocGetId(std::span<const u8> input, std::span<u8> output); | 104 | NvResult IocGetId(IocGetIdParams& params); |
| 105 | NvResult IocFromId(std::span<const u8> input, std::span<u8> output); | 105 | NvResult IocFromId(IocFromIdParams& params); |
| 106 | NvResult IocParam(std::span<const u8> input, std::span<u8> output); | 106 | NvResult IocParam(IocParamParams& params); |
| 107 | NvResult IocFree(std::span<const u8> input, std::span<u8> output); | 107 | NvResult IocFree(IocFreeParams& params); |
| 108 | 108 | ||
| 109 | private: | 109 | private: |
| 110 | /// Id to use for the next handle that is created. | 110 | /// Id to use for the next handle that is created. |
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp index 2e29bc848..6dc327b8b 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp | |||
| @@ -71,24 +71,17 @@ Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address, | |||
| 71 | R_SUCCEED(); | 71 | R_SUCCEED(); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | template <typename T> | ||
| 75 | std::span<u8> SerializeIoc(T& params) { | ||
| 76 | return std::span(reinterpret_cast<u8*>(std::addressof(params)), sizeof(T)); | ||
| 77 | } | ||
| 78 | |||
| 79 | Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) { | 74 | Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) { |
| 80 | // Create a handle. | 75 | // Create a handle. |
| 81 | Nvidia::Devices::nvmap::IocCreateParams create_in_params{ | 76 | Nvidia::Devices::nvmap::IocCreateParams create_params{ |
| 82 | .size = size, | 77 | .size = size, |
| 83 | .handle = 0, | 78 | .handle = 0, |
| 84 | }; | 79 | }; |
| 85 | Nvidia::Devices::nvmap::IocCreateParams create_out_params{}; | 80 | R_UNLESS(nvmap.IocCreate(create_params) == Nvidia::NvResult::Success, |
| 86 | R_UNLESS(nvmap.IocCreate(SerializeIoc(create_in_params), SerializeIoc(create_out_params)) == | ||
| 87 | Nvidia::NvResult::Success, | ||
| 88 | VI::ResultOperationFailed); | 81 | VI::ResultOperationFailed); |
| 89 | 82 | ||
| 90 | // Assign the output handle. | 83 | // Assign the output handle. |
| 91 | *out_nv_map_handle = create_out_params.handle; | 84 | *out_nv_map_handle = create_params.handle; |
| 92 | 85 | ||
| 93 | // We succeeded. | 86 | // We succeeded. |
| 94 | R_SUCCEED(); | 87 | R_SUCCEED(); |
| @@ -96,13 +89,10 @@ Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, | |||
| 96 | 89 | ||
| 97 | Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) { | 90 | Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) { |
| 98 | // Free the handle. | 91 | // Free the handle. |
| 99 | Nvidia::Devices::nvmap::IocFreeParams free_in_params{ | 92 | Nvidia::Devices::nvmap::IocFreeParams free_params{ |
| 100 | .handle = handle, | 93 | .handle = handle, |
| 101 | }; | 94 | }; |
| 102 | Nvidia::Devices::nvmap::IocFreeParams free_out_params{}; | 95 | R_UNLESS(nvmap.IocFree(free_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed); |
| 103 | R_UNLESS(nvmap.IocFree(SerializeIoc(free_in_params), SerializeIoc(free_out_params)) == | ||
| 104 | Nvidia::NvResult::Success, | ||
| 105 | VI::ResultOperationFailed); | ||
| 106 | 96 | ||
| 107 | // We succeeded. | 97 | // We succeeded. |
| 108 | R_SUCCEED(); | 98 | R_SUCCEED(); |
| @@ -111,7 +101,7 @@ Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) { | |||
| 111 | Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, | 101 | Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, |
| 112 | u32 size) { | 102 | u32 size) { |
| 113 | // Assign the allocated memory to the handle. | 103 | // Assign the allocated memory to the handle. |
| 114 | Nvidia::Devices::nvmap::IocAllocParams alloc_in_params{ | 104 | Nvidia::Devices::nvmap::IocAllocParams alloc_params{ |
| 115 | .handle = handle, | 105 | .handle = handle, |
| 116 | .heap_mask = 0, | 106 | .heap_mask = 0, |
| 117 | .flags = {}, | 107 | .flags = {}, |
| @@ -119,10 +109,7 @@ Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::Proce | |||
| 119 | .kind = 0, | 109 | .kind = 0, |
| 120 | .address = GetInteger(buffer), | 110 | .address = GetInteger(buffer), |
| 121 | }; | 111 | }; |
| 122 | Nvidia::Devices::nvmap::IocAllocParams alloc_out_params{}; | 112 | R_UNLESS(nvmap.IocAlloc(alloc_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed); |
| 123 | R_UNLESS(nvmap.IocAlloc(SerializeIoc(alloc_in_params), SerializeIoc(alloc_out_params)) == | ||
| 124 | Nvidia::NvResult::Success, | ||
| 125 | VI::ResultOperationFailed); | ||
| 126 | 113 | ||
| 127 | // We succeeded. | 114 | // We succeeded. |
| 128 | R_SUCCEED(); | 115 | R_SUCCEED(); |