mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-22 21:39:15 +01:00
Add support for Ioctl2/3 and improve debug logging
This commit is contained in:
parent
7468003381
commit
b9098ac14a
@ -6,7 +6,13 @@
|
|||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
#include "devices/nvdevice.h"
|
#include "devices/nvdevice.h"
|
||||||
|
|
||||||
#define NVRESULT(x) [&response](NvResult err) { response.Push<NvResult>(err); return Result{}; }(x)
|
#define NVRESULT(x) [&response, this](NvResult err) { \
|
||||||
|
if (err != NvResult::Success) \
|
||||||
|
state.logger->Debug("IOCTL Failed: {}", err); \
|
||||||
|
\
|
||||||
|
response.Push<NvResult>(err); \
|
||||||
|
return Result{}; \
|
||||||
|
} (x)
|
||||||
|
|
||||||
namespace skyline::service::nvdrv {
|
namespace skyline::service::nvdrv {
|
||||||
INvDrvServices::INvDrvServices(const DeviceState &state, ServiceManager &manager, Driver &driver, const SessionPermissions &perms) : BaseService(state, manager), driver(driver), ctx(SessionContext{.perms = perms}) {}
|
INvDrvServices::INvDrvServices(const DeviceState &state, ServiceManager &manager, Driver &driver, const SessionPermissions &perms) : BaseService(state, manager), driver(driver), ctx(SessionContext{.perms = perms}) {}
|
||||||
@ -29,29 +35,34 @@ namespace skyline::service::nvdrv {
|
|||||||
return NVRESULT(NvResult::Success);
|
return NVRESULT(NvResult::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result INvDrvServices::Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
static NvResultValue<span<u8>> GetMainIoctlBuffer(IoctlDescriptor ioctl, span<u8> inBuf, span<u8> outBuf) {
|
||||||
auto fd{request.Pop<FileDescriptor>()};
|
|
||||||
auto ioctl{request.Pop<IoctlDescriptor>()};
|
|
||||||
|
|
||||||
auto inBuf{request.inputBuf.at(0)};
|
|
||||||
auto outBuf{request.outputBuf.at(0)};
|
|
||||||
|
|
||||||
if (ioctl.in && inBuf.size() < ioctl.size)
|
if (ioctl.in && inBuf.size() < ioctl.size)
|
||||||
return NVRESULT(NvResult::InvalidSize);
|
return NvResult::InvalidSize;
|
||||||
|
|
||||||
if (ioctl.out && outBuf.size() < ioctl.size)
|
if (ioctl.out && outBuf.size() < ioctl.size)
|
||||||
return NVRESULT(NvResult::InvalidSize);
|
return NvResult::InvalidSize;
|
||||||
|
|
||||||
if (ioctl.in && ioctl.out) {
|
if (ioctl.in && ioctl.out) {
|
||||||
if (outBuf.size() < inBuf.size())
|
if (outBuf.size() < inBuf.size())
|
||||||
return NVRESULT(NvResult::InvalidSize);
|
return NvResult::InvalidSize;
|
||||||
|
|
||||||
// Copy in buf to out buf for inout ioctls to avoid needing to pass around two buffers everywhere
|
// Copy in buf to out buf for inout ioctls to avoid needing to pass around two buffers everywhere
|
||||||
if (outBuf.data() != inBuf.data())
|
if (outBuf.data() != inBuf.data())
|
||||||
outBuf.copy_from(inBuf, ioctl.size);
|
outBuf.copy_from(inBuf, ioctl.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NVRESULT(driver.Ioctl(fd, ioctl, ioctl.out ? outBuf : inBuf));
|
return ioctl.out ? outBuf : inBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result INvDrvServices::Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
auto fd{request.Pop<FileDescriptor>()};
|
||||||
|
auto ioctl{request.Pop<IoctlDescriptor>()};
|
||||||
|
|
||||||
|
auto buf{GetMainIoctlBuffer(ioctl, request.inputBuf.at(0), request.outputBuf.at(0))};
|
||||||
|
if (!buf)
|
||||||
|
return NVRESULT(buf);
|
||||||
|
else
|
||||||
|
return NVRESULT(driver.Ioctl(fd, ioctl, *buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result INvDrvServices::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
@ -85,6 +96,34 @@ namespace skyline::service::nvdrv {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result INvDrvServices::Ioctl2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
auto fd{request.Pop<FileDescriptor>()};
|
||||||
|
auto ioctl{request.Pop<IoctlDescriptor>()};
|
||||||
|
|
||||||
|
// The inline buffer is technically not required
|
||||||
|
auto inlineBuf{request.inputBuf.size() > 1 ? request.inputBuf.at(1) : span<u8>{}};
|
||||||
|
|
||||||
|
auto buf{GetMainIoctlBuffer(ioctl, request.inputBuf.at(0), request.outputBuf.at(0))};
|
||||||
|
if (!buf)
|
||||||
|
return NVRESULT(buf);
|
||||||
|
else
|
||||||
|
return NVRESULT(driver.Ioctl2(fd, ioctl, *buf, inlineBuf));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result INvDrvServices::Ioctl3(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
auto fd{request.Pop<FileDescriptor>()};
|
||||||
|
auto ioctl{request.Pop<IoctlDescriptor>()};
|
||||||
|
|
||||||
|
// The inline buffer is technically not required
|
||||||
|
auto inlineBuf{request.outputBuf.size() > 1 ? request.outputBuf.at(1) : span<u8>{}};
|
||||||
|
|
||||||
|
auto buf{GetMainIoctlBuffer(ioctl, request.inputBuf.at(0), request.outputBuf.at(0))};
|
||||||
|
if (!buf)
|
||||||
|
return NVRESULT(buf);
|
||||||
|
else
|
||||||
|
return NVRESULT(driver.Ioctl3(fd, ioctl, *buf, inlineBuf));
|
||||||
|
}
|
||||||
|
|
||||||
Result INvDrvServices::SetAruid(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::SetAruid(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
return NVRESULT(NvResult::Success);
|
return NVRESULT(NvResult::Success);
|
||||||
}
|
}
|
||||||
|
@ -63,13 +63,13 @@ namespace skyline::service::nvdrv {
|
|||||||
* @brief Perform an IOCTL on the specified FD with an extra input buffer
|
* @brief Perform an IOCTL on the specified FD with an extra input buffer
|
||||||
* @url https://switchbrew.org/wiki/NV_services#Ioctl2
|
* @url https://switchbrew.org/wiki/NV_services#Ioctl2
|
||||||
*/
|
*/
|
||||||
// Result Ioctl2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Ioctl2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Perform an IOCTL on the specified FD with an extra output buffer
|
* @brief Perform an IOCTL on the specified FD with an extra output buffer
|
||||||
* @url https://switchbrew.org/wiki/NV_services#Ioctl3
|
* @url https://switchbrew.org/wiki/NV_services#Ioctl3
|
||||||
*/
|
*/
|
||||||
// Result Ioctl3(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Ioctl3(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enables the graphics firmware memory margin
|
* @brief Enables the graphics firmware memory margin
|
||||||
@ -84,7 +84,8 @@ namespace skyline::service::nvdrv {
|
|||||||
SFUNC(0x3, INvDrvServices, Initialize),
|
SFUNC(0x3, INvDrvServices, Initialize),
|
||||||
SFUNC(0x4, INvDrvServices, QueryEvent),
|
SFUNC(0x4, INvDrvServices, QueryEvent),
|
||||||
SFUNC(0x8, INvDrvServices, SetAruid),
|
SFUNC(0x8, INvDrvServices, SetAruid),
|
||||||
|
SFUNC(0xB, INvDrvServices, Ioctl2),
|
||||||
|
SFUNC(0xC, INvDrvServices, Ioctl3),
|
||||||
SFUNC(0xD, INvDrvServices, SetGraphicsFirmwareMemoryMarginEnabled)
|
SFUNC(0xD, INvDrvServices, SetGraphicsFirmwareMemoryMarginEnabled)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -3,6 +3,16 @@
|
|||||||
|
|
||||||
#include "deserialisation.h"
|
#include "deserialisation.h"
|
||||||
|
|
||||||
|
#define INLINE_IOCTL_HANDLER_FUNC(type, name, cases) \
|
||||||
|
PosixResult name::type(IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineBuffer) { \
|
||||||
|
using className = name; \
|
||||||
|
switch (cmd.raw) { \
|
||||||
|
cases; \
|
||||||
|
default: \
|
||||||
|
return PosixResult::InappropriateIoctlForDevice; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define VARIABLE_IOCTL_HANDLER_FUNC(name, cases, variableCases) \
|
#define VARIABLE_IOCTL_HANDLER_FUNC(name, cases, variableCases) \
|
||||||
PosixResult name::Ioctl(IoctlDescriptor cmd, span<u8> buffer) { \
|
PosixResult name::Ioctl(IoctlDescriptor cmd, span<u8> buffer) { \
|
||||||
using className = name; \
|
using className = name; \
|
||||||
@ -28,11 +38,11 @@
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IOCTL_CASE_ARGS_I(out, in, size, magic, function, name, ...) \
|
#define IOCTL_CASE_ARGS_I(out, in, size, magic, function, name, ...) \
|
||||||
case MetaIoctlDescriptor<out, in, size, magic, function>::Raw(): { \
|
case MetaIoctlDescriptor<out, in, size, magic, function>::Raw(): { \
|
||||||
using IoctlType = MetaIoctlDescriptor< out, in, size, magic, function>; \
|
using IoctlType = MetaIoctlDescriptor< out, in, size, magic, function>; \
|
||||||
auto args = DecodeArguments<IoctlType, __VA_ARGS__>(buffer.subspan<0, size>()); \
|
auto args = DecodeArguments<IoctlType, __VA_ARGS__>(buffer.subspan<0, size>()); \
|
||||||
return std::apply(&className::name, std::tuple_cat(std::make_tuple(this), args)); \
|
return std::apply(&className::name, std::tuple_cat(std::make_tuple(this), args)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IOCTL_CASE_NOARGS_I(out, in, size, magic, function, name) \
|
#define IOCTL_CASE_NOARGS_I(out, in, size, magic, function, name) \
|
||||||
@ -47,6 +57,7 @@
|
|||||||
#define IOCTL_CASE_NOARGS(...) IOCTL_CASE_NOARGS_I(__VA_ARGS__)
|
#define IOCTL_CASE_NOARGS(...) IOCTL_CASE_NOARGS_I(__VA_ARGS__)
|
||||||
#define IOCTL_CASE_RESULT(...) IOCTL_CASE_RESULT_I(__VA_ARGS__)
|
#define IOCTL_CASE_RESULT(...) IOCTL_CASE_RESULT_I(__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
#define VARIABLE_IOCTL_CASE_ARGS_I(out, in, magic, function, name, ...) \
|
#define VARIABLE_IOCTL_CASE_ARGS_I(out, in, magic, function, name, ...) \
|
||||||
case MetaVariableIoctlDescriptor<out, in, magic, function>::Raw(): { \
|
case MetaVariableIoctlDescriptor<out, in, magic, function>::Raw(): { \
|
||||||
using IoctlType = MetaVariableIoctlDescriptor<out, in, magic, function>; \
|
using IoctlType = MetaVariableIoctlDescriptor<out, in, magic, function>; \
|
||||||
@ -56,6 +67,16 @@
|
|||||||
|
|
||||||
#define VARIABLE_IOCTL_CASE_ARGS(...) VARIABLE_IOCTL_CASE_ARGS_I(__VA_ARGS__)
|
#define VARIABLE_IOCTL_CASE_ARGS(...) VARIABLE_IOCTL_CASE_ARGS_I(__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
#define INLINE_IOCTL_CASE_ARGS_I(out, in, size, magic, function, name, ...) \
|
||||||
|
case MetaIoctlDescriptor<out, in, size, magic, function>::Raw(): { \
|
||||||
|
using IoctlType = MetaIoctlDescriptor< out, in, size, magic, function>; \
|
||||||
|
auto args = DecodeArguments<IoctlType, __VA_ARGS__>(buffer.subspan<0, size>()); \
|
||||||
|
return std::apply(&className::name, std::tuple_cat(std::make_tuple(this, inlineBuffer), args)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define INLINE_IOCTL_CASE_ARGS(...) INLINE_IOCTL_CASE_ARGS_I(__VA_ARGS__)
|
||||||
|
|
||||||
#define IN false, true
|
#define IN false, true
|
||||||
#define OUT true, false
|
#define OUT true, false
|
||||||
#define INOUT true, true
|
#define INOUT true, true
|
||||||
|
@ -3,14 +3,21 @@
|
|||||||
|
|
||||||
#undef IOCTL_HANDLER_FUNC
|
#undef IOCTL_HANDLER_FUNC
|
||||||
#undef VARIABLE_IOCTL_HANDLER_FUNC
|
#undef VARIABLE_IOCTL_HANDLER_FUNC
|
||||||
|
#undef INLINE_IOCTL_HANDLER_FUNC
|
||||||
|
|
||||||
#undef IOCTL_CASE_ARGS_I
|
#undef IOCTL_CASE_ARGS_I
|
||||||
#undef IOCTL_CASE_NOARGS_I
|
#undef IOCTL_CASE_NOARGS_I
|
||||||
#undef IOCTL_CASE_RESULT_I
|
#undef IOCTL_CASE_RESULT_I
|
||||||
#undef IOCTL_CASE_ARGS
|
#undef IOCTL_CASE_ARGS
|
||||||
#undef IOCTL_CASE_NOARGS
|
#undef IOCTL_CASE_NOARGS
|
||||||
#undef IOCTL_CASE_RESULT
|
#undef IOCTL_CASE_RESULT
|
||||||
|
|
||||||
#undef VARIABLE_IOCTL_CASE_ARGS_I
|
#undef VARIABLE_IOCTL_CASE_ARGS_I
|
||||||
#undef VARIABLE_IOCTL_CASE_ARGS
|
#undef VARIABLE_IOCTL_CASE_ARGS
|
||||||
|
|
||||||
|
#undef INLINE_IOCTL_CASE_ARGS_I
|
||||||
|
#undef INLINE_IOCTL_CASE_ARGS
|
||||||
|
|
||||||
#undef IN
|
#undef IN
|
||||||
#undef OUT
|
#undef OUT
|
||||||
#undef INOUT
|
#undef INOUT
|
||||||
|
@ -40,9 +40,13 @@ namespace skyline::service::nvdrv::device {
|
|||||||
|
|
||||||
virtual PosixResult Ioctl(IoctlDescriptor cmd, span<u8> buffer) = 0;
|
virtual PosixResult Ioctl(IoctlDescriptor cmd, span<u8> buffer) = 0;
|
||||||
|
|
||||||
virtual PosixResult Ioctl2(IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineOutput) { return PosixResult::NotSupported; }
|
virtual PosixResult Ioctl2(IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineOutput) {
|
||||||
|
return PosixResult::InappropriateIoctlForDevice;
|
||||||
|
}
|
||||||
|
|
||||||
virtual PosixResult Ioctl3(IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineInput) { return PosixResult::NotSupported; }
|
virtual PosixResult Ioctl3(IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineInput) {
|
||||||
|
return PosixResult::InappropriateIoctlForDevice;
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::shared_ptr<kernel::type::KEvent> QueryEvent(u32 eventId) {
|
virtual std::shared_ptr<kernel::type::KEvent> QueryEvent(u32 eventId) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -54,6 +54,8 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PosixResult AsGpu::MapBufferEx(In<MappingFlags> flags, In<u32> kind, In<core::NvMap::Handle::Id> handle, InOut<u32> pageSize, In<u64> bufferOffset, In<u64> mappingSize, InOut<u64> offset) {
|
PosixResult AsGpu::MapBufferEx(In<MappingFlags> flags, In<u32> kind, In<core::NvMap::Handle::Id> handle, InOut<u32> pageSize, In<u64> bufferOffset, In<u64> mappingSize, InOut<u64> offset) {
|
||||||
|
state.logger->Debug("flags: ( fixed: {}, remap: {} ), kind: {}, handle: {}, pageSize: 0x{:X}, bufferOffset: 0x{:X}, mappingSize: 0x{:X}, offset: 0x{:X}", flags.fixed, flags.remap, kind, handle, pageSize, bufferOffset, mappingSize, offset);
|
||||||
|
|
||||||
if (flags.remap) {
|
if (flags.remap) {
|
||||||
auto region{regionMap.lower_bound(offset)};
|
auto region{regionMap.lower_bound(offset)};
|
||||||
if (region == regionMap.end()) {
|
if (region == regionMap.end()) {
|
||||||
@ -95,8 +97,11 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
state.logger->Warn("Failed to map GPU address space region!");
|
state.logger->Warn("Failed to map GPU address space region!");
|
||||||
return PosixResult::InvalidArgument;
|
return PosixResult::InvalidArgument;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.logger->Debug("Mapped to 0x{:X}", offset);
|
||||||
|
|
||||||
regionMap[offset] = {cpuPtr, size, flags.fixed};
|
regionMap[offset] = {cpuPtr, size, flags.fixed};
|
||||||
|
|
||||||
return PosixResult::Success;
|
return PosixResult::Success;
|
||||||
@ -107,6 +112,10 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
return PosixResult::Success;
|
return PosixResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PosixResult AsGpu::GetVaRegions3(span<u8> inlineBufer, In<u64> bufAddr, InOut<u32> bufSize, Out<std::array<VaRegion, 2>> vaRegions) {
|
||||||
|
return GetVaRegions(bufAddr, bufSize, vaRegions);
|
||||||
|
}
|
||||||
|
|
||||||
PosixResult AsGpu::AllocAsEx(In<u32> bigPageSize, In<FileDescriptor> asFd, In<u32> flags, In<u64> vaRangeStart, In<u64> vaRangeEnd, In<u64> vaRangeSplit) {
|
PosixResult AsGpu::AllocAsEx(In<u32> bigPageSize, In<FileDescriptor> asFd, In<u32> flags, In<u64> vaRangeStart, In<u64> vaRangeEnd, In<u64> vaRangeSplit) {
|
||||||
// TODO: create the allocator here
|
// TODO: create the allocator here
|
||||||
return PosixResult::Success;
|
return PosixResult::Success;
|
||||||
@ -152,5 +161,10 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
VARIABLE_IOCTL_CASE_ARGS(INOUT, MAGIC(AsGpuMagic), FUNC(0x14),
|
VARIABLE_IOCTL_CASE_ARGS(INOUT, MAGIC(AsGpuMagic), FUNC(0x14),
|
||||||
Remap, ARGS(AutoSizeSpan<RemapEntry>))
|
Remap, ARGS(AutoSizeSpan<RemapEntry>))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
INLINE_IOCTL_HANDLER_FUNC(Ioctl3, AsGpu, ({
|
||||||
|
INLINE_IOCTL_CASE_ARGS(INOUT, SIZE(0x40), MAGIC(AsGpuMagic), FUNC(0x8),
|
||||||
|
GetVaRegions3, ARGS(In<u64>, InOut<u32>, Pad<u32>, Out<std::array<VaRegion, 2>>))
|
||||||
|
}))
|
||||||
#include <services/nvdrv/devices/deserialisation/macro_undef.h>
|
#include <services/nvdrv/devices/deserialisation/macro_undef.h>
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,11 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
*/
|
*/
|
||||||
PosixResult GetVaRegions(In<u64> bufAddr, InOut<u32> bufSize, Out<std::array<VaRegion, 2>> vaRegions);
|
PosixResult GetVaRegions(In<u64> bufAddr, InOut<u32> bufSize, Out<std::array<VaRegion, 2>> vaRegions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ioctl3 variant of GetVaRegions
|
||||||
|
*/
|
||||||
|
PosixResult GetVaRegions3(span<u8> inlineBuffer, In<u64> bufAddr, InOut<u32> bufSize, Out<std::array<VaRegion, 2>> vaRegions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Allocates this address space with the given parameters
|
* @brief Allocates this address space with the given parameters
|
||||||
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_ALLOC_AS_EX
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_ALLOC_AS_EX
|
||||||
@ -98,5 +103,7 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
PosixResult Remap(span<RemapEntry> entries);
|
PosixResult Remap(span<RemapEntry> entries);
|
||||||
|
|
||||||
PosixResult Ioctl(IoctlDescriptor cmd, span<u8> buffer) override;
|
PosixResult Ioctl(IoctlDescriptor cmd, span<u8> buffer) override;
|
||||||
|
|
||||||
|
PosixResult Ioctl3(IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineBuffer) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,22 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
return PosixResult::Success;
|
return PosixResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
PosixResult CtrlGpu::GetTpcMasks(In<u32> bufSize, Out<u64> maskBuf) {
|
PosixResult CtrlGpu::GetCharacteristics3(span<u8> inlineBuffer, InOut<u64> size, In<u64> userAddress, Out<GpuCharacteristics> characteristics) {
|
||||||
// TODO
|
inlineBuffer.as<GpuCharacteristics>() = {};
|
||||||
maskBuf = 0x3;
|
return GetCharacteristics(size, userAddress, characteristics);
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixResult CtrlGpu::GetTpcMasks(In<u32> bufSize, Out<u32> mask) {
|
||||||
|
if (bufSize)
|
||||||
|
mask = 0x3;
|
||||||
|
|
||||||
|
return PosixResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixResult CtrlGpu::GetTpcMasks3(span<u8> inlineBuffer, In<u32> bufSize, Out<u32> mask) {
|
||||||
|
if (bufSize)
|
||||||
|
mask = inlineBuffer.as<u32>() = 0x3;
|
||||||
|
|
||||||
return PosixResult::Success;
|
return PosixResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +73,7 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
IOCTL_CASE_ARGS(INOUT, SIZE(0xB0), MAGIC(CtrlGpuMagic), FUNC(0x5),
|
IOCTL_CASE_ARGS(INOUT, SIZE(0xB0), MAGIC(CtrlGpuMagic), FUNC(0x5),
|
||||||
GetCharacteristics, ARGS(InOut<u64>, In<u64>, Out<GpuCharacteristics>))
|
GetCharacteristics, ARGS(InOut<u64>, In<u64>, Out<GpuCharacteristics>))
|
||||||
IOCTL_CASE_ARGS(INOUT, SIZE(0x18), MAGIC(CtrlGpuMagic), FUNC(0x6),
|
IOCTL_CASE_ARGS(INOUT, SIZE(0x18), MAGIC(CtrlGpuMagic), FUNC(0x6),
|
||||||
GetTpcMasks, ARGS(In<u32>, Pad<u32, 3>, Out<u64>))
|
GetTpcMasks, ARGS(In<u32>, Pad<u32, 3>, Out<u32>))
|
||||||
IOCTL_CASE_ARGS(OUT, SIZE(0x8), MAGIC(CtrlGpuMagic), FUNC(0x14),
|
IOCTL_CASE_ARGS(OUT, SIZE(0x8), MAGIC(CtrlGpuMagic), FUNC(0x14),
|
||||||
GetActiveSlotMask, ARGS(Out<u32>, Out<u32>))
|
GetActiveSlotMask, ARGS(Out<u32>, Out<u32>))
|
||||||
}))
|
}))
|
||||||
|
@ -93,11 +93,21 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
*/
|
*/
|
||||||
PosixResult GetCharacteristics(InOut<u64> size, In<u64> userAddress, Out<GpuCharacteristics> characteristics);
|
PosixResult GetCharacteristics(InOut<u64> size, In<u64> userAddress, Out<GpuCharacteristics> characteristics);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ioctl3 variant of GetTpcMasks
|
||||||
|
*/
|
||||||
|
PosixResult GetCharacteristics3(span<u8> inlineBuffer, InOut<u64> size, In<u64> userAddress, Out<GpuCharacteristics> characteristics);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the TPC mask value for each GPC
|
* @brief Returns the TPC mask value for each GPC
|
||||||
* @url https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_TPC_MASKS
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_GPU_IOCTL_GET_TPC_MASKS
|
||||||
*/
|
*/
|
||||||
PosixResult GetTpcMasks(In<u32> bufSize, Out<u64> maskBuf);
|
PosixResult GetTpcMasks(In<u32> bufSize, Out<u32> mask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ioctl3 variant of GetTpcMasks
|
||||||
|
*/
|
||||||
|
PosixResult GetTpcMasks3(span<u8> inlineBuffer, In<u32> bufSize, Out<u32> mask);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the mask value for a ZBC slot
|
* @brief Returns the mask value for a ZBC slot
|
||||||
|
@ -23,7 +23,7 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PosixResult GpuChannel::SubmitGpfifo(In<u64> userAddress, In<u32> numEntries, InOut<SubmitGpfifoFlags> flags, InOut<Fence> fence, span<soc::gm20b::GpEntry> gpEntries) {
|
PosixResult GpuChannel::SubmitGpfifo(In<u64> userAddress, In<u32> numEntries, InOut<SubmitGpfifoFlags> flags, InOut<Fence> fence, span<soc::gm20b::GpEntry> gpEntries) {
|
||||||
if (numEntries != gpEntries.size())
|
if (numEntries > gpEntries.size())
|
||||||
throw exception("GpEntry size mismatch!");
|
throw exception("GpEntry size mismatch!");
|
||||||
|
|
||||||
if (flags.fenceWait) {
|
if (flags.fenceWait) {
|
||||||
@ -34,7 +34,7 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
throw exception("Waiting on a fence through SubmitGpfifo is unimplemented");
|
throw exception("Waiting on a fence through SubmitGpfifo is unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
state.soc->gm20b.gpfifo.Push(gpEntries);
|
state.soc->gm20b.gpfifo.Push(gpEntries.subspan(0, numEntries));
|
||||||
|
|
||||||
fence.id = channelSyncpoint;
|
fence.id = channelSyncpoint;
|
||||||
|
|
||||||
@ -49,6 +49,10 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
return PosixResult::Success;
|
return PosixResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PosixResult GpuChannel::SubmitGpfifo2(span<u8> inlineBuffer, In<u64> userAddress, In<u32> numEntries, InOut<GpuChannel::SubmitGpfifoFlags> flags, InOut<Fence> fence) {
|
||||||
|
return SubmitGpfifo(userAddress, numEntries, flags, fence, inlineBuffer.cast<soc::gm20b::GpEntry>());
|
||||||
|
}
|
||||||
|
|
||||||
PosixResult GpuChannel::AllocObjCtx(In<u32> classId, In<u32> flags, Out<u64> objId) {
|
PosixResult GpuChannel::AllocObjCtx(In<u32> classId, In<u32> flags, Out<u64> objId) {
|
||||||
return PosixResult::Success;
|
return PosixResult::Success;
|
||||||
}
|
}
|
||||||
@ -129,5 +133,10 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
VARIABLE_IOCTL_CASE_ARGS(INOUT, MAGIC(GpuChannelMagic), FUNC(0x8),
|
VARIABLE_IOCTL_CASE_ARGS(INOUT, MAGIC(GpuChannelMagic), FUNC(0x8),
|
||||||
SubmitGpfifo, ARGS(In<u64>, In<u32>, InOut<SubmitGpfifoFlags>, InOut<Fence>, AutoSizeSpan<soc::gm20b::GpEntry>))
|
SubmitGpfifo, ARGS(In<u64>, In<u32>, InOut<SubmitGpfifoFlags>, InOut<Fence>, AutoSizeSpan<soc::gm20b::GpEntry>))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
INLINE_IOCTL_HANDLER_FUNC(Ioctl2, GpuChannel, ({
|
||||||
|
INLINE_IOCTL_CASE_ARGS(INOUT, SIZE(0x18), MAGIC(GpuChannelMagic), FUNC(0x1B),
|
||||||
|
SubmitGpfifo2, ARGS(In<u64>, In<u32>, InOut<SubmitGpfifoFlags>, InOut<Fence>))
|
||||||
|
}))
|
||||||
#include <services/nvdrv/devices/deserialisation/macro_undef.h>
|
#include <services/nvdrv/devices/deserialisation/macro_undef.h>
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,11 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
*/
|
*/
|
||||||
PosixResult SubmitGpfifo(In<u64> userAddress, In<u32> numEntries, InOut<SubmitGpfifoFlags> flags, InOut<Fence> fence, span<soc::gm20b::GpEntry> gpEntries);
|
PosixResult SubmitGpfifo(In<u64> userAddress, In<u32> numEntries, InOut<SubmitGpfifoFlags> flags, InOut<Fence> fence, span<soc::gm20b::GpEntry> gpEntries);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ioctl2 variant of SubmitGpfifo
|
||||||
|
*/
|
||||||
|
PosixResult SubmitGpfifo2(span<u8> inlineBuffer, In<u64> userAddress, In<u32> numEntries, InOut<SubmitGpfifoFlags> flags, InOut<Fence> fence);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Allocates a graphic context object
|
* @brief Allocates a graphic context object
|
||||||
* @url https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX
|
||||||
@ -108,5 +113,7 @@ namespace skyline::service::nvdrv::device::nvhost {
|
|||||||
std::shared_ptr<type::KEvent> QueryEvent(u32 eventId) override;
|
std::shared_ptr<type::KEvent> QueryEvent(u32 eventId) override;
|
||||||
|
|
||||||
PosixResult Ioctl(IoctlDescriptor cmd, span<u8> buffer) override;
|
PosixResult Ioctl(IoctlDescriptor cmd, span<u8> buffer) override;
|
||||||
|
|
||||||
|
PosixResult Ioctl2(IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineBuffer) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ namespace skyline::service::nvdrv::device {
|
|||||||
if (h) {
|
if (h) {
|
||||||
(*h)->origSize = size; // Orig size is the unaligned size
|
(*h)->origSize = size; // Orig size is the unaligned size
|
||||||
handle = (*h)->id;
|
handle = (*h)->id;
|
||||||
|
state.logger->Debug("handle: {}, size: 0x{:X}", (*h)->id, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
@ -47,6 +48,8 @@ namespace skyline::service::nvdrv::device {
|
|||||||
if (!h) [[unlikely]]
|
if (!h) [[unlikely]]
|
||||||
return PosixResult::InvalidArgument;
|
return PosixResult::InvalidArgument;
|
||||||
|
|
||||||
|
state.logger->Debug("handle: {}, flags: ( mapUncached: {}, keepUncachedAfterFree: {} ), align: 0x{:X}, kind: {}, address: 0x{:X}", handle, flags.mapUncached, flags.keepUncachedAfterFree, align, kind, address);
|
||||||
|
|
||||||
return h->Alloc(flags, align, kind, address);
|
return h->Alloc(flags, align, kind, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,11 +95,34 @@ namespace skyline::service::nvdrv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult Driver::Ioctl(u32 fd, IoctlDescriptor cmd, span<u8> buffer) {
|
NvResult Driver::Ioctl(u32 fd, IoctlDescriptor cmd, span<u8> buffer) {
|
||||||
|
state.logger->Debug("fd: {}, cmd: 0x{:X}, device: {}", fd, cmd.raw, devices.at(fd)->GetName());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return ConvertResult(devices.at(fd)->Ioctl(cmd, buffer));
|
return ConvertResult(devices.at(fd)->Ioctl(cmd, buffer));
|
||||||
} catch (const std::out_of_range &) {
|
} catch (const std::out_of_range &) {
|
||||||
throw exception("GetDevice was called with invalid file descriptor: 0x{:X}", fd);
|
throw exception("Ioctl was called with invalid file descriptor: 0x{:X}", fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NvResult Driver::Ioctl2(u32 fd, IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineBuffer) {
|
||||||
|
state.logger->Debug("fd: {}, cmd: 0x{:X}, device: {}", fd, cmd.raw, devices.at(fd)->GetName());
|
||||||
|
|
||||||
|
try {
|
||||||
|
return ConvertResult(devices.at(fd)->Ioctl2(cmd, buffer, inlineBuffer));
|
||||||
|
} catch (const std::out_of_range &) {
|
||||||
|
throw exception("Ioctl2 was called with invalid file descriptor: 0x{:X}", fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NvResult Driver::Ioctl3(u32 fd, IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineBuffer) {
|
||||||
|
state.logger->Debug("fd: {}, cmd: 0x{:X}, device: {}", fd, cmd.raw, devices.at(fd)->GetName());
|
||||||
|
|
||||||
|
try {
|
||||||
|
return ConvertResult(devices.at(fd)->Ioctl3(cmd, buffer, inlineBuffer));
|
||||||
|
} catch (const std::out_of_range &) {
|
||||||
|
throw exception("Ioctl3 was called with invalid file descriptor: 0x{:X}", fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +135,8 @@ namespace skyline::service::nvdrv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<kernel::type::KEvent> Driver::QueryEvent(u32 fd, u32 eventId) {
|
std::shared_ptr<kernel::type::KEvent> Driver::QueryEvent(u32 fd, u32 eventId) {
|
||||||
|
state.logger->Debug("fd: {}, eventId: 0x{:X}, device: {}", fd, eventId, devices.at(fd)->GetName());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return devices.at(fd)->QueryEvent(eventId);
|
return devices.at(fd)->QueryEvent(eventId);
|
||||||
} catch (const std::exception &) {
|
} catch (const std::exception &) {
|
||||||
|
@ -32,6 +32,16 @@ namespace skyline::service::nvdrv {
|
|||||||
*/
|
*/
|
||||||
NvResult Ioctl(u32 fd, IoctlDescriptor cmd, span<u8> buffer);
|
NvResult Ioctl(u32 fd, IoctlDescriptor cmd, span<u8> buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calls an IOCTL on the device specified by `fd` using the given inline input buffer
|
||||||
|
*/
|
||||||
|
NvResult Ioctl2(u32 fd, IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineBuffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calls an IOCTL on the device specified by `fd` using the given inline output buffer
|
||||||
|
*/
|
||||||
|
NvResult Ioctl3(u32 fd, IoctlDescriptor cmd, span<u8> buffer, span<u8> inlineBuffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Queries a KEvent for the given `eventId` for the device specified by `fd`
|
* @brief Queries a KEvent for the given `eventId` for the device specified by `fd`
|
||||||
*/
|
*/
|
||||||
|
@ -90,4 +90,7 @@ namespace skyline::service::nvdrv {
|
|||||||
AccessDenied = 0x30010,
|
AccessDenied = 0x30010,
|
||||||
IoctlFailed = 0x3000F
|
IoctlFailed = 0x3000F
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
using NvResultValue = ResultValue<ValueType, NvResult>;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user