diff options
Diffstat (limited to 'src/core')
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 @@ +// 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 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 @@  #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;  } 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:      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}; 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 @@  #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); 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:      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); 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 @@  #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;  } 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:      };      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 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 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 GetCharacteristics1(IoctlCharacteristics& params); +    NvResult GetCharacteristics3(IoctlCharacteristics& params, +                                 std::span<IoctlGpuCharacteristics> gpu_characteristics); + +    NvResult GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params); +    NvResult GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask); + +    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; 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 @@  #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; 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:      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; 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 @@  #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;          } 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          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); +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::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::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] = {};      } -    std::memset(output.data(), 0, output.size()); +    params = {};      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::SetSubmitTimeout(u32 timeout) {      LOG_WARNING(Service_NVDRV, "(STUBBED) called");      return NvResult::Success;  } 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:      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; 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 @@  #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; 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:      s32_le nvmap_fd{}; -    NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output); +    NvResult SetNVMAPfd(IoctlSetNvmapFD& params);  };  } // 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 @@  #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;          } 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 @@  #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;  } 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:      };      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. 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,      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(); | 
