2020-04-19 23:04:05 +02:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
2020-03-27 20:36:02 +01:00
|
|
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
|
|
|
|
2020-07-14 16:15:28 +02:00
|
|
|
#include <gpu.h>
|
|
|
|
#include <os.h>
|
|
|
|
#include <kernel/types/KProcess.h>
|
|
|
|
#include <services/nvdrv/INvDrvServices.h>
|
|
|
|
#include "nvmap.h"
|
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
#include "nvhost_as_gpu.h"
|
|
|
|
|
2020-03-24 21:17:31 +01:00
|
|
|
namespace skyline::service::nvdrv::device {
|
2020-07-14 16:15:28 +02:00
|
|
|
NvHostAsGpu::NvHostAsGpu(const DeviceState &state) : NvDevice(state, NvDeviceType::nvhost_as_gpu, {
|
2020-08-09 15:26:45 +02:00
|
|
|
{0x4101, NFUNC(NvHostAsGpu::BindChannel)},
|
2020-07-14 16:15:28 +02:00
|
|
|
{0x4102, NFUNC(NvHostAsGpu::AllocSpace)},
|
2020-08-09 15:26:45 +02:00
|
|
|
{0x4105, NFUNC(NvHostAsGpu::UnmapBuffer)},
|
2020-07-14 16:15:28 +02:00
|
|
|
{0x4106, NFUNC(NvHostAsGpu::Modify)},
|
2020-08-09 15:26:45 +02:00
|
|
|
{0x4108, NFUNC(NvHostAsGpu::GetVaRegions)},
|
|
|
|
{0x4109, NFUNC(NvHostAsGpu::InitializeEx)},
|
|
|
|
{0x4114, NFUNC(NvHostAsGpu::Remap)},
|
2020-07-14 16:15:28 +02:00
|
|
|
}) {}
|
|
|
|
|
|
|
|
void NvHostAsGpu::BindChannel(IoctlData &buffer) {
|
|
|
|
struct Data {
|
|
|
|
u32 fd;
|
|
|
|
} channelInfo = state.process->GetReference<Data>(buffer.input.at(0).address);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NvHostAsGpu::AllocSpace(IoctlData &buffer) {
|
|
|
|
struct Data {
|
|
|
|
u32 pages;
|
|
|
|
u32 pageSize;
|
|
|
|
u32 flags;
|
|
|
|
u32 _pad_;
|
|
|
|
u64 offset;
|
|
|
|
} region = state.process->GetObject<Data>(buffer.input.at(0).address);
|
|
|
|
|
|
|
|
u64 size = static_cast<u64>(region.pages) * static_cast<u64>(region.pageSize);
|
|
|
|
|
|
|
|
if (region.flags & 1)
|
2020-08-09 17:01:38 +02:00
|
|
|
region.offset = state.gpu->memoryManager.ReserveFixed(region.offset, size);
|
2020-07-14 16:15:28 +02:00
|
|
|
else
|
2020-08-09 17:01:38 +02:00
|
|
|
region.offset = state.gpu->memoryManager.ReserveSpace(size);
|
2020-07-14 16:15:28 +02:00
|
|
|
|
|
|
|
if (region.offset == 0) {
|
|
|
|
state.logger->Warn("Failed to allocate GPU address space region!");
|
|
|
|
buffer.status = NvStatus::BadParameter;
|
|
|
|
}
|
|
|
|
|
|
|
|
state.process->WriteMemory(region, buffer.output.at(0).address);
|
|
|
|
}
|
|
|
|
|
2020-08-09 15:26:45 +02:00
|
|
|
void NvHostAsGpu::UnmapBuffer(IoctlData &buffer) {
|
|
|
|
auto offset = state.process->GetObject<u64>(buffer.input.at(0).address);
|
|
|
|
|
|
|
|
if (!state.gpu->memoryManager.Unmap(offset))
|
|
|
|
state.logger->Warn("Failed to unmap chunk at 0x{:X}", offset);
|
|
|
|
}
|
|
|
|
|
2020-07-14 16:15:28 +02:00
|
|
|
void NvHostAsGpu::Modify(IoctlData &buffer) {
|
|
|
|
struct Data {
|
|
|
|
u32 flags;
|
|
|
|
u32 kind;
|
|
|
|
u32 nvmapHandle;
|
|
|
|
u32 pageSize;
|
|
|
|
u64 bufferOffset;
|
|
|
|
u64 mappingSize;
|
|
|
|
u64 offset;
|
|
|
|
} region = state.process->GetObject<Data>(buffer.input.at(0).address);
|
|
|
|
|
|
|
|
if (!region.nvmapHandle)
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto nvmap = state.os->serviceManager.GetService<nvdrv::INvDrvServices>(Service::nvdrv_INvDrvServices)->GetDevice<nvdrv::device::NvMap>(nvdrv::device::NvDeviceType::nvmap)->handleTable.at(region.nvmapHandle);
|
|
|
|
|
|
|
|
u64 mapPhysicalAddress = region.bufferOffset + nvmap->address;
|
|
|
|
u64 mapSize = region.mappingSize ? region.mappingSize : nvmap->size;
|
|
|
|
|
|
|
|
if (region.flags & 1)
|
|
|
|
region.offset = state.gpu->memoryManager.MapFixed(region.offset, mapPhysicalAddress, mapSize);
|
|
|
|
else
|
2020-08-09 17:01:38 +02:00
|
|
|
region.offset = state.gpu->memoryManager.MapAllocate(mapPhysicalAddress, mapSize);
|
2020-07-14 16:15:28 +02:00
|
|
|
|
|
|
|
if (region.offset == 0) {
|
|
|
|
state.logger->Warn("Failed to map GPU address space region!");
|
|
|
|
buffer.status = NvStatus::BadParameter;
|
|
|
|
}
|
|
|
|
|
|
|
|
state.process->WriteMemory(region, buffer.output.at(0).address);
|
|
|
|
}
|
2020-08-09 15:26:45 +02:00
|
|
|
|
|
|
|
void NvHostAsGpu::GetVaRegions(IoctlData &buffer) {
|
|
|
|
struct Data {
|
|
|
|
u64 _pad0_;
|
|
|
|
u32 bufferSize;
|
|
|
|
u32 _pad1_;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
u64 offset;
|
|
|
|
u32 page_size;
|
|
|
|
u32 pad;
|
|
|
|
u64 pages;
|
|
|
|
} regions[2];
|
|
|
|
} regionInfo = state.process->GetReference<Data>(buffer.input.at(0).address);
|
|
|
|
state.process->WriteMemory(regionInfo, buffer.output.at(0).address);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NvHostAsGpu::InitializeEx(IoctlData &buffer) {
|
|
|
|
struct Data {
|
|
|
|
u32 bigPageSize;
|
|
|
|
i32 asFd;
|
|
|
|
u32 flags;
|
|
|
|
u32 reserved;
|
|
|
|
u64 vaRangeStart;
|
|
|
|
u64 vaRangeEnd;
|
|
|
|
u64 vaRangeSplit;
|
|
|
|
} addressSpace = state.process->GetObject<Data>(buffer.input.at(0).address);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NvHostAsGpu::Remap(IoctlData &buffer) {
|
|
|
|
struct Entry {
|
|
|
|
u16 flags;
|
|
|
|
u16 kind;
|
|
|
|
u32 nvmapHandle;
|
|
|
|
u32 mapOffset;
|
|
|
|
u32 gpuOffset;
|
|
|
|
u32 pages;
|
|
|
|
};
|
|
|
|
|
|
|
|
size_t entryCount{buffer.input.at(0).size / sizeof(Entry)};
|
|
|
|
std::span entries(state.process->GetPointer<Entry>(buffer.input.at(0).address), entryCount);
|
|
|
|
|
|
|
|
for (auto entry : entries) {
|
|
|
|
try {
|
|
|
|
auto nvmap = state.os->serviceManager.GetService<nvdrv::INvDrvServices>(Service::nvdrv_INvDrvServices)->GetDevice<nvdrv::device::NvMap>(nvdrv::device::NvDeviceType::nvmap)->handleTable.at(entry.nvmapHandle);
|
|
|
|
|
|
|
|
u64 mapAddress = static_cast<u64>(entry.gpuOffset) << 0x10;
|
|
|
|
u64 mapPhysicalAddress = nvmap->address + (static_cast<u64>(entry.mapOffset) << 0x10);
|
|
|
|
u64 mapSize = static_cast<u64>(entry.pages) << 0x10;
|
|
|
|
|
|
|
|
state.gpu->memoryManager.MapFixed(mapAddress, mapPhysicalAddress, mapSize);
|
|
|
|
} catch (const std::exception &e) {
|
|
|
|
buffer.status = NvStatus::BadValue;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
|
|
|
}
|