mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 15:55:29 +03:00
Move nvhost-as-gpu to new device API
This commit is contained in:
parent
1149158198
commit
3d4f7d9b44
@ -0,0 +1,156 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR MPL-2.0
|
||||||
|
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
|
#include <soc.h>
|
||||||
|
#include <services/nvdrv/devices/deserialisation/deserialisation.h>
|
||||||
|
#include "as_gpu.h"
|
||||||
|
|
||||||
|
namespace skyline::service::nvdrv::device::nvhost {
|
||||||
|
AsGpu::AsGpu(const DeviceState &state, Core &core, const SessionContext &ctx) : NvDevice(state, core, ctx) {}
|
||||||
|
|
||||||
|
PosixResult AsGpu::BindChannel(In<FileDescriptor> channelFd) {
|
||||||
|
// TODO: support once multiple address spaces are supported
|
||||||
|
return PosixResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixResult AsGpu::AllocSpace(In<u32> pages, In<u32> pageSize, In<MappingFlags> flags, InOut<u64> offset) {
|
||||||
|
// TODO: track this on the nvdrv side and have the gmmu only do virt -> phys
|
||||||
|
// Also fix error codes
|
||||||
|
u64 size{static_cast<u64>(pages) * static_cast<u64>(pageSize)};
|
||||||
|
|
||||||
|
if (flags.fixed)
|
||||||
|
offset = state.soc->gmmu.ReserveFixed(offset, size);
|
||||||
|
else
|
||||||
|
offset = state.soc->gmmu.ReserveSpace(size, offset); // offset contains the input alignment
|
||||||
|
|
||||||
|
if (offset == 0) {
|
||||||
|
state.logger->Warn("Failed to allocate GPU address space region!");
|
||||||
|
return PosixResult::InvalidArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PosixResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixResult AsGpu::FreeSpace(In<u64> offset, In<u32> pages, In<u32> pageSize) {
|
||||||
|
// TODO: implement this when we add nvdrv side address space allocation
|
||||||
|
return PosixResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixResult AsGpu::UnmapBuffer(In<u64> offset) {
|
||||||
|
try {
|
||||||
|
auto region{regionMap.at(offset)};
|
||||||
|
|
||||||
|
// Non-fixed regions are unmapped so that they can be used by future non-fixed mappings
|
||||||
|
if (!region.fixed)
|
||||||
|
if (!state.soc->gmmu.Unmap(offset, region.size))
|
||||||
|
state.logger->Warn("Failed to unmap region at 0x{:X}", offset);
|
||||||
|
|
||||||
|
regionMap.erase(offset);
|
||||||
|
} catch (const std::out_of_range &e) {
|
||||||
|
state.logger->Warn("Couldn't find region to unmap at 0x{:X}", offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PosixResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (flags.remap) {
|
||||||
|
auto region{regionMap.lower_bound(offset)};
|
||||||
|
if (region == regionMap.end()) {
|
||||||
|
state.logger->Warn("Cannot remap an unmapped GPU address space region: 0x{:X}", offset);
|
||||||
|
return PosixResult::InvalidArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (region->second.size < mappingSize) {
|
||||||
|
state.logger->Warn("Cannot remap an partially mapped GPU address space region: 0x{:X}", offset);
|
||||||
|
return PosixResult::InvalidArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 gpuAddress{offset + bufferOffset};
|
||||||
|
u8 *cpuPtr{region->second.ptr + bufferOffset};
|
||||||
|
|
||||||
|
if (!state.soc->gmmu.MapFixed(gpuAddress, cpuPtr, mappingSize)) {
|
||||||
|
state.logger->Warn("Failed to remap GPU address space region: 0x{:X}", gpuAddress);
|
||||||
|
return PosixResult::InvalidArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PosixResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto h{core.nvMap.GetHandle(handle)};
|
||||||
|
if (!h)
|
||||||
|
return PosixResult::InvalidArgument;
|
||||||
|
|
||||||
|
if (auto err{h->Duplicate(ctx.internalSession)}; err != PosixResult::Success)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
u8 *cpuPtr{reinterpret_cast<u8 *>(h->address + bufferOffset)};
|
||||||
|
u64 size{mappingSize ? mappingSize : h->origSize};
|
||||||
|
|
||||||
|
if (flags.fixed)
|
||||||
|
offset = state.soc->gmmu.MapFixed(offset, cpuPtr, size);
|
||||||
|
else
|
||||||
|
offset = state.soc->gmmu.MapAllocate(cpuPtr, size);
|
||||||
|
|
||||||
|
if (offset == 0) {
|
||||||
|
state.logger->Warn("Failed to map GPU address space region!");
|
||||||
|
return PosixResult::InvalidArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
regionMap[offset] = {cpuPtr, size, flags.fixed};
|
||||||
|
|
||||||
|
return PosixResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixResult AsGpu::GetVaRegions(In<u64> bufAddr, InOut<u32> bufSize, Out<std::array<VaRegion, 2>> vaRegions) {
|
||||||
|
// TODO: impl when we move allocator to nvdrv
|
||||||
|
return PosixResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
return PosixResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixResult AsGpu::Remap(span<RemapEntry> entries) {
|
||||||
|
constexpr u32 BigPageSize{0x10}; //!< The big page size of the GPU
|
||||||
|
|
||||||
|
for (const auto &entry : entries) {
|
||||||
|
auto h{core.nvMap.GetHandle(entry.handle)};
|
||||||
|
if (!h)
|
||||||
|
return PosixResult::InvalidArgument;
|
||||||
|
|
||||||
|
u64 virtAddr{static_cast<u64>(entry.asOffsetBigPages) << BigPageSize};
|
||||||
|
u8 *cpuPtr{reinterpret_cast<u8 *>(h->address + (static_cast<u64>(entry.handleOffsetBigPages) << BigPageSize))};
|
||||||
|
u64 size{static_cast<u64>(entry.bigPages) << BigPageSize};
|
||||||
|
|
||||||
|
state.soc->gmmu.MapFixed(virtAddr, cpuPtr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PosixResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <services/nvdrv/devices/deserialisation/macro_def.h>
|
||||||
|
static constexpr u32 AsGpuMagic{0x41};
|
||||||
|
|
||||||
|
VARIABLE_IOCTL_HANDLER_FUNC(AsGpu, ({
|
||||||
|
IOCTL_CASE_ARGS(IN, SIZE(0x4), MAGIC(AsGpuMagic), FUNC(0x1),
|
||||||
|
BindChannel, ARGS(In<FileDescriptor>))
|
||||||
|
IOCTL_CASE_ARGS(INOUT, SIZE(0x18), MAGIC(AsGpuMagic), FUNC(0x2),
|
||||||
|
AllocSpace, ARGS(In<u32>, In<u32>, In<MappingFlags>, Pad<u32>, InOut<u64>))
|
||||||
|
IOCTL_CASE_ARGS(INOUT, SIZE(0x10), MAGIC(AsGpuMagic), FUNC(0x3),
|
||||||
|
FreeSpace, ARGS(In<u64>, In<u32>, In<u32>))
|
||||||
|
IOCTL_CASE_ARGS(INOUT, SIZE(0x8), MAGIC(AsGpuMagic), FUNC(0x5),
|
||||||
|
UnmapBuffer, ARGS(In<u64>))
|
||||||
|
IOCTL_CASE_ARGS(INOUT, SIZE(0x28), MAGIC(AsGpuMagic), FUNC(0x6),
|
||||||
|
MapBufferEx, ARGS(In<MappingFlags>, In<u32>, In<core::NvMap::Handle::Id>, InOut<u32>, In<u64>, In<u64>, InOut<u64>))
|
||||||
|
IOCTL_CASE_ARGS(INOUT, SIZE(0x40), MAGIC(AsGpuMagic), FUNC(0x8),
|
||||||
|
GetVaRegions, ARGS(In<u64>, InOut<u32>, Pad<u32>, Out<std::array<VaRegion, 2>>))
|
||||||
|
IOCTL_CASE_ARGS(IN, SIZE(0x28), MAGIC(AsGpuMagic), FUNC(0x9),
|
||||||
|
AllocAsEx, ARGS(In<u32>, In<FileDescriptor>, In<u32>, Pad<u32>, In<u64>, In<u64>, In<u64>))
|
||||||
|
}), ({
|
||||||
|
VARIABLE_IOCTL_CASE_ARGS(INOUT, MAGIC(AsGpuMagic), FUNC(0x14),
|
||||||
|
Remap, ARGS(AutoSizeSpan<RemapEntry>))
|
||||||
|
}))
|
||||||
|
#include <services/nvdrv/devices/deserialisation/macro_undef.h>
|
||||||
|
}
|
102
app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/as_gpu.h
Normal file
102
app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/as_gpu.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR MPL-2.0
|
||||||
|
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <services/nvdrv/devices/nvdevice.h>
|
||||||
|
|
||||||
|
namespace skyline::service::nvdrv::device::nvhost {
|
||||||
|
/**
|
||||||
|
* @brief nvhost::AsGpu (/dev/nvhost-as-gpu) is used to access a GPU virtual address space
|
||||||
|
* @url https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvhost-as-gpu
|
||||||
|
*/
|
||||||
|
class AsGpu : public NvDevice {
|
||||||
|
private:
|
||||||
|
struct AddressSpaceRegion {
|
||||||
|
u8 *ptr;
|
||||||
|
u64 size;
|
||||||
|
bool fixed;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<u64, AddressSpaceRegion> regionMap; //!< This maps the base addresses of mapped buffers to their total sizes and mapping type, this is needed as what was originally a single buffer may have been split into multiple GPU side buffers with the remap flag.
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct MappingFlags {
|
||||||
|
bool fixed : 1;
|
||||||
|
u8 _pad0_ : 7;
|
||||||
|
bool remap : 1;
|
||||||
|
u32 _pad1_ : 23;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MappingFlags) == sizeof(u32));
|
||||||
|
|
||||||
|
struct VaRegion {
|
||||||
|
u64 offset;
|
||||||
|
u32 pageSize;
|
||||||
|
u32 _pad0_;
|
||||||
|
u64 pages;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(VaRegion) == 0x18);
|
||||||
|
|
||||||
|
struct RemapEntry {
|
||||||
|
u16 flags;
|
||||||
|
u16 kind;
|
||||||
|
core::NvMap::Handle::Id handle;
|
||||||
|
u32 handleOffsetBigPages;
|
||||||
|
u32 asOffsetBigPages;
|
||||||
|
u32 bigPages;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(RemapEntry) == 0x14);
|
||||||
|
|
||||||
|
AsGpu(const DeviceState &state, Core &core, const SessionContext &ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Binds this address space to a channel
|
||||||
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_BIND_CHANNEL
|
||||||
|
*/
|
||||||
|
PosixResult BindChannel(In<FileDescriptor> channelFd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reserves a region in this address space
|
||||||
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_FREE_SPACE
|
||||||
|
*/
|
||||||
|
PosixResult AllocSpace(In<u32> pages, In<u32> pageSize, In<MappingFlags> flags, InOut<u64> offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Frees an allocated region in this address space
|
||||||
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_FREE_SPACE
|
||||||
|
*/
|
||||||
|
PosixResult FreeSpace(In<u64> offset, In<u32> pages, In<u32> pageSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unmaps a region in this address space
|
||||||
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_UNMAP_BUFFER
|
||||||
|
*/
|
||||||
|
PosixResult UnmapBuffer(In<u64> offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maps a region into this address space with extra parameters
|
||||||
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX
|
||||||
|
*/
|
||||||
|
PosixResult 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns info about the address space and its page sizes
|
||||||
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_GET_VA_REGIONS
|
||||||
|
*/
|
||||||
|
PosixResult GetVaRegions(In<u64> bufAddr, InOut<u32> bufSize, Out<std::array<VaRegion, 2>> vaRegions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocates this address space with the given parameters
|
||||||
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_ALLOC_AS_EX
|
||||||
|
*/
|
||||||
|
PosixResult AllocAsEx(In<u32> bigPageSize, In<FileDescriptor> asFd, In<u32> flags, In<u64> vaRangeStart, In<u64> vaRangeEnd, In<u64> vaRangeSplit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remaps a region of the GPU address space
|
||||||
|
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_REMAP
|
||||||
|
*/
|
||||||
|
PosixResult Remap(span<RemapEntry> entries);
|
||||||
|
|
||||||
|
PosixResult Ioctl(IoctlDescriptor cmd, span<u8> buffer) override;
|
||||||
|
};
|
||||||
|
}
|
@ -1,196 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
|
||||||
|
|
||||||
#include <soc.h>
|
|
||||||
#include <services/nvdrv/driver.h>
|
|
||||||
#include "nvmap.h"
|
|
||||||
#include "nvhost_as_gpu.h"
|
|
||||||
|
|
||||||
namespace skyline::service::nvdrv::device {
|
|
||||||
struct MappingFlags {
|
|
||||||
bool fixed : 1;
|
|
||||||
u8 _pad0_ : 7;
|
|
||||||
bool remap : 1;
|
|
||||||
u32 _pad1_ : 23;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(MappingFlags) == sizeof(u32));
|
|
||||||
|
|
||||||
NvHostAsGpu::NvHostAsGpu(const DeviceState &state) : NvDevice(state) {}
|
|
||||||
|
|
||||||
NvStatus NvHostAsGpu::BindChannel(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
|
||||||
return NvStatus::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
NvStatus NvHostAsGpu::AllocSpace(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
|
||||||
struct Data {
|
|
||||||
u32 pages; // In
|
|
||||||
u32 pageSize; // In
|
|
||||||
MappingFlags flags; // In
|
|
||||||
u32 _pad_;
|
|
||||||
union {
|
|
||||||
u64 offset; // InOut
|
|
||||||
u64 align; // In
|
|
||||||
};
|
|
||||||
} ®ion = buffer.as<Data>();
|
|
||||||
|
|
||||||
u64 size{static_cast<u64>(region.pages) * static_cast<u64>(region.pageSize)};
|
|
||||||
|
|
||||||
if (region.flags.fixed)
|
|
||||||
region.offset = state.soc->gmmu.ReserveFixed(region.offset, size);
|
|
||||||
else
|
|
||||||
region.offset = state.soc->gmmu.ReserveSpace(size, region.align);
|
|
||||||
|
|
||||||
if (region.offset == 0) {
|
|
||||||
state.logger->Warn("Failed to allocate GPU address space region!");
|
|
||||||
return NvStatus::BadParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NvStatus::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
NvStatus NvHostAsGpu::UnmapBuffer(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
|
||||||
u64 offset{buffer.as<u64>()};
|
|
||||||
|
|
||||||
try {
|
|
||||||
auto region{regionMap.at(offset)};
|
|
||||||
|
|
||||||
// Non-fixed regions are unmapped so that they can be used by future non-fixed mappings
|
|
||||||
if (!region.fixed)
|
|
||||||
if (!state.soc->gmmu.Unmap(offset, region.size))
|
|
||||||
state.logger->Warn("Failed to unmap region at 0x{:X}", offset);
|
|
||||||
|
|
||||||
regionMap.erase(offset);
|
|
||||||
} catch (const std::out_of_range &e) {
|
|
||||||
state.logger->Warn("Couldn't find region to unmap at 0x{:X}", offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NvStatus::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
NvStatus NvHostAsGpu::Modify(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
|
||||||
struct Data {
|
|
||||||
MappingFlags flags; // In
|
|
||||||
u32 kind; // In
|
|
||||||
u32 nvmapHandle; // In
|
|
||||||
u32 pageSize; // InOut
|
|
||||||
u64 bufferOffset; // In
|
|
||||||
u64 mappingSize; // In
|
|
||||||
u64 offset; // InOut
|
|
||||||
} &data = buffer.as<Data>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (data.flags.remap) {
|
|
||||||
auto region{regionMap.lower_bound(data.offset)};
|
|
||||||
if (region == regionMap.end()) {
|
|
||||||
state.logger->Warn("Cannot remap an unmapped GPU address space region: 0x{:X}", data.offset);
|
|
||||||
return NvStatus::BadParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (region->second.size < data.mappingSize) {
|
|
||||||
state.logger->Warn("Cannot remap an partially mapped GPU address space region: 0x{:X}", data.offset);
|
|
||||||
return NvStatus::BadParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 gpuAddress{data.offset + data.bufferOffset};
|
|
||||||
u8 *cpuPtr{region->second.ptr + data.bufferOffset};
|
|
||||||
|
|
||||||
if (!state.soc->gmmu.MapFixed(gpuAddress, cpuPtr, data.mappingSize)) {
|
|
||||||
state.logger->Warn("Failed to remap GPU address space region: 0x{:X}", gpuAddress);
|
|
||||||
return NvStatus::BadParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NvStatus::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto driver{nvdrv::driver.lock()};
|
|
||||||
auto nvmap{driver->nvMap.lock()};
|
|
||||||
auto mapping{nvmap->GetObject(data.nvmapHandle)};
|
|
||||||
|
|
||||||
u8 *cpuPtr{data.bufferOffset + mapping->ptr};
|
|
||||||
u64 size{data.mappingSize ? data.mappingSize : mapping->size};
|
|
||||||
|
|
||||||
if (data.flags.fixed)
|
|
||||||
data.offset = state.soc->gmmu.MapFixed(data.offset, cpuPtr, size);
|
|
||||||
else
|
|
||||||
data.offset = state.soc->gmmu.MapAllocate(cpuPtr, size);
|
|
||||||
|
|
||||||
if (data.offset == 0) {
|
|
||||||
state.logger->Warn("Failed to map GPU address space region!");
|
|
||||||
return NvStatus::BadParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
regionMap[data.offset] = {cpuPtr, size, data.flags.fixed};
|
|
||||||
|
|
||||||
return NvStatus::Success;
|
|
||||||
} catch (const std::out_of_range &) {
|
|
||||||
state.logger->Warn("Invalid NvMap handle: 0x{:X}", data.nvmapHandle);
|
|
||||||
return NvStatus::BadParameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NvStatus NvHostAsGpu::GetVaRegions(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
|
||||||
/*
|
|
||||||
struct Data {
|
|
||||||
u64 _pad0_;
|
|
||||||
u32 bufferSize; // InOut
|
|
||||||
u32 _pad1_;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 offset;
|
|
||||||
u32 page_size;
|
|
||||||
u32 pad;
|
|
||||||
u64 pages;
|
|
||||||
} regions[2]; // Out
|
|
||||||
} ®ionInfo = buffer.as<Data>();
|
|
||||||
*/
|
|
||||||
return NvStatus::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
NvStatus NvHostAsGpu::AllocAsEx(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
|
||||||
/*
|
|
||||||
struct Data {
|
|
||||||
u32 bigPageSize; // In
|
|
||||||
i32 asFd; // In
|
|
||||||
u32 flags; // In
|
|
||||||
u32 reserved; // In
|
|
||||||
u64 vaRangeStart; // In
|
|
||||||
u64 vaRangeEnd; // In
|
|
||||||
u64 vaRangeSplit; // In
|
|
||||||
} addressSpace = buffer.as<Data>();
|
|
||||||
*/
|
|
||||||
return NvStatus::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
NvStatus NvHostAsGpu::Remap(IoctlType type, span<u8> buffer, span<u8> inlineBuffer) {
|
|
||||||
struct Entry {
|
|
||||||
u16 flags; // In
|
|
||||||
u16 kind; // In
|
|
||||||
u32 nvmapHandle; // In
|
|
||||||
u32 mapOffset; // In
|
|
||||||
u32 gpuOffset; // In
|
|
||||||
u32 pages; // In
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr u32 MinAlignmentShift{0x10}; // This shift is applied to all addresses passed to Remap
|
|
||||||
|
|
||||||
auto entries{buffer.cast<Entry>()};
|
|
||||||
for (const auto &entry : entries) {
|
|
||||||
try {
|
|
||||||
auto driver{nvdrv::driver.lock()};
|
|
||||||
auto nvmap{driver->nvMap.lock()};
|
|
||||||
auto mapping{nvmap->GetObject(entry.nvmapHandle)};
|
|
||||||
|
|
||||||
u64 virtAddr{static_cast<u64>(entry.gpuOffset) << MinAlignmentShift};
|
|
||||||
u8 *cpuPtr{mapping->ptr + (static_cast<u64>(entry.mapOffset) << MinAlignmentShift)};
|
|
||||||
u64 size{static_cast<u64>(entry.pages) << MinAlignmentShift};
|
|
||||||
|
|
||||||
state.soc->gmmu.MapFixed(virtAddr, cpuPtr, size);
|
|
||||||
} catch (const std::out_of_range &) {
|
|
||||||
state.logger->Warn("Invalid NvMap handle: 0x{:X}", entry.nvmapHandle);
|
|
||||||
return NvStatus::BadParameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NvStatus::Success;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "nvdevice.h"
|
|
||||||
|
|
||||||
namespace skyline::service::nvdrv::device {
|
|
||||||
/**
|
|
||||||
* @brief NvHostAsGpu (/dev/nvhost-as-gpu) is used to access GPU virtual address spaces
|
|
||||||
* @url https://switchbrew.org/wiki/NV_services#.2Fdev.2Fnvhost-as-gpu
|
|
||||||
*/
|
|
||||||
class NvHostAsGpu : public NvDevice {
|
|
||||||
private:
|
|
||||||
struct AddressSpaceRegion {
|
|
||||||
u8 *ptr;
|
|
||||||
u64 size;
|
|
||||||
bool fixed;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<u64, AddressSpaceRegion> regionMap; //!< This maps the base addresses of mapped buffers to their total sizes and mapping type, this is needed as what was originally a single buffer may have been split into multiple GPU side buffers with the remap flag.
|
|
||||||
|
|
||||||
public:
|
|
||||||
NvHostAsGpu(const DeviceState &state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Binds a channel to the address space
|
|
||||||
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_BIND_CHANNEL
|
|
||||||
*/
|
|
||||||
NvStatus BindChannel(IoctlType type, span <u8> buffer, span <u8> inlineBuffer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reserves a region in the GPU address space
|
|
||||||
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE
|
|
||||||
*/
|
|
||||||
NvStatus AllocSpace(IoctlType type, span <u8> buffer, span <u8> inlineBuffer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unmaps a region in the GPU address space
|
|
||||||
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_UNMAP_BUFFER
|
|
||||||
*/
|
|
||||||
NvStatus UnmapBuffer(IoctlType type, span <u8> buffer, span <u8> inlineBuffer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Maps a region in the GPU address space
|
|
||||||
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_MODIFY
|
|
||||||
*/
|
|
||||||
NvStatus Modify(IoctlType type, span <u8> buffer, span <u8> inlineBuffer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the application's GPU address space
|
|
||||||
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_GET_VA_REGIONS
|
|
||||||
*/
|
|
||||||
NvStatus GetVaRegions(IoctlType type, span <u8> buffer, span <u8> inlineBuffer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initializes the application's GPU address space
|
|
||||||
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_ALLOC_AS_EX
|
|
||||||
*/
|
|
||||||
NvStatus AllocAsEx(IoctlType type, span <u8> buffer, span <u8> inlineBuffer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remaps a region of the GPU address space
|
|
||||||
* @url https://switchbrew.org/wiki/NV_services#NVGPU_AS_IOCTL_REMAP
|
|
||||||
*/
|
|
||||||
NvStatus Remap(IoctlType type, span <u8> buffer, span <u8> inlineBuffer);
|
|
||||||
|
|
||||||
NVDEVICE_DECL(
|
|
||||||
NVFUNC(0x4101, NvHostAsGpu, BindChannel),
|
|
||||||
NVFUNC(0x4102, NvHostAsGpu, AllocSpace),
|
|
||||||
NVFUNC(0x4105, NvHostAsGpu, UnmapBuffer),
|
|
||||||
NVFUNC(0x4106, NvHostAsGpu, Modify),
|
|
||||||
NVFUNC(0x4108, NvHostAsGpu, GetVaRegions),
|
|
||||||
NVFUNC(0x4109, NvHostAsGpu, AllocAsEx),
|
|
||||||
NVFUNC(0x4114, NvHostAsGpu, Remap)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user