From 04e5237ec19646f95b34ee709be8a9302a960924 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sun, 24 Oct 2021 16:16:23 +0100 Subject: [PATCH] Stub host1x channel devices and IOCTLs host1x channels are generally similar to GPU channels however there is only one channel for each specific class (like a GPU engine) and an address space is shared between them all. This PR implements the simple IOCTLs with the larger ones that will depend on changes outside of nvdrv being left for future commits. This is enough to partly run oss-nvjpeg. --- app/CMakeLists.txt | 1 + .../nvdrv/devices/nvhost/host1x_channel.cpp | 91 +++++++++++++++ .../nvdrv/devices/nvhost/host1x_channel.h | 110 ++++++++++++++++++ .../cpp/skyline/services/nvdrv/driver.cpp | 11 +- app/src/main/cpp/skyline/soc/host1x.h | 2 +- 5 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/host1x_channel.cpp create mode 100644 app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/host1x_channel.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index fd5ae191..43d02e79 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -229,6 +229,7 @@ add_library(skyline SHARED ${source_DIR}/skyline/services/nvdrv/devices/nvhost/ctrl.cpp ${source_DIR}/skyline/services/nvdrv/devices/nvhost/ctrl_gpu.cpp ${source_DIR}/skyline/services/nvdrv/devices/nvhost/gpu_channel.cpp + ${source_DIR}/skyline/services/nvdrv/devices/nvhost/host1x_channel.cpp ${source_DIR}/skyline/services/hosbinder/parcel.cpp ${source_DIR}/skyline/services/hosbinder/IHOSBinderDriver.cpp ${source_DIR}/skyline/services/hosbinder/GraphicBufferProducer.cpp diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/host1x_channel.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/host1x_channel.cpp new file mode 100644 index 00000000..ad6fdd01 --- /dev/null +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/host1x_channel.cpp @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT OR MPL-2.0 +// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#include +#include +#include "host1x_channel.h" + +namespace skyline::service::nvdrv::device::nvhost { + Host1XChannel::Host1XChannel(const DeviceState &state, + Driver &driver, + Core &core, + const SessionContext &ctx, + core::ChannelType channelType) + : NvDevice(state, driver, core, ctx), + channelType(channelType) {} + + PosixResult Host1XChannel::SetNvmapFd(In fd) { + state.logger->Debug("fd: {}", fd); + return PosixResult::Success; + } + + PosixResult Host1XChannel::Submit(span cmdBufs, + span relocs, span relocShifts, + span syncpointIncrs, span fenceThresholds) { + state.logger->Debug("numCmdBufs: {}, numRelocs: {}, numSyncpointIncrs: {}, numFenceThresholds: {}", + cmdBufs.size(), relocs.size(), syncpointIncrs.size(), fenceThresholds.size()); + + return PosixResult::Success; + } + + PosixResult Host1XChannel::GetSyncpoint(In channelSyncpointIdx, Out syncpointId) { + state.logger->Debug("channelSyncpointIdx: {}", channelSyncpointIdx); + + if (channelSyncpointIdx > 0) + throw exception("Multiple channel syncpoints are unimplemented!"); + + u32 id{core::SyncpointManager::ChannelSyncpoints[static_cast(channelType)]}; + if (!id) + throw exception("Requested syncpoint for a channel with none specified!"); + + state.logger->Debug("syncpointId: {}", id); + syncpointId = id; + return PosixResult::Success; + } + + PosixResult Host1XChannel::GetWaitBase(In pChannelType, Out waitBase) { + state.logger->Debug("channelType: {}", static_cast(pChannelType)); + waitBase = 0; + return PosixResult::Success; + } + + PosixResult Host1XChannel::SetSubmitTimeout(In timeout) { + state.logger->Debug("timeout: {}", timeout); + return PosixResult::Success; + } + + PosixResult Host1XChannel::MapBuffer(u8 compressed, span handles) { + state.logger->Debug("compressed: {}", compressed); + return PosixResult::Success; + } + + PosixResult Host1XChannel::UnmapBuffer(u8 compressed, span handles) { + state.logger->Debug("compressed: {}", compressed); + return PosixResult::Success; + } +#include + static constexpr u32 Host1XChannelMagic{0x00}; + static constexpr u32 GpuChannelMagic{0x48}; //!< Used for SetNvmapFd which is needed in both GPU and host1x channels + + VARIABLE_IOCTL_HANDLER_FUNC(Host1XChannel, ({ + IOCTL_CASE_ARGS(IN, SIZE(0x4), MAGIC(GpuChannelMagic), FUNC(0x1), + SetNvmapFd, ARGS(In)) + IOCTL_CASE_ARGS(INOUT, SIZE(0x8), MAGIC(Host1XChannelMagic), FUNC(0x2), + GetSyncpoint, ARGS(In, Out)) + IOCTL_CASE_ARGS(INOUT, SIZE(0x8), MAGIC(Host1XChannelMagic), FUNC(0x3), + GetWaitBase, ARGS(In, Out)) + IOCTL_CASE_ARGS(IN, SIZE(0x4), MAGIC(Host1XChannelMagic), FUNC(0x7), + SetSubmitTimeout, ARGS(In)) + }), ({ + VARIABLE_IOCTL_CASE_ARGS(INOUT, MAGIC(Host1XChannelMagic), FUNC(0x1), + Submit, ARGS(Save, Save, Save, Save, + SlotSizeSpan, + SlotSizeSpan, SlotSizeSpan, + SlotSizeSpan, SlotSizeSpan)) + VARIABLE_IOCTL_CASE_ARGS(INOUT, MAGIC(Host1XChannelMagic), FUNC(0x9), + MapBuffer, ARGS(Save, Pad, In, Pad, SlotSizeSpan)) + VARIABLE_IOCTL_CASE_ARGS(INOUT, MAGIC(Host1XChannelMagic), FUNC(0xA), + UnmapBuffer, ARGS(Save, Pad, In, Pad, SlotSizeSpan)) + })) +#include +} diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/host1x_channel.h b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/host1x_channel.h new file mode 100644 index 00000000..e48287bd --- /dev/null +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/host1x_channel.h @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: MIT OR MPL-2.0 +// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include +#include +#include + +namespace skyline::service::nvdrv::device::nvhost { + /** + * @brief nvhost::Host1XChannel is used by applications to interface with host1x channels, such as VIC and NVDEC + * @url https://switchbrew.org/wiki/NV_services#Channels + */ + class Host1XChannel : public NvDevice { + private: + core::ChannelType channelType; //!< The specific host1x channel that this instance refers to + std::mutex channelMutex; //!< Synchronises submit operations + + public: + /** + * @brief Describes how a gather for a submit should be generated from a given handle + */ + struct SubmitCmdBuf { + core::NvMap::Handle::Id mem; + u32 offset; //!< Offset from the handle of where the gather should start + u32 words; //!< Size for the gather in 4 byte words + }; + + /** + * @brief Describes a single memory relocation that can be applied to a pinned handle before command submission + * @note These are used like: patchMem[patchOffset] = pinMem.iova + pinOffset + */ + struct SubmitReloc { + core::NvMap::Handle::Id patchMem; + u32 patchOffset; + core::NvMap::Handle::Id pinMem; + u32 pinOffset; + }; + + /** + * @brief Describes how the command buffers supplied with the submit will affect a given syncpoint + */ + struct SubmitSyncpointIncr { + u32 syncpointId; + u32 numIncrs; + std::array _res_; + }; + + /** + * @brief A buffer descriptor used for MapBuffer and UnmapBuffer + */ + struct BufferHandle { + core::NvMap::Handle::Id handle; //!< Handle to be (un)pinned + u32 address; //!< The output IOVA that the handle was pinned too + }; + + Host1XChannel(const DeviceState &state, + Driver &driver, + Core &core, + const SessionContext &ctx, + core::ChannelType channelType); + + /** + * @brief Sets the nvmap client to be used for channel submits + * @url https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_SET_NVMAP_FD + */ + PosixResult SetNvmapFd(In id); + + /** + * @brief Submits the specified command buffer data to the channel and returns fences that can be waited on + * @url https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CHANNEL_SUBMIT + */ + PosixResult Submit(span cmdBufs, + span relocs, span relocShifts, + span syncpointIncrs, span fenceThresholds); + + /** + * @brief Returns the syncpoint ID that is located at the given index in this channel's syncpoint array + * @url https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CHANNEL_GET_SYNCPOINT + */ + PosixResult GetSyncpoint(In channelSyncpointIdx, Out syncpointId); + + /** + * @brief Stubbed in modern nvdrv to return 0 + * @url https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CHANNEL_GET_WAITBASE + */ + PosixResult GetWaitBase(In pChannelType, Out waitBase); + + /** + * @brief Sets the timeout for channel submits + * @url https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CHANNEL_SET_SUBMIT_TIMEOUT + */ + PosixResult SetSubmitTimeout(In timeout); + + /** + * @brief Pins a set of nvmap handles into the channel address space for use in submitted command buffers + * @url https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CHANNEL_MAP_CMD_BUFFER + */ + PosixResult MapBuffer(u8 compressed, span handles); + + /** + * @brief Unpins a set of nvmap handles into the channel address space + * @url https://switchbrew.org/wiki/NV_services#NVHOST_IOCTL_CHANNEL_UNMAP_CMD_BUFFER + */ + PosixResult UnmapBuffer(u8 compressed, span handles); + + PosixResult Ioctl(IoctlDescriptor cmd, span buffer) override; + }; +} diff --git a/app/src/main/cpp/skyline/services/nvdrv/driver.cpp b/app/src/main/cpp/skyline/services/nvdrv/driver.cpp index 340ac62d..15e48fdf 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/driver.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/driver.cpp @@ -7,7 +7,7 @@ #include "devices/nvhost/ctrl_gpu.h" #include "devices/nvhost/gpu_channel.h" #include "devices/nvhost/as_gpu.h" - +#include "devices/nvhost/host1x_channel.h" namespace skyline::service::nvdrv { Driver::Driver(const DeviceState &state) : state(state), core(state) {} @@ -44,6 +44,15 @@ namespace skyline::service::nvdrv { ) } + if (ctx.perms.AccessJpeg) + DEVICE_SWITCH(DEVICE_CASE("/dev/nvhost-nvjpg", nvhost::Host1XChannel, core::ChannelType::NvJpg)) + + if (ctx.perms.AccessVic) + DEVICE_SWITCH(DEVICE_CASE("/dev/nvhost-vic", nvhost::Host1XChannel, core::ChannelType::Vic)) + + if (ctx.perms.AccessVideoDecoder) + DEVICE_SWITCH(DEVICE_CASE("/dev/nvhost-nvdec", nvhost::Host1XChannel, core::ChannelType::NvDec)) + #undef DEVICE_CASE #undef DEVICE_SWITCH diff --git a/app/src/main/cpp/skyline/soc/host1x.h b/app/src/main/cpp/skyline/soc/host1x.h index ac3a04a8..37c1f3f6 100644 --- a/app/src/main/cpp/skyline/soc/host1x.h +++ b/app/src/main/cpp/skyline/soc/host1x.h @@ -8,7 +8,7 @@ namespace skyline::soc::host1x { /** * @brief An abstraction for the graphics host, this handles DMA on behalf of the CPU when communicating to it's clients alongside handling syncpts - * @note This is different from the GM20B Host, it serves a similar function and has an interface for accessing Host1X syncpts + * @note This is different from the GM20B Host, it serves a similar function and has an interface for accessing host1x syncpts */ class Host1X { public: