early-access version 3959
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| yuzu emulator early access | ||||
| ============= | ||||
|  | ||||
| This is the source code for early-access 3958. | ||||
| This is the source code for early-access 3959. | ||||
|  | ||||
| ## Legal Notice | ||||
|  | ||||
|   | ||||
							
								
								
									
										159
									
								
								src/core/hle/service/nvdrv/devices/ioctl_serialization.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										159
									
								
								src/core/hle/service/nvdrv/devices/ioctl_serialization.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <span> | ||||
| #include <vector> | ||||
|  | ||||
| #include "common/concepts.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||||
|  | ||||
| namespace Service::Nvidia::Devices { | ||||
|  | ||||
| struct IoctlOneArgTraits { | ||||
|     template <typename T, typename R, typename A, typename... B> | ||||
|     static A GetFirstArgImpl(R (T::*)(A, B...)); | ||||
| }; | ||||
|  | ||||
| struct IoctlTwoArgTraits { | ||||
|     template <typename T, typename R, typename A, typename B, typename... C> | ||||
|     static A GetFirstArgImpl(R (T::*)(A, B, C...)); | ||||
|  | ||||
|     template <typename T, typename R, typename A, typename B, typename... C> | ||||
|     static B GetSecondArgImpl(R (T::*)(A, B, C...)); | ||||
| }; | ||||
|  | ||||
| struct Null {}; | ||||
|  | ||||
| // clang-format off | ||||
|  | ||||
| template <typename FixedArg, typename VarArg, typename InlInVarArg, typename InlOutVarArg, typename F> | ||||
| NvResult WrapGeneric(F&& callable, std::span<const u8> input, std::span<const u8> inline_input, std::span<u8> output, std::span<u8> inline_output) { | ||||
|     constexpr bool HasFixedArg     = !std::is_same_v<FixedArg, Null>; | ||||
|     constexpr bool HasVarArg       = !std::is_same_v<VarArg, Null>; | ||||
|     constexpr bool HasInlInVarArg  = !std::is_same_v<InlInVarArg, Null>; | ||||
|     constexpr bool HasInlOutVarArg = !std::is_same_v<InlOutVarArg, Null>; | ||||
|  | ||||
|     // Declare the fixed-size input value. | ||||
|     FixedArg fixed{}; | ||||
|     size_t var_offset = 0; | ||||
|  | ||||
|     if constexpr (HasFixedArg) { | ||||
|         // Read the fixed-size input value. | ||||
|         var_offset = std::min(sizeof(FixedArg), input.size()); | ||||
|         if (var_offset > 0) { | ||||
|             std::memcpy(&fixed, input.data(), var_offset); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Read the variable-sized inputs. | ||||
|     const size_t num_var_args = HasVarArg ? ((input.size() - var_offset) / sizeof(VarArg)) : 0; | ||||
|     std::vector<VarArg> var_args(num_var_args); | ||||
|     if constexpr (HasVarArg) { | ||||
|         if (num_var_args > 0) { | ||||
|             std::memcpy(var_args.data(), input.data() + var_offset, num_var_args * sizeof(VarArg)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     const size_t num_inl_in_var_args = HasInlInVarArg ? (inline_input.size() / sizeof(InlInVarArg)) : 0; | ||||
|     std::vector<InlInVarArg> inl_in_var_args(num_inl_in_var_args); | ||||
|     if constexpr (HasInlInVarArg) { | ||||
|         if (num_inl_in_var_args > 0) { | ||||
|             std::memcpy(inl_in_var_args.data(), inline_input.data(), num_inl_in_var_args * sizeof(InlInVarArg)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Construct inline output data. | ||||
|     const size_t num_inl_out_var_args = HasInlOutVarArg ? (inline_output.size() / sizeof(InlOutVarArg)) : 0; | ||||
|     std::vector<InlOutVarArg> inl_out_var_args(num_inl_out_var_args); | ||||
|  | ||||
|     // Perform the call. | ||||
|     NvResult result = callable(fixed, var_args, inl_in_var_args, inl_out_var_args); | ||||
|  | ||||
|     // Copy outputs. | ||||
|     if constexpr (HasFixedArg) { | ||||
|         if (output.size() > 0) { | ||||
|             std::memcpy(output.data(), &fixed, std::min(output.size(), sizeof(FixedArg))); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if constexpr (HasVarArg) { | ||||
|         if (num_var_args > 0 && output.size() > var_offset) { | ||||
|             const size_t max_var_size = output.size() - var_offset; | ||||
|             std::memcpy(output.data() + var_offset, var_args.data(), std::min(max_var_size, num_var_args * sizeof(VarArg))); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Copy inline outputs. | ||||
|     if constexpr (HasInlOutVarArg) { | ||||
|         if (num_inl_out_var_args > 0) { | ||||
|             std::memcpy(inline_output.data(), inl_out_var_args.data(), num_inl_out_var_args * sizeof(InlOutVarArg)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // We're done. | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| template <typename Self, typename F, typename... Rest> | ||||
| NvResult WrapFixed(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) { | ||||
|     using FixedArg = typename std::remove_reference_t<decltype(IoctlOneArgTraits::GetFirstArgImpl(callable))>; | ||||
|  | ||||
|     const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||||
|         return (self->*callable)(fixed, std::forward<Rest>(rest)...); | ||||
|     }; | ||||
|  | ||||
|     return WrapGeneric<FixedArg, Null, Null, Null>(std::move(Callable), input, {}, output, {}); | ||||
| } | ||||
|  | ||||
| template <typename Self, typename F, typename... Rest> | ||||
| NvResult WrapFixedInlOut(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, std::span<u8> inline_output, Rest&&... rest) { | ||||
|     using FixedArg     = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>; | ||||
|     using InlOutVarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type; | ||||
|  | ||||
|     const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||||
|         return (self->*callable)(fixed, inl_out, std::forward<Rest>(rest)...); | ||||
|     }; | ||||
|  | ||||
|     return WrapGeneric<FixedArg, Null, Null, InlOutVarArg>(std::move(Callable), input, {}, output, inline_output); | ||||
| } | ||||
|  | ||||
| template <typename Self, typename F, typename... Rest> | ||||
| NvResult WrapVariable(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) { | ||||
|     using VarArg = typename std::remove_reference_t<decltype(IoctlOneArgTraits::GetFirstArgImpl(callable))>::value_type; | ||||
|  | ||||
|     const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||||
|         return (self->*callable)(var, std::forward<Rest>(rest)...); | ||||
|     }; | ||||
|  | ||||
|     return WrapGeneric<Null, VarArg, Null, Null>(std::move(Callable), input, {}, output, {}); | ||||
| } | ||||
|  | ||||
| template <typename Self, typename F, typename... Rest> | ||||
| NvResult WrapFixedVariable(Self* self, F&& callable, std::span<const u8> input, std::span<u8> output, Rest&&... rest) { | ||||
|     using FixedArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>; | ||||
|     using VarArg   = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type; | ||||
|  | ||||
|     const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||||
|         return (self->*callable)(fixed, var, std::forward<Rest>(rest)...); | ||||
|     }; | ||||
|  | ||||
|     return WrapGeneric<FixedArg, VarArg, Null, Null>(std::move(Callable), input, {}, output, {}); | ||||
| } | ||||
|  | ||||
| template <typename Self, typename F, typename... Rest> | ||||
| NvResult WrapFixedInlIn(Self* self, F&& callable, std::span<const u8> input, std::span<const u8> inline_input, std::span<u8> output, Rest&&... rest) { | ||||
|     using FixedArg    = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetFirstArgImpl(callable))>; | ||||
|     using InlInVarArg = typename std::remove_reference_t<decltype(IoctlTwoArgTraits::GetSecondArgImpl(callable))>::value_type; | ||||
|  | ||||
|     const auto Callable = [&](auto& fixed, auto& var, auto& inl_in, auto& inl_out) -> NvResult { | ||||
|         return (self->*callable)(fixed, inl_in, std::forward<Rest>(rest)...); | ||||
|     }; | ||||
|  | ||||
|     return WrapGeneric<FixedArg, Null, InlInVarArg, Null>(std::move(Callable), input, inline_input, output, {}); | ||||
| } | ||||
|  | ||||
| // clang-format on | ||||
|  | ||||
| } // namespace Service::Nvidia::Devices | ||||
| @@ -11,6 +11,7 @@ | ||||
| #include "core/core.h" | ||||
| #include "core/hle/service/nvdrv/core/container.h" | ||||
| #include "core/hle/service/nvdrv/core/nvmap.h" | ||||
| #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" | ||||
| #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 | ||||
|     case 'A': | ||||
|         switch (command.cmd) { | ||||
|         case 0x1: | ||||
|             return BindChannel(input, output); | ||||
|             return WrapFixed(this, &nvhost_as_gpu::BindChannel, input, output); | ||||
|         case 0x2: | ||||
|             return AllocateSpace(input, output); | ||||
|             return WrapFixed(this, &nvhost_as_gpu::AllocateSpace, input, output); | ||||
|         case 0x3: | ||||
|             return FreeSpace(input, output); | ||||
|             return WrapFixed(this, &nvhost_as_gpu::FreeSpace, input, output); | ||||
|         case 0x5: | ||||
|             return UnmapBuffer(input, output); | ||||
|             return WrapFixed(this, &nvhost_as_gpu::UnmapBuffer, input, output); | ||||
|         case 0x6: | ||||
|             return MapBufferEx(input, output); | ||||
|             return WrapFixed(this, &nvhost_as_gpu::MapBufferEx, input, output); | ||||
|         case 0x8: | ||||
|             return GetVARegions(input, output); | ||||
|             return WrapFixed(this, &nvhost_as_gpu::GetVARegions1, input, output); | ||||
|         case 0x9: | ||||
|             return AllocAsEx(input, output); | ||||
|             return WrapFixed(this, &nvhost_as_gpu::AllocAsEx, input, output); | ||||
|         case 0x14: | ||||
|             return Remap(input, output); | ||||
|             return WrapVariable(this, &nvhost_as_gpu::Remap, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -72,7 +73,8 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i | ||||
|     case 'A': | ||||
|         switch (command.cmd) { | ||||
|         case 0x8: | ||||
|             return GetVARegions(input, output, inline_output); | ||||
|             return WrapFixedInlOut(this, &nvhost_as_gpu::GetVARegions3, input, output, | ||||
|                                    inline_output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -87,10 +89,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i | ||||
| void nvhost_as_gpu::OnOpen(DeviceFD fd) {} | ||||
| void nvhost_as_gpu::OnClose(DeviceFD fd) {} | ||||
|  | ||||
| NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlAllocAsEx params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|  | ||||
| NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size); | ||||
|  | ||||
|     std::scoped_lock lock(mutex); | ||||
| @@ -141,10 +140,7 @@ NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> outpu | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlAllocSpace params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|  | ||||
| NvResult nvhost_as_gpu::AllocateSpace(IoctlAllocSpace& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages, | ||||
|               params.page_size, params.flags); | ||||
|  | ||||
| @@ -194,7 +190,6 @@ NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> o | ||||
|         .big_pages = params.page_size != VM::YUZU_PAGESIZE, | ||||
|     }; | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| @@ -222,10 +217,7 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) { | ||||
|     mapping_map.erase(offset); | ||||
| } | ||||
|  | ||||
| NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlFreeSpace params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|  | ||||
| NvResult nvhost_as_gpu::FreeSpace(IoctlFreeSpace& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, offset={:X}, pages={:X}, page_size={:X}", params.offset, | ||||
|               params.pages, params.page_size); | ||||
|  | ||||
| @@ -264,18 +256,11 @@ NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> outpu | ||||
|         return NvResult::BadValue; | ||||
|     } | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) { | ||||
|     const auto num_entries = input.size() / sizeof(IoctlRemapEntry); | ||||
|  | ||||
|     LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries); | ||||
|  | ||||
|     std::scoped_lock lock(mutex); | ||||
|     entries.resize_destructive(num_entries); | ||||
|     std::memcpy(entries.data(), input.data(), input.size()); | ||||
| NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", entries.size()); | ||||
|  | ||||
|     if (!vm.initialised) { | ||||
|         return NvResult::BadValue; | ||||
| @@ -317,14 +302,10 @@ NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     std::memcpy(output.data(), entries.data(), output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlMapBufferEx params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|  | ||||
| NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, | ||||
|               "called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}" | ||||
|               ", offset={}", | ||||
| @@ -421,14 +402,10 @@ NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> out | ||||
|         mapping_map[params.offset] = mapping; | ||||
|     } | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlUnmapBuffer params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|  | ||||
| NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset); | ||||
|  | ||||
|     std::scoped_lock lock(mutex); | ||||
| @@ -464,9 +441,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> out | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlBindChannel params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
| NvResult nvhost_as_gpu::BindChannel(IoctlBindChannel& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); | ||||
|  | ||||
|     auto gpu_channel_device = module.GetDevice<nvhost_gpu>(params.fd); | ||||
| @@ -493,10 +468,7 @@ void nvhost_as_gpu::GetVARegionsImpl(IoctlGetVaRegions& params) { | ||||
|     }; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlGetVaRegions params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|  | ||||
| NvResult nvhost_as_gpu::GetVARegions1(IoctlGetVaRegions& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr, | ||||
|               params.buf_size); | ||||
|  | ||||
| @@ -508,15 +480,10 @@ NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> ou | ||||
|  | ||||
|     GetVARegionsImpl(params); | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output, | ||||
|                                      std::span<u8> inline_output) { | ||||
|     IoctlGetVaRegions params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|  | ||||
| NvResult nvhost_as_gpu::GetVARegions3(IoctlGetVaRegions& params, std::span<VaRegion> regions) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, buf_addr={:X}, buf_size={:X}", params.buf_addr, | ||||
|               params.buf_size); | ||||
|  | ||||
| @@ -528,9 +495,10 @@ NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> ou | ||||
|  | ||||
|     GetVARegionsImpl(params); | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     std::memcpy(inline_output.data(), ¶ms.regions[0], sizeof(VaRegion)); | ||||
|     std::memcpy(inline_output.data() + sizeof(VaRegion), ¶ms.regions[1], sizeof(VaRegion)); | ||||
|     const size_t num_regions = std::min(params.regions.size(), regions.size()); | ||||
|     for (size_t i = 0; i < num_regions; i++) { | ||||
|         regions[i] = params.regions[i]; | ||||
|     } | ||||
|  | ||||
|     return NvResult::Success; | ||||
| } | ||||
|   | ||||
| @@ -139,18 +139,17 @@ private: | ||||
|     static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2, | ||||
|                   "IoctlGetVaRegions is incorrect size"); | ||||
|  | ||||
|     NvResult AllocAsEx(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult AllocateSpace(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult Remap(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult MapBufferEx(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult FreeSpace(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult BindChannel(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult AllocAsEx(IoctlAllocAsEx& params); | ||||
|     NvResult AllocateSpace(IoctlAllocSpace& params); | ||||
|     NvResult Remap(std::span<IoctlRemapEntry> params); | ||||
|     NvResult MapBufferEx(IoctlMapBufferEx& params); | ||||
|     NvResult UnmapBuffer(IoctlUnmapBuffer& params); | ||||
|     NvResult FreeSpace(IoctlFreeSpace& params); | ||||
|     NvResult BindChannel(IoctlBindChannel& params); | ||||
|  | ||||
|     void GetVARegionsImpl(IoctlGetVaRegions& params); | ||||
|     NvResult GetVARegions(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult GetVARegions(std::span<const u8> input, std::span<u8> output, | ||||
|                           std::span<u8> inline_output); | ||||
|     NvResult GetVARegions1(IoctlGetVaRegions& params); | ||||
|     NvResult GetVARegions3(IoctlGetVaRegions& params, std::span<VaRegion> regions); | ||||
|  | ||||
|     void FreeMappingLocked(u64 offset); | ||||
|  | ||||
| @@ -213,7 +212,6 @@ private: | ||||
|         bool initialised{}; | ||||
|     } vm; | ||||
|     std::shared_ptr<Tegra::MemoryManager> gmmu; | ||||
|     Common::ScratchBuffer<IoctlRemapEntry> entries; | ||||
|  | ||||
|     // s32 channel{}; | ||||
|     // u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE}; | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| #include "core/hle/kernel/k_event.h" | ||||
| #include "core/hle/service/nvdrv/core/container.h" | ||||
| #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | ||||
| #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" | ||||
| #include "video_core/gpu.h" | ||||
| #include "video_core/host1x/host1x.h" | ||||
| @@ -40,19 +41,19 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inp | ||||
|     case 0x0: | ||||
|         switch (command.cmd) { | ||||
|         case 0x1b: | ||||
|             return NvOsGetConfigU32(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl::NvOsGetConfigU32, input, output); | ||||
|         case 0x1c: | ||||
|             return IocCtrlClearEventWait(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl::IocCtrlClearEventWait, input, output); | ||||
|         case 0x1d: | ||||
|             return IocCtrlEventWait(input, output, true); | ||||
|             return WrapFixed(this, &nvhost_ctrl::IocCtrlEventWait, input, output, true); | ||||
|         case 0x1e: | ||||
|             return IocCtrlEventWait(input, output, false); | ||||
|             return WrapFixed(this, &nvhost_ctrl::IocCtrlEventWait, input, output, false); | ||||
|         case 0x1f: | ||||
|             return IocCtrlEventRegister(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl::IocCtrlEventRegister, input, output); | ||||
|         case 0x20: | ||||
|             return IocCtrlEventUnregister(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl::IocCtrlEventUnregister, input, output); | ||||
|         case 0x21: | ||||
|             return IocCtrlEventUnregisterBatch(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl::IocCtrlEventUnregisterBatch, input, output); | ||||
|         } | ||||
|         break; | ||||
|     default: | ||||
| @@ -79,25 +80,19 @@ void nvhost_ctrl::OnOpen(DeviceFD fd) {} | ||||
|  | ||||
| void nvhost_ctrl::OnClose(DeviceFD fd) {} | ||||
|  | ||||
| NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output) { | ||||
|     IocGetConfigParams params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
| NvResult nvhost_ctrl::NvOsGetConfigU32(IocGetConfigParams& params) { | ||||
|     LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), | ||||
|               params.param_str.data()); | ||||
|     return NvResult::ConfigVarNotFound; // Returns error on production mode | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, | ||||
|                                        bool is_allocation) { | ||||
|     IocCtrlEventWaitParams params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
| NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_allocation) { | ||||
|     LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_allocation={}", | ||||
|               params.fence.id, params.fence.value, params.timeout, is_allocation); | ||||
|  | ||||
|     bool must_unmark_fail = !is_allocation; | ||||
|     const u32 event_id = params.value.raw; | ||||
|     SCOPE_EXIT({ | ||||
|         std::memcpy(output.data(), ¶ms, sizeof(params)); | ||||
|         if (must_unmark_fail) { | ||||
|             events[event_id].fails = 0; | ||||
|         } | ||||
| @@ -231,9 +226,7 @@ NvResult nvhost_ctrl::FreeEvent(u32 slot) { | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output) { | ||||
|     IocCtrlEventRegisterParams params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
| NvResult nvhost_ctrl::IocCtrlEventRegister(IocCtrlEventRegisterParams& params) { | ||||
|     const u32 event_id = params.user_event_id; | ||||
|     LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); | ||||
|     if (event_id >= MaxNvEvents) { | ||||
| @@ -252,9 +245,7 @@ NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span< | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output) { | ||||
|     IocCtrlEventUnregisterParams params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
| NvResult nvhost_ctrl::IocCtrlEventUnregister(IocCtrlEventUnregisterParams& params) { | ||||
|     const u32 event_id = params.user_event_id & 0x00FF; | ||||
|     LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id); | ||||
|  | ||||
| @@ -262,9 +253,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::spa | ||||
|     return FreeEvent(event_id); | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output) { | ||||
|     IocCtrlEventUnregisterBatchParams params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
| NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(IocCtrlEventUnregisterBatchParams& params) { | ||||
|     u64 event_mask = params.user_events; | ||||
|     LOG_DEBUG(Service_NVDRV, " called, event_mask: {:X}", event_mask); | ||||
|  | ||||
| @@ -280,10 +269,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output) { | ||||
|     IocCtrlEventClearParams params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
|  | ||||
| NvResult nvhost_ctrl::IocCtrlClearEventWait(IocCtrlEventClearParams& params) { | ||||
|     u32 event_id = params.event_id.slot; | ||||
|     LOG_DEBUG(Service_NVDRV, "called, event_id: {:X}", event_id); | ||||
|  | ||||
|   | ||||
| @@ -186,12 +186,12 @@ private: | ||||
|     static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8, | ||||
|                   "IocCtrlEventKill is incorrect size"); | ||||
|  | ||||
|     NvResult NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, bool is_allocation); | ||||
|     NvResult IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult NvOsGetConfigU32(IocGetConfigParams& params); | ||||
|     NvResult IocCtrlEventRegister(IocCtrlEventRegisterParams& params); | ||||
|     NvResult IocCtrlEventUnregister(IocCtrlEventUnregisterParams& params); | ||||
|     NvResult IocCtrlEventUnregisterBatch(IocCtrlEventUnregisterBatchParams& params); | ||||
|     NvResult IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_allocation); | ||||
|     NvResult IocCtrlClearEventWait(IocCtrlEventClearParams& params); | ||||
|  | ||||
|     NvResult FreeEvent(u32 slot); | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include "common/logging/log.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" | ||||
| #include "core/hle/service/nvdrv/nvdrv.h" | ||||
|  | ||||
| @@ -27,23 +28,23 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> | ||||
|     case 'G': | ||||
|         switch (command.cmd) { | ||||
|         case 0x1: | ||||
|             return ZCullGetCtxSize(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl_gpu::ZCullGetCtxSize, input, output); | ||||
|         case 0x2: | ||||
|             return ZCullGetInfo(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl_gpu::ZCullGetInfo, input, output); | ||||
|         case 0x3: | ||||
|             return ZBCSetTable(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl_gpu::ZBCSetTable, input, output); | ||||
|         case 0x4: | ||||
|             return ZBCQueryTable(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl_gpu::ZBCQueryTable, input, output); | ||||
|         case 0x5: | ||||
|             return GetCharacteristics(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl_gpu::GetCharacteristics1, input, output); | ||||
|         case 0x6: | ||||
|             return GetTPCMasks(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl_gpu::GetTPCMasks1, input, output); | ||||
|         case 0x7: | ||||
|             return FlushL2(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl_gpu::FlushL2, input, output); | ||||
|         case 0x14: | ||||
|             return GetActiveSlotMask(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl_gpu::GetActiveSlotMask, input, output); | ||||
|         case 0x1c: | ||||
|             return GetGpuTime(input, output); | ||||
|             return WrapFixed(this, &nvhost_ctrl_gpu::GetGpuTime, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -65,9 +66,11 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> | ||||
|     case 'G': | ||||
|         switch (command.cmd) { | ||||
|         case 0x5: | ||||
|             return GetCharacteristics(input, output, inline_output); | ||||
|             return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetCharacteristics3, input, output, | ||||
|                                    inline_output); | ||||
|         case 0x6: | ||||
|             return GetTPCMasks(input, output, inline_output); | ||||
|             return WrapFixedInlOut(this, &nvhost_ctrl_gpu::GetTPCMasks3, input, output, | ||||
|                                    inline_output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -82,10 +85,8 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> | ||||
| void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {} | ||||
| void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvhost_ctrl_gpu::GetCharacteristics1(IoctlCharacteristics& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called"); | ||||
|     IoctlCharacteristics params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|     params.gc.arch = 0x120; | ||||
|     params.gc.impl = 0xb; | ||||
|     params.gc.rev = 0xa1; | ||||
| @@ -123,15 +124,13 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::spa | ||||
|     params.gc.gr_compbit_store_base_hw = 0x0; | ||||
|     params.gpu_characteristics_buf_size = 0xA0; | ||||
|     params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output, | ||||
|                                              std::span<u8> inline_output) { | ||||
| NvResult nvhost_ctrl_gpu::GetCharacteristics3( | ||||
|     IoctlCharacteristics& params, std::span<IoctlGpuCharacteristics> gpu_characteristics) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called"); | ||||
|     IoctlCharacteristics params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|  | ||||
|     params.gc.arch = 0x120; | ||||
|     params.gc.impl = 0xb; | ||||
|     params.gc.rev = 0xa1; | ||||
| @@ -169,70 +168,47 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::spa | ||||
|     params.gc.gr_compbit_store_base_hw = 0x0; | ||||
|     params.gpu_characteristics_buf_size = 0xA0; | ||||
|     params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     std::memcpy(inline_output.data(), ¶ms.gc, inline_output.size()); | ||||
|     if (!gpu_characteristics.empty()) { | ||||
|         gpu_characteristics.front() = params.gc; | ||||
|     } | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlGpuGetTpcMasksArgs params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
| NvResult nvhost_ctrl_gpu::GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); | ||||
|     if (params.mask_buffer_size != 0) { | ||||
|         params.tcp_mask = 3; | ||||
|     } | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output, | ||||
|                                       std::span<u8> inline_output) { | ||||
|     IoctlGpuGetTpcMasksArgs params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
| NvResult nvhost_ctrl_gpu::GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); | ||||
|     if (params.mask_buffer_size != 0) { | ||||
|         params.tcp_mask = 3; | ||||
|     } | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     std::memcpy(inline_output.data(), ¶ms.tcp_mask, inline_output.size()); | ||||
|     if (!tpc_mask.empty()) { | ||||
|         tpc_mask.front() = params.tcp_mask; | ||||
|     } | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvhost_ctrl_gpu::GetActiveSlotMask(IoctlActiveSlotMask& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called"); | ||||
|  | ||||
|     IoctlActiveSlotMask params{}; | ||||
|     if (input.size() > 0) { | ||||
|         std::memcpy(¶ms, input.data(), input.size()); | ||||
|     } | ||||
|     params.slot = 0x07; | ||||
|     params.mask = 0x01; | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(IoctlZcullGetCtxSize& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called"); | ||||
|  | ||||
|     IoctlZcullGetCtxSize params{}; | ||||
|     if (input.size() > 0) { | ||||
|         std::memcpy(¶ms, input.data(), input.size()); | ||||
|     } | ||||
|     params.size = 0x1; | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvhost_ctrl_gpu::ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called"); | ||||
|  | ||||
|     IoctlNvgpuGpuZcullGetInfoArgs params{}; | ||||
|  | ||||
|     if (input.size() > 0) { | ||||
|         std::memcpy(¶ms, input.data(), input.size()); | ||||
|     } | ||||
|  | ||||
|     params.width_align_pixels = 0x20; | ||||
|     params.height_align_pixels = 0x20; | ||||
|     params.pixel_squares_by_aliquots = 0x400; | ||||
| @@ -243,53 +219,28 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8> | ||||
|     params.subregion_width_align_pixels = 0x20; | ||||
|     params.subregion_height_align_pixels = 0x40; | ||||
|     params.subregion_count = 0x10; | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) { | ||||
|     LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | ||||
|  | ||||
|     IoctlZbcSetTable params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|     // TODO(ogniK): What does this even actually do? | ||||
|  | ||||
|     // Prevent null pointer being passed as arg 1 | ||||
|     if (output.empty()) { | ||||
|         LOG_WARNING(Service_NVDRV, "Avoiding passing null pointer to memcpy"); | ||||
|     } else { | ||||
|         std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     } | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) { | ||||
|     LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | ||||
|  | ||||
|     IoctlZbcQueryTable params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|     // TODO : To implement properly | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvhost_ctrl_gpu::FlushL2(IoctlFlushL2& params) { | ||||
|     LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | ||||
|  | ||||
|     IoctlFlushL2 params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|     // TODO : To implement properly | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvhost_ctrl_gpu::GetGpuTime(IoctlGetGpuTime& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called"); | ||||
|  | ||||
|     IoctlGetGpuTime params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|     params.gpu_time = static_cast<u64_le>(system.CoreTiming().GetGlobalTimeNs().count()); | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -151,21 +151,20 @@ private: | ||||
|     }; | ||||
|     static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); | ||||
|  | ||||
|     NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output, | ||||
|                                 std::span<u8> inline_output); | ||||
|     NvResult GetCharacteristics1(IoctlCharacteristics& params); | ||||
|     NvResult GetCharacteristics3(IoctlCharacteristics& params, | ||||
|                                  std::span<IoctlGpuCharacteristics> gpu_characteristics); | ||||
|  | ||||
|     NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output, | ||||
|                          std::span<u8> inline_output); | ||||
|     NvResult GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params); | ||||
|     NvResult GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask); | ||||
|  | ||||
|     NvResult GetActiveSlotMask(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult ZCullGetInfo(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult ZBCSetTable(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult ZBCQueryTable(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult FlushL2(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult GetGpuTime(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult GetActiveSlotMask(IoctlActiveSlotMask& params); | ||||
|     NvResult ZCullGetCtxSize(IoctlZcullGetCtxSize& params); | ||||
|     NvResult ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params); | ||||
|     NvResult ZBCSetTable(IoctlZbcSetTable& params); | ||||
|     NvResult ZBCQueryTable(IoctlZbcQueryTable& params); | ||||
|     NvResult FlushL2(IoctlFlushL2& params); | ||||
|     NvResult GetGpuTime(IoctlGetGpuTime& params); | ||||
|  | ||||
|     EventInterface& events_interface; | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include "core/hle/service/nvdrv/core/container.h" | ||||
| #include "core/hle/service/nvdrv/core/nvmap.h" | ||||
| #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | ||||
| #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" | ||||
| #include "core/hle/service/nvdrv/nvdrv.h" | ||||
| #include "core/memory.h" | ||||
| @@ -52,7 +53,7 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | ||||
|     case 0x0: | ||||
|         switch (command.cmd) { | ||||
|         case 0x3: | ||||
|             return GetWaitbase(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::GetWaitbase, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -60,25 +61,25 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | ||||
|     case 'H': | ||||
|         switch (command.cmd) { | ||||
|         case 0x1: | ||||
|             return SetNVMAPfd(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::SetNVMAPfd, input, output); | ||||
|         case 0x3: | ||||
|             return ChannelSetTimeout(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::ChannelSetTimeout, input, output); | ||||
|         case 0x8: | ||||
|             return SubmitGPFIFOBase(input, output, false); | ||||
|             return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, false); | ||||
|         case 0x9: | ||||
|             return AllocateObjectContext(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::AllocateObjectContext, input, output); | ||||
|         case 0xb: | ||||
|             return ZCullBind(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::ZCullBind, input, output); | ||||
|         case 0xc: | ||||
|             return SetErrorNotifier(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::SetErrorNotifier, input, output); | ||||
|         case 0xd: | ||||
|             return SetChannelPriority(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::SetChannelPriority, input, output); | ||||
|         case 0x1a: | ||||
|             return AllocGPFIFOEx2(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx2, input, output); | ||||
|         case 0x1b: | ||||
|             return SubmitGPFIFOBase(input, output, true); | ||||
|             return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, true); | ||||
|         case 0x1d: | ||||
|             return ChannelSetTimeslice(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::ChannelSetTimeslice, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -86,9 +87,9 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | ||||
|     case 'G': | ||||
|         switch (command.cmd) { | ||||
|         case 0x14: | ||||
|             return SetClientData(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::SetClientData, input, output); | ||||
|         case 0x15: | ||||
|             return GetClientData(input, output); | ||||
|             return WrapFixed(this, &nvhost_gpu::GetClientData, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -104,7 +105,8 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> inpu | ||||
|     case 'H': | ||||
|         switch (command.cmd) { | ||||
|         case 0x1b: | ||||
|             return SubmitGPFIFOBase(input, inline_input, output); | ||||
|             return WrapFixedInlIn(this, &nvhost_gpu::SubmitGPFIFOBase2, input, inline_input, | ||||
|                                   output); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
| @@ -121,63 +123,45 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu | ||||
| void nvhost_gpu::OnOpen(DeviceFD fd) {} | ||||
| void nvhost_gpu::OnClose(DeviceFD fd) {} | ||||
|  | ||||
| NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlSetNvmapFD params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
| NvResult nvhost_gpu::SetNVMAPfd(IoctlSetNvmapFD& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | ||||
|  | ||||
|     nvmap_fd = params.nvmap_fd; | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvhost_gpu::SetClientData(IoctlClientData& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called"); | ||||
|  | ||||
|     IoctlClientData params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|     user_data = params.data; | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvhost_gpu::GetClientData(IoctlClientData& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called"); | ||||
|  | ||||
|     IoctlClientData params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
|     params.data = user_data; | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::span<u8> output) { | ||||
|     std::memcpy(&zcull_params, input.data(), input.size()); | ||||
| NvResult nvhost_gpu::ZCullBind(IoctlZCullBind& params) { | ||||
|     zcull_params = params; | ||||
|     LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va, | ||||
|               zcull_params.mode); | ||||
|  | ||||
|     std::memcpy(output.data(), &zcull_params, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlSetErrorNotifier params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
| NvResult nvhost_gpu::SetErrorNotifier(IoctlSetErrorNotifier& params) { | ||||
|     LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, | ||||
|                 params.size, params.mem); | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::span<u8> output) { | ||||
|     std::memcpy(&channel_priority, input.data(), input.size()); | ||||
| NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) { | ||||
|     channel_priority = params.priority; | ||||
|     LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); | ||||
|  | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlAllocGpfifoEx2 params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
| NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params) { | ||||
|     LOG_WARNING(Service_NVDRV, | ||||
|                 "(STUBBED) called, num_entries={:X}, flags={:X}, unk0={:X}, " | ||||
|                 "unk1={:X}, unk2={:X}, unk3={:X}", | ||||
| @@ -193,18 +177,14 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> out | ||||
|  | ||||
|     params.fence_out = syncpoint_manager.GetSyncpointFence(channel_syncpoint); | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlAllocObjCtx params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
| NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) { | ||||
|     LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, | ||||
|                 params.flags); | ||||
|  | ||||
|     params.obj_id = 0x0; | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| @@ -248,8 +228,7 @@ static boost::container::small_vector<Tegra::CommandHeader, 512> BuildIncrementW | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output, | ||||
|                                       Tegra::CommandList&& entries) { | ||||
| NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries) { | ||||
|     LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address, | ||||
|               params.num_entries, params.flags.raw); | ||||
|  | ||||
| @@ -290,65 +269,55 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> o | ||||
|  | ||||
|     flags.raw = 0; | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmitGpfifo)); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output, | ||||
|                                       bool kickoff) { | ||||
|     if (input.size() < sizeof(IoctlSubmitGpfifo)) { | ||||
| NvResult nvhost_gpu::SubmitGPFIFOBase1(IoctlSubmitGpfifo& params, | ||||
|                                        std::span<Tegra::CommandListHeader> commands, bool kickoff) { | ||||
|     if (params.num_entries > commands.size()) { | ||||
|         UNIMPLEMENTED(); | ||||
|         return NvResult::InvalidSize; | ||||
|     } | ||||
|     IoctlSubmitGpfifo params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | ||||
|     Tegra::CommandList entries(params.num_entries); | ||||
|  | ||||
|     Tegra::CommandList entries(params.num_entries); | ||||
|     if (kickoff) { | ||||
|         system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(), | ||||
|                                              params.num_entries * sizeof(Tegra::CommandListHeader)); | ||||
|     } else { | ||||
|         std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], | ||||
|         std::memcpy(entries.command_lists.data(), commands.data(), | ||||
|                     params.num_entries * sizeof(Tegra::CommandListHeader)); | ||||
|     } | ||||
|  | ||||
|     return SubmitGPFIFOImpl(params, output, std::move(entries)); | ||||
|     return SubmitGPFIFOImpl(params, std::move(entries)); | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, | ||||
|                                       std::span<u8> output) { | ||||
|     if (input.size() < sizeof(IoctlSubmitGpfifo)) { | ||||
| NvResult nvhost_gpu::SubmitGPFIFOBase2(IoctlSubmitGpfifo& params, | ||||
|                                        std::span<const Tegra::CommandListHeader> commands) { | ||||
|     if (params.num_entries > commands.size()) { | ||||
|         UNIMPLEMENTED(); | ||||
|         return NvResult::InvalidSize; | ||||
|     } | ||||
|     IoctlSubmitGpfifo params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); | ||||
|  | ||||
|     Tegra::CommandList entries(params.num_entries); | ||||
|     std::memcpy(entries.command_lists.data(), input_inline.data(), input_inline.size()); | ||||
|     return SubmitGPFIFOImpl(params, output, std::move(entries)); | ||||
|     std::memcpy(entries.command_lists.data(), commands.data(), | ||||
|                 params.num_entries * sizeof(Tegra::CommandListHeader)); | ||||
|     return SubmitGPFIFOImpl(params, std::move(entries)); | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlGetWaitbase params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); | ||||
| NvResult nvhost_gpu::GetWaitbase(IoctlGetWaitbase& params) { | ||||
|     LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); | ||||
|  | ||||
|     params.value = 0; // Seems to be hard coded at 0 | ||||
|     std::memcpy(output.data(), ¶ms, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlChannelSetTimeout params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlChannelSetTimeout)); | ||||
| NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) { | ||||
|     LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); | ||||
|  | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlSetTimeslice params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlSetTimeslice)); | ||||
| NvResult nvhost_gpu::ChannelSetTimeslice(IoctlSetTimeslice& params) { | ||||
|     LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); | ||||
|  | ||||
|     channel_timeslice = params.timeslice; | ||||
|   | ||||
| @@ -186,23 +186,24 @@ private: | ||||
|     u32_le channel_priority{}; | ||||
|     u32_le channel_timeslice{}; | ||||
|  | ||||
|     NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult SetClientData(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult GetClientData(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult ZCullBind(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult SetErrorNotifier(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult SetChannelPriority(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult AllocateObjectContext(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output, | ||||
|                               Tegra::CommandList&& entries); | ||||
|     NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output, | ||||
|                               bool kickoff = false); | ||||
|     NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline, | ||||
|                               std::span<u8> output); | ||||
|     NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult ChannelSetTimeout(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult SetNVMAPfd(IoctlSetNvmapFD& params); | ||||
|     NvResult SetClientData(IoctlClientData& params); | ||||
|     NvResult GetClientData(IoctlClientData& params); | ||||
|     NvResult ZCullBind(IoctlZCullBind& params); | ||||
|     NvResult SetErrorNotifier(IoctlSetErrorNotifier& params); | ||||
|     NvResult SetChannelPriority(IoctlChannelSetPriority& params); | ||||
|     NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params); | ||||
|     NvResult AllocateObjectContext(IoctlAllocObjCtx& params); | ||||
|  | ||||
|     NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries); | ||||
|     NvResult SubmitGPFIFOBase1(IoctlSubmitGpfifo& params, | ||||
|                                std::span<Tegra::CommandListHeader> commands, bool kickoff = false); | ||||
|     NvResult SubmitGPFIFOBase2(IoctlSubmitGpfifo& params, | ||||
|                                std::span<const Tegra::CommandListHeader> commands); | ||||
|  | ||||
|     NvResult GetWaitbase(IoctlGetWaitbase& params); | ||||
|     NvResult ChannelSetTimeout(IoctlChannelSetTimeout& params); | ||||
|     NvResult ChannelSetTimeslice(IoctlSetTimeslice& params); | ||||
|  | ||||
|     EventInterface& events_interface; | ||||
|     NvCore::Container& core; | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include "common/logging/log.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/service/nvdrv/core/container.h" | ||||
| #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" | ||||
| #include "video_core/renderer_base.h" | ||||
|  | ||||
| @@ -25,18 +26,18 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in | ||||
|             if (!host1x_file.fd_to_id.contains(fd)) { | ||||
|                 host1x_file.fd_to_id[fd] = host1x_file.nvdec_next_id++; | ||||
|             } | ||||
|             return Submit(fd, input, output); | ||||
|             return WrapFixedVariable(this, &nvhost_nvdec::Submit, input, output, fd); | ||||
|         } | ||||
|         case 0x2: | ||||
|             return GetSyncpoint(input, output); | ||||
|             return WrapFixed(this, &nvhost_nvdec::GetSyncpoint, input, output); | ||||
|         case 0x3: | ||||
|             return GetWaitbase(input, output); | ||||
|             return WrapFixed(this, &nvhost_nvdec::GetWaitbase, input, output); | ||||
|         case 0x7: | ||||
|             return SetSubmitTimeout(input, output); | ||||
|             return WrapFixed(this, &nvhost_nvdec::SetSubmitTimeout, input, output); | ||||
|         case 0x9: | ||||
|             return MapBuffer(input, output); | ||||
|             return WrapFixedVariable(this, &nvhost_nvdec::MapBuffer, input, output); | ||||
|         case 0xa: | ||||
|             return UnmapBuffer(input, output); | ||||
|             return WrapFixedVariable(this, &nvhost_nvdec::UnmapBuffer, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -44,7 +45,7 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in | ||||
|     case 'H': | ||||
|         switch (command.cmd) { | ||||
|         case 0x1: | ||||
|             return SetNVMAPfd(input); | ||||
|             return WrapFixed(this, &nvhost_nvdec::SetNVMAPfd, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|   | ||||
| @@ -29,6 +29,9 @@ std::size_t SliceVectors(std::span<const u8> input, std::vector<T>& dst, std::si | ||||
|         return 0; | ||||
|     } | ||||
|     const size_t bytes_copied = count * sizeof(T); | ||||
|     if (input.size() < offset + bytes_copied) { | ||||
|         return 0; | ||||
|     } | ||||
|     std::memcpy(dst.data(), input.data() + offset, bytes_copied); | ||||
|     return bytes_copied; | ||||
| } | ||||
| @@ -41,6 +44,9 @@ std::size_t WriteVectors(std::span<u8> dst, const std::vector<T>& src, std::size | ||||
|         return 0; | ||||
|     } | ||||
|     const size_t bytes_copied = src.size() * sizeof(T); | ||||
|     if (dst.size() < offset + bytes_copied) { | ||||
|         return 0; | ||||
|     } | ||||
|     std::memcpy(dst.data() + offset, src.data(), bytes_copied); | ||||
|     return bytes_copied; | ||||
| } | ||||
| @@ -63,18 +69,14 @@ nvhost_nvdec_common::~nvhost_nvdec_common() { | ||||
|     core.Host1xDeviceFile().syncpts_accumulated.push_back(channel_syncpoint); | ||||
| } | ||||
|  | ||||
| NvResult nvhost_nvdec_common::SetNVMAPfd(std::span<const u8> input) { | ||||
|     IoctlSetNvmapFD params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD)); | ||||
| NvResult nvhost_nvdec_common::SetNVMAPfd(IoctlSetNvmapFD& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | ||||
|  | ||||
|     nvmap_fd = params.nvmap_fd; | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlSubmit params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); | ||||
| NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, DeviceFD fd) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); | ||||
|  | ||||
|     // Instantiate param buffers | ||||
| @@ -85,12 +87,12 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std | ||||
|     std::vector<u32> fence_thresholds(params.fence_count); | ||||
|  | ||||
|     // Slice input into their respective buffers | ||||
|     std::size_t offset = sizeof(IoctlSubmit); | ||||
|     offset += SliceVectors(input, command_buffers, params.cmd_buffer_count, offset); | ||||
|     offset += SliceVectors(input, relocs, params.relocation_count, offset); | ||||
|     offset += SliceVectors(input, reloc_shifts, params.relocation_count, offset); | ||||
|     offset += SliceVectors(input, syncpt_increments, params.syncpoint_count, offset); | ||||
|     offset += SliceVectors(input, fence_thresholds, params.fence_count, offset); | ||||
|     std::size_t offset = 0; | ||||
|     offset += SliceVectors(data, command_buffers, params.cmd_buffer_count, offset); | ||||
|     offset += SliceVectors(data, relocs, params.relocation_count, offset); | ||||
|     offset += SliceVectors(data, reloc_shifts, params.relocation_count, offset); | ||||
|     offset += SliceVectors(data, syncpt_increments, params.syncpoint_count, offset); | ||||
|     offset += SliceVectors(data, fence_thresholds, params.fence_count, offset); | ||||
|  | ||||
|     auto& gpu = system.GPU(); | ||||
|     if (gpu.UseNvdec()) { | ||||
| @@ -108,72 +110,51 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std | ||||
|                                              cmdlist.size() * sizeof(u32)); | ||||
|         gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); | ||||
|     } | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); | ||||
|     // Some games expect command_buffers to be written back | ||||
|     offset = sizeof(IoctlSubmit); | ||||
|     offset += WriteVectors(output, command_buffers, offset); | ||||
|     offset += WriteVectors(output, relocs, offset); | ||||
|     offset += WriteVectors(output, reloc_shifts, offset); | ||||
|     offset += WriteVectors(output, syncpt_increments, offset); | ||||
|     offset += WriteVectors(output, fence_thresholds, offset); | ||||
|     offset = 0; | ||||
|     offset += WriteVectors(data, command_buffers, offset); | ||||
|     offset += WriteVectors(data, relocs, offset); | ||||
|     offset += WriteVectors(data, reloc_shifts, offset); | ||||
|     offset += WriteVectors(data, syncpt_increments, offset); | ||||
|     offset += WriteVectors(data, fence_thresholds, offset); | ||||
|  | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlGetSyncpoint params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint)); | ||||
| NvResult nvhost_nvdec_common::GetSyncpoint(IoctlGetSyncpoint& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); | ||||
|  | ||||
|     // const u32 id{NvCore::SyncpointManager::channel_syncpoints[static_cast<u32>(channel_type)]}; | ||||
|     params.value = channel_syncpoint; | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint)); | ||||
|  | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlGetWaitbase params{}; | ||||
| NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) { | ||||
|     LOG_CRITICAL(Service_NVDRV, "called WAITBASE"); | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); | ||||
|     params.value = 0; // Seems to be hard coded at 0 | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase)); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlMapBuffer params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | ||||
|     std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | ||||
|  | ||||
|     SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | ||||
|  | ||||
|     for (auto& cmd_buffer : cmd_buffer_handles) { | ||||
|         cmd_buffer.map_address = nvmap.PinHandle(cmd_buffer.map_handle); | ||||
|     } | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer)); | ||||
|     std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(), | ||||
|                 cmd_buffer_handles.size() * sizeof(MapBufferEntry)); | ||||
|  | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlMapBuffer params{}; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | ||||
|     std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | ||||
|  | ||||
|     SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | ||||
|     for (auto& cmd_buffer : cmd_buffer_handles) { | ||||
|         nvmap.UnpinHandle(cmd_buffer.map_handle); | ||||
| NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries) { | ||||
|     const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size())); | ||||
|     for (size_t i = 0; i < num_entries; i++) { | ||||
|         entries[i].map_address = nvmap.PinHandle(entries[i].map_handle); | ||||
|     } | ||||
|  | ||||
|     std::memset(output.data(), 0, output.size()); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::span<u8> output) { | ||||
|     std::memcpy(&submit_timeout, input.data(), input.size()); | ||||
| NvResult nvhost_nvdec_common::UnmapBuffer(IoctlMapBuffer& params, | ||||
|                                           std::span<MapBufferEntry> entries) { | ||||
|     const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size())); | ||||
|     for (size_t i = 0; i < num_entries; i++) { | ||||
|         nvmap.UnpinHandle(entries[i].map_handle); | ||||
|         entries[i] = {}; | ||||
|     } | ||||
|  | ||||
|     params = {}; | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvhost_nvdec_common::SetSubmitTimeout(u32 timeout) { | ||||
|     LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|   | ||||
| @@ -107,13 +107,13 @@ protected: | ||||
|     static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); | ||||
|  | ||||
|     /// Ioctl command implementations | ||||
|     NvResult SetNVMAPfd(std::span<const u8> input); | ||||
|     NvResult Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult GetSyncpoint(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult MapBuffer(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult SetSubmitTimeout(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult SetNVMAPfd(IoctlSetNvmapFD&); | ||||
|     NvResult Submit(IoctlSubmit& params, std::span<u8> input, DeviceFD fd); | ||||
|     NvResult GetSyncpoint(IoctlGetSyncpoint& params); | ||||
|     NvResult GetWaitbase(IoctlGetWaitbase& params); | ||||
|     NvResult MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); | ||||
|     NvResult UnmapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); | ||||
|     NvResult SetSubmitTimeout(u32 timeout); | ||||
|  | ||||
|     Kernel::KEvent* QueryEvent(u32 event_id) override; | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
|  | ||||
| #include "common/assert.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h" | ||||
|  | ||||
| namespace Service::Nvidia::Devices { | ||||
| @@ -18,7 +19,7 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in | ||||
|     case 'H': | ||||
|         switch (command.cmd) { | ||||
|         case 0x1: | ||||
|             return SetNVMAPfd(input, output); | ||||
|             return WrapFixed(this, &nvhost_nvjpg::SetNVMAPfd, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -46,9 +47,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in | ||||
| void nvhost_nvjpg::OnOpen(DeviceFD fd) {} | ||||
| void nvhost_nvjpg::OnClose(DeviceFD fd) {} | ||||
|  | ||||
| NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) { | ||||
|     IoctlSetNvmapFD params{}; | ||||
|     std::memcpy(¶ms, input.data(), input.size()); | ||||
| NvResult nvhost_nvjpg::SetNVMAPfd(IoctlSetNvmapFD& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); | ||||
|  | ||||
|     nvmap_fd = params.nvmap_fd; | ||||
|   | ||||
| @@ -33,7 +33,7 @@ private: | ||||
|  | ||||
|     s32_le nvmap_fd{}; | ||||
|  | ||||
|     NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult SetNVMAPfd(IoctlSetNvmapFD& params); | ||||
| }; | ||||
|  | ||||
| } // namespace Service::Nvidia::Devices | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #include "common/logging/log.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/service/nvdrv/core/container.h" | ||||
| #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_vic.h" | ||||
| #include "video_core/renderer_base.h" | ||||
|  | ||||
| @@ -25,16 +26,16 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | ||||
|             if (!host1x_file.fd_to_id.contains(fd)) { | ||||
|                 host1x_file.fd_to_id[fd] = host1x_file.vic_next_id++; | ||||
|             } | ||||
|             return Submit(fd, input, output); | ||||
|             return WrapFixedVariable(this, &nvhost_vic::Submit, input, output, fd); | ||||
|         } | ||||
|         case 0x2: | ||||
|             return GetSyncpoint(input, output); | ||||
|             return WrapFixed(this, &nvhost_vic::GetSyncpoint, input, output); | ||||
|         case 0x3: | ||||
|             return GetWaitbase(input, output); | ||||
|             return WrapFixed(this, &nvhost_vic::GetWaitbase, input, output); | ||||
|         case 0x9: | ||||
|             return MapBuffer(input, output); | ||||
|             return WrapFixedVariable(this, &nvhost_vic::MapBuffer, input, output); | ||||
|         case 0xa: | ||||
|             return UnmapBuffer(input, output); | ||||
|             return WrapFixedVariable(this, &nvhost_vic::UnmapBuffer, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -42,7 +43,7 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | ||||
|     case 'H': | ||||
|         switch (command.cmd) { | ||||
|         case 0x1: | ||||
|             return SetNVMAPfd(input); | ||||
|             return WrapFixed(this, &nvhost_vic::SetNVMAPfd, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| #include "core/hle/kernel/k_process.h" | ||||
| #include "core/hle/service/nvdrv/core/container.h" | ||||
| #include "core/hle/service/nvdrv/core/nvmap.h" | ||||
| #include "core/hle/service/nvdrv/devices/ioctl_serialization.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvmap.h" | ||||
| #include "core/memory.h" | ||||
|  | ||||
| @@ -31,17 +32,17 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, | ||||
|     case 0x1: | ||||
|         switch (command.cmd) { | ||||
|         case 0x1: | ||||
|             return IocCreate(input, output); | ||||
|             return WrapFixed(this, &nvmap::IocCreate, input, output); | ||||
|         case 0x3: | ||||
|             return IocFromId(input, output); | ||||
|             return WrapFixed(this, &nvmap::IocFromId, input, output); | ||||
|         case 0x4: | ||||
|             return IocAlloc(input, output); | ||||
|             return WrapFixed(this, &nvmap::IocAlloc, input, output); | ||||
|         case 0x5: | ||||
|             return IocFree(input, output); | ||||
|             return WrapFixed(this, &nvmap::IocFree, input, output); | ||||
|         case 0x9: | ||||
|             return IocParam(input, output); | ||||
|             return WrapFixed(this, &nvmap::IocParam, input, output); | ||||
|         case 0xe: | ||||
|             return IocGetId(input, output); | ||||
|             return WrapFixed(this, &nvmap::IocGetId, input, output); | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| @@ -69,9 +70,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, st | ||||
| void nvmap::OnOpen(DeviceFD fd) {} | ||||
| void nvmap::OnClose(DeviceFD fd) {} | ||||
|  | ||||
| NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) { | ||||
|     IocCreateParams params; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
| NvResult nvmap::IocCreate(IocCreateParams& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); | ||||
|  | ||||
|     std::shared_ptr<NvCore::NvMap::Handle> handle_description{}; | ||||
| @@ -85,13 +84,10 @@ NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) { | ||||
|     params.handle = handle_description->id; | ||||
|     LOG_DEBUG(Service_NVDRV, "handle: {}, size: 0x{:X}", handle_description->id, params.size); | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(params)); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) { | ||||
|     IocAllocParams params; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
| NvResult nvmap::IocAlloc(IocAllocParams& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); | ||||
|  | ||||
|     if (!params.handle) { | ||||
| @@ -133,14 +129,10 @@ NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) { | ||||
|                                              handle_description->size, | ||||
|                                              Kernel::KMemoryPermission::None, true, false) | ||||
|                .IsSuccess()); | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(params)); | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| NvResult nvmap::IocGetId(std::span<const u8> input, std::span<u8> output) { | ||||
|     IocGetIdParams params; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
|  | ||||
| NvResult nvmap::IocGetId(IocGetIdParams& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called"); | ||||
|  | ||||
|     // 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) { | ||||
|     } | ||||
|  | ||||
|     params.id = handle_description->id; | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(params)); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvmap::IocFromId(std::span<const u8> input, std::span<u8> output) { | ||||
|     IocFromIdParams params; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
|  | ||||
| NvResult nvmap::IocFromId(IocFromIdParams& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called, id:{}", params.id); | ||||
|  | ||||
|     // 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) { | ||||
|         return result; | ||||
|     } | ||||
|     params.handle = handle_description->id; | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(params)); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) { | ||||
| NvResult nvmap::IocParam(IocParamParams& params) { | ||||
|     enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; | ||||
|  | ||||
|     IocParamParams params; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
|  | ||||
|     LOG_DEBUG(Service_NVDRV, "called type={}", params.param); | ||||
|  | ||||
|     if (!params.handle) { | ||||
| @@ -237,14 +221,10 @@ NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) { | ||||
|         return NvResult::BadValue; | ||||
|     } | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(params)); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
| NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) { | ||||
|     IocFreeParams params; | ||||
|     std::memcpy(¶ms, input.data(), sizeof(params)); | ||||
|  | ||||
| NvResult nvmap::IocFree(IocFreeParams& params) { | ||||
|     LOG_DEBUG(Service_NVDRV, "called"); | ||||
|  | ||||
|     if (!params.handle) { | ||||
| @@ -267,7 +247,6 @@ NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) { | ||||
|         // This is possible when there's internal dups or other duplicates. | ||||
|     } | ||||
|  | ||||
|     std::memcpy(output.data(), ¶ms, sizeof(params)); | ||||
|     return NvResult::Success; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -99,12 +99,12 @@ public: | ||||
|     }; | ||||
|     static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); | ||||
|  | ||||
|     NvResult IocCreate(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult IocAlloc(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult IocGetId(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult IocFromId(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult IocParam(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult IocFree(std::span<const u8> input, std::span<u8> output); | ||||
|     NvResult IocCreate(IocCreateParams& params); | ||||
|     NvResult IocAlloc(IocAllocParams& params); | ||||
|     NvResult IocGetId(IocGetIdParams& params); | ||||
|     NvResult IocFromId(IocFromIdParams& params); | ||||
|     NvResult IocParam(IocParamParams& params); | ||||
|     NvResult IocFree(IocFreeParams& params); | ||||
|  | ||||
| private: | ||||
|     /// Id to use for the next handle that is created. | ||||
|   | ||||
| @@ -71,24 +71,17 @@ Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address, | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| std::span<u8> SerializeIoc(T& params) { | ||||
|     return std::span(reinterpret_cast<u8*>(std::addressof(params)), sizeof(T)); | ||||
| } | ||||
|  | ||||
| Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) { | ||||
|     // Create a handle. | ||||
|     Nvidia::Devices::nvmap::IocCreateParams create_in_params{ | ||||
|     Nvidia::Devices::nvmap::IocCreateParams create_params{ | ||||
|         .size = size, | ||||
|         .handle = 0, | ||||
|     }; | ||||
|     Nvidia::Devices::nvmap::IocCreateParams create_out_params{}; | ||||
|     R_UNLESS(nvmap.IocCreate(SerializeIoc(create_in_params), SerializeIoc(create_out_params)) == | ||||
|                  Nvidia::NvResult::Success, | ||||
|     R_UNLESS(nvmap.IocCreate(create_params) == Nvidia::NvResult::Success, | ||||
|              VI::ResultOperationFailed); | ||||
|  | ||||
|     // Assign the output handle. | ||||
|     *out_nv_map_handle = create_out_params.handle; | ||||
|     *out_nv_map_handle = create_params.handle; | ||||
|  | ||||
|     // We succeeded. | ||||
|     R_SUCCEED(); | ||||
| @@ -96,13 +89,10 @@ Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, | ||||
|  | ||||
| Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) { | ||||
|     // Free the handle. | ||||
|     Nvidia::Devices::nvmap::IocFreeParams free_in_params{ | ||||
|     Nvidia::Devices::nvmap::IocFreeParams free_params{ | ||||
|         .handle = handle, | ||||
|     }; | ||||
|     Nvidia::Devices::nvmap::IocFreeParams free_out_params{}; | ||||
|     R_UNLESS(nvmap.IocFree(SerializeIoc(free_in_params), SerializeIoc(free_out_params)) == | ||||
|                  Nvidia::NvResult::Success, | ||||
|              VI::ResultOperationFailed); | ||||
|     R_UNLESS(nvmap.IocFree(free_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed); | ||||
|  | ||||
|     // We succeeded. | ||||
|     R_SUCCEED(); | ||||
| @@ -111,7 +101,7 @@ Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) { | ||||
| Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, | ||||
|                         u32 size) { | ||||
|     // Assign the allocated memory to the handle. | ||||
|     Nvidia::Devices::nvmap::IocAllocParams alloc_in_params{ | ||||
|     Nvidia::Devices::nvmap::IocAllocParams alloc_params{ | ||||
|         .handle = handle, | ||||
|         .heap_mask = 0, | ||||
|         .flags = {}, | ||||
| @@ -119,10 +109,7 @@ Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::Proce | ||||
|         .kind = 0, | ||||
|         .address = GetInteger(buffer), | ||||
|     }; | ||||
|     Nvidia::Devices::nvmap::IocAllocParams alloc_out_params{}; | ||||
|     R_UNLESS(nvmap.IocAlloc(SerializeIoc(alloc_in_params), SerializeIoc(alloc_out_params)) == | ||||
|                  Nvidia::NvResult::Success, | ||||
|              VI::ResultOperationFailed); | ||||
|     R_UNLESS(nvmap.IocAlloc(alloc_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed); | ||||
|  | ||||
|     // We succeeded. | ||||
|     R_SUCCEED(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user