mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 09:51:48 +01:00
Implement AsGpu::FreeSpace and clean up locking and debug prints
This commit is contained in:
parent
4a7700bd7c
commit
b57710f260
@ -22,7 +22,13 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult AsGpu::AllocSpace(In<u32> pages, In<u32> pageSize, In<MappingFlags> flags, InOut<u64> offset) {
|
||||
state.logger->Debug("pages: 0x{:X}, pageSize: 0x{:X}, flags: ( fixed: {}, sparse: {} ), offset: 0x{:X}", pages, pageSize, flags.fixed, flags.sparse, offset);
|
||||
state.logger->Debug("pages: 0x{:X}, pageSize: 0x{:X}, flags: ( fixed: {}, sparse: {} ), offset: 0x{:X}",
|
||||
pages, pageSize, flags.fixed, flags.sparse, offset);
|
||||
|
||||
std::scoped_lock lock(mutex);
|
||||
|
||||
if (!vm.initialised)
|
||||
return PosixResult::InvalidArgument;
|
||||
|
||||
if (pageSize != VM::PageSize && pageSize != vm.bigPageSize)
|
||||
return PosixResult::InvalidArgument;
|
||||
@ -44,7 +50,7 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
else
|
||||
offset = static_cast<u64>(allocator->Allocate(pages)) << pageSizeBits;
|
||||
|
||||
u64 size{static_cast<u64>(pages) * static_cast<u64>(pageSize)};
|
||||
u64 size{static_cast<u64>(pages) * pageSize};
|
||||
|
||||
if (flags.sparse)
|
||||
state.soc->gm20b.gmmu.Map(offset, GMMU::SparsePlaceholderAddress(), size, true);
|
||||
@ -58,14 +64,67 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
||||
void AsGpu::FreeMappingLocked(u64 offset) {
|
||||
auto mapping{mappingMap.at(offset)};
|
||||
|
||||
if (!mapping->fixed) {
|
||||
auto &allocator{mapping->bigPage ? vm.bigPageAllocator : vm.smallPageAllocator};
|
||||
u32 pageSizeBits{mapping->bigPage ? vm.bigPageSizeBits : VM::PageSizeBits};
|
||||
|
||||
allocator->Free(mapping->offset >> pageSizeBits, mapping->size >> pageSizeBits);
|
||||
}
|
||||
|
||||
// Sparse mappings shouldn't be fully unmapped, just returned to their sparse state
|
||||
// Only FreeSpace can unmap them fully
|
||||
if (mapping->sparseAlloc)
|
||||
state.soc->gm20b.gmmu.Map(offset, GMMU::SparsePlaceholderAddress(), mapping->size, true);
|
||||
else
|
||||
state.soc->gm20b.gmmu.Unmap(offset, mapping->size);
|
||||
|
||||
mappingMap.erase(offset);
|
||||
}
|
||||
|
||||
PosixResult AsGpu::FreeSpace(In<u64> offset, In<u32> pages, In<u32> pageSize) {
|
||||
// TODO: implement after UNMAP
|
||||
state.logger->Debug("offset: 0x{:X}, pages: 0x{:X}, pageSize: 0x{:X}", offset, pages, pageSize);
|
||||
|
||||
std::scoped_lock lock(mutex);
|
||||
|
||||
if (!vm.initialised)
|
||||
return PosixResult::InvalidArgument;
|
||||
|
||||
try {
|
||||
auto allocation{allocationMap[offset]};
|
||||
|
||||
if (allocation.pageSize != pageSize || allocation.size != (static_cast<u64>(pages) * pageSize))
|
||||
return PosixResult::InvalidArgument;
|
||||
|
||||
for (const auto &mapping : allocation.mappings)
|
||||
FreeMapping(mapping->offset);
|
||||
|
||||
// Unset sparse flag if required
|
||||
if (allocation.sparse)
|
||||
state.soc->gm20b.gmmu.Unmap(offset, allocation.size);
|
||||
|
||||
auto &allocator{pageSize == VM::PageSize ? vm.smallPageAllocator : vm.bigPageAllocator};
|
||||
u32 pageSizeBits{pageSize == VM::PageSize ? VM::PageSizeBits : vm.bigPageSizeBits};
|
||||
|
||||
allocator->Free(offset >> pageSizeBits, allocation.size >> pageSizeBits);
|
||||
allocationMap.erase(offset);
|
||||
} catch (const std::out_of_range &e) {
|
||||
return PosixResult::InvalidArgument;
|
||||
}
|
||||
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
||||
PosixResult AsGpu::UnmapBuffer(In<u64> offset) {
|
||||
state.logger->Debug("offset: 0x{:X}", offset);
|
||||
|
||||
std::scoped_lock lock(mutex);
|
||||
|
||||
if (!vm.initialised)
|
||||
return PosixResult::InvalidArgument;
|
||||
|
||||
try {
|
||||
auto mapping{mappingMap.at(offset)};
|
||||
|
||||
@ -92,11 +151,13 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult AsGpu::MapBufferEx(In<MappingFlags> flags, In<u32> kind, In<core::NvMap::Handle::Id> handle, In<u64> bufferOffset, In<u64> mappingSize, InOut<u64> offset) {
|
||||
state.logger->Debug("flags: ( fixed: {}, remap: {} ), kind: {}, handle: {}, bufferOffset: 0x{:X}, mappingSize: 0x{:X}, offset: 0x{:X}", flags.fixed, flags.remap, kind, handle, bufferOffset, mappingSize, offset);
|
||||
|
||||
std::scoped_lock lock(mutex);
|
||||
|
||||
if (!vm.initialised)
|
||||
return PosixResult::InvalidArgument;
|
||||
|
||||
state.logger->Debug("flags: ( fixed: {}, remap: {} ), kind: {}, handle: {}, bufferOffset: 0x{:X}, mappingSize: 0x{:X}, offset: 0x{:X}", flags.fixed, flags.remap, kind, handle, bufferOffset, mappingSize, offset);
|
||||
|
||||
// Remaps a subregion of an existing mapping to a different PA
|
||||
if (flags.remap) {
|
||||
try {
|
||||
@ -164,6 +225,8 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult AsGpu::GetVaRegions(In<u64> bufAddr, InOut<u32> bufSize, Out<std::array<VaRegion, 2>> vaRegions) {
|
||||
std::scoped_lock lock(mutex);
|
||||
|
||||
if (!vm.initialised)
|
||||
return PosixResult::InvalidArgument;
|
||||
|
||||
@ -188,6 +251,8 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult AsGpu::AllocAsEx(In<u32> flags, In<FileDescriptor> asFd, In<u32> bigPageSize, In<u64> vaRangeStart, In<u64> vaRangeEnd, In<u64> vaRangeSplit) {
|
||||
std::scoped_lock lock(mutex);
|
||||
|
||||
if (vm.initialised)
|
||||
throw exception("Cannot initialise an address space twice!");
|
||||
|
||||
@ -232,6 +297,11 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult AsGpu::Remap(span<RemapEntry> entries) {
|
||||
std::scoped_lock lock(mutex);
|
||||
|
||||
if (!vm.initialised)
|
||||
return PosixResult::InvalidArgument;
|
||||
|
||||
for (const auto &entry : entries) {
|
||||
u64 virtAddr{static_cast<u64>(entry.asOffsetBigPages) << vm.bigPageSizeBits};
|
||||
u64 size{static_cast<u64>(entry.bigPages) << vm.bigPageSizeBits};
|
||||
|
@ -38,9 +38,8 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
};
|
||||
|
||||
std::map<u64, std::shared_ptr<Mapping>> mappingMap; //!< 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.
|
||||
|
||||
std::map<u64, Allocation> allocationMap;
|
||||
|
||||
std::map<u64, Allocation> allocationMap; //!< Holds allocations created by AllocSpace from which fixed buffers can be mapped into
|
||||
std::mutex mutex; //!< Locks all AS operations
|
||||
|
||||
struct VM {
|
||||
static constexpr u32 PageSize{0x1000};
|
||||
@ -66,6 +65,7 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
bool initialised{};
|
||||
} vm;
|
||||
|
||||
void FreeMappingLocked(u64 offset);
|
||||
|
||||
public:
|
||||
struct MappingFlags {
|
||||
|
@ -70,6 +70,9 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult Ctrl::SyncpointWaitEventImpl(In<Fence> fence, In<i32> timeout, InOut<SyncpointEventValue> value, bool allocate) {
|
||||
state.logger->Debug("fence: ( id: {}, threshold: {} ), timeout: {}, value: {}, allocate: {}",
|
||||
fence.id, fence.threshold, timeout, value.val, allocate);
|
||||
|
||||
if (fence.id >= soc::host1x::SyncpointCount)
|
||||
return PosixResult::InvalidArgument;
|
||||
|
||||
@ -147,6 +150,8 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult Ctrl::SyncpointClearEventWait(In<SyncpointEventValue> value) {
|
||||
state.logger->Debug("slot: {}", value.slot);
|
||||
|
||||
u16 slot{value.slot};
|
||||
if (slot >= SyncpointEventCount)
|
||||
return PosixResult::InvalidArgument;
|
||||
@ -178,7 +183,7 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult Ctrl::SyncpointAllocateEvent(In<u32> slot) {
|
||||
state.logger->Debug("Registering syncpoint event: {}", slot);
|
||||
state.logger->Debug("slot: {}", slot);
|
||||
|
||||
if (slot >= SyncpointEventCount)
|
||||
return PosixResult::InvalidArgument;
|
||||
@ -196,11 +201,15 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult Ctrl::SyncpointFreeEvent(In<u32> slot) {
|
||||
state.logger->Debug("slot: {}", slot);
|
||||
|
||||
std::lock_guard lock(syncpointEventMutex);
|
||||
return SyncpointFreeEventLocked(slot);
|
||||
}
|
||||
|
||||
PosixResult Ctrl::SyncpointFreeEventBatch(In<u64> bitmask) {
|
||||
state.logger->Debug("bitmask: 0x{:X}", bitmask);
|
||||
|
||||
auto err{PosixResult::Success};
|
||||
|
||||
// Avoid repeated locks/unlocks by just locking now
|
||||
|
@ -15,14 +15,23 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult GpuChannel::SetNvmapFd(In<core::NvMap::Handle::Id> id) {
|
||||
state.logger->Debug("id: {}", id);
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
||||
PosixResult GpuChannel::SetTimeout(In<u32> timeout) {
|
||||
state.logger->Debug("timeout: {}", timeout);
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
||||
PosixResult GpuChannel::SubmitGpfifo(In<u64> userAddress, In<u32> numEntries, InOut<SubmitGpfifoFlags> flags, InOut<Fence> fence, span<soc::gm20b::GpEntry> gpEntries) {
|
||||
state.logger->Debug("userAddress: 0x{:X}, numEntries: {},"
|
||||
"flags ( fenceWait: {}, fenceIncrement: {}, hwFormat: {}, suppressWfi: {}, incrementWithValue: {}),"
|
||||
"fence ( id: {}, threshold: {} )",
|
||||
userAddress, numEntries,
|
||||
+flags.fenceWait, +flags.fenceIncrement, +flags.hwFormat, +flags.suppressWfi, +flags.incrementWithValue,
|
||||
fence.id, fence.threshold);
|
||||
|
||||
if (numEntries > gpEntries.size())
|
||||
throw exception("GpEntry size mismatch!");
|
||||
|
||||
@ -54,22 +63,27 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult GpuChannel::AllocObjCtx(In<u32> classId, In<u32> flags, Out<u64> objId) {
|
||||
state.logger->Debug("classId: 0x{:X}, flags: 0x{:X}", classId, flags);
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
||||
PosixResult GpuChannel::ZcullBind(In<u64> gpuVa, In<u32> mode) {
|
||||
state.logger->Debug("gpuVa: 0x{:X}, mode: {}", gpuVa, mode);
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
||||
PosixResult GpuChannel::SetErrorNotifier(In<u64> offset, In<u64> size, In<u32> mem) {
|
||||
state.logger->Debug("offset: 0x{:X}, size: 0x{:X}, mem: 0x{:X}", offset, size, mem);
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
||||
PosixResult GpuChannel::SetPriority(In<u32> priority) {
|
||||
state.logger->Debug("priority: {}", priority);
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
||||
PosixResult GpuChannel::AllocGpfifoEx2(In<u32> numEntries, In<u32> numJobs, In<u32> flags, Out<Fence> fence) {
|
||||
state.logger->Debug("numEntries: {}, numJobs: {}, flags: 0x{:X}", numEntries, numJobs, flags);
|
||||
state.soc->gm20b.gpfifo.Initialize(numEntries);
|
||||
|
||||
fence = core.syncpointManager.GetSyncpointFence(channelSyncpoint);
|
||||
@ -78,10 +92,12 @@ namespace skyline::service::nvdrv::device::nvhost {
|
||||
}
|
||||
|
||||
PosixResult GpuChannel::SetTimeslice(In<u32> timeslice) {
|
||||
state.logger->Debug("timeslice: {}", timeslice);
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
||||
PosixResult GpuChannel::SetUserData(In<u64> userData) {
|
||||
state.logger->Debug("userData: 0x{:X}", userData);
|
||||
channelUserData = userData;
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ namespace skyline::service::nvdrv::device {
|
||||
}
|
||||
|
||||
PosixResult NvMap::FromId(In<NvMapCore::Handle::Id> id, Out<NvMapCore::Handle::Id> handle) {
|
||||
state.logger->Debug("id: {}", id);
|
||||
|
||||
// Handles and IDs are always the same value in nvmap however IDs can be used globally given the right permissions.
|
||||
// Since we don't plan on ever supporting multiprocess we can skip implementing handle refs and so this function
|
||||
// just does simple validation and passes through the handle id.
|
||||
@ -34,6 +36,8 @@ namespace skyline::service::nvdrv::device {
|
||||
}
|
||||
|
||||
PosixResult NvMap::Alloc(In<NvMapCore::Handle::Id> handle, In<u32> heapMask, In<NvMapCore::Handle::Flags> flags, InOut<u32> align, In<u8> kind, In<u64> address) {
|
||||
state.logger->Debug("handle: {}, flags: ( mapUncached: {}, keepUncachedAfterFree: {} ), align: 0x{:X}, kind: {}, address: 0x{:X}", handle, flags.mapUncached, flags.keepUncachedAfterFree, align, kind, address);
|
||||
|
||||
if (!handle) [[unlikely]]
|
||||
return PosixResult::InvalidArgument;
|
||||
|
||||
@ -48,12 +52,12 @@ namespace skyline::service::nvdrv::device {
|
||||
if (!h) [[unlikely]]
|
||||
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);
|
||||
}
|
||||
|
||||
PosixResult NvMap::Free(In<NvMapCore::Handle::Id> handle, Out<u64> address, Out<u32> size, Out<NvMapCore::Handle::Flags> flags) {
|
||||
state.logger->Debug("handle: {}", handle);
|
||||
|
||||
if (!handle) [[unlikely]]
|
||||
return PosixResult::Success;
|
||||
|
||||
@ -61,12 +65,16 @@ namespace skyline::service::nvdrv::device {
|
||||
address = freeInfo->address;
|
||||
size = static_cast<u32>(freeInfo->size);
|
||||
flags = NvMapCore::Handle::Flags{ .mapUncached = freeInfo->wasUncached };
|
||||
} else {
|
||||
state.logger->Debug("Handle not freed");
|
||||
}
|
||||
|
||||
return PosixResult::Success;
|
||||
}
|
||||
|
||||
PosixResult NvMap::Param(In<NvMapCore::Handle::Id> handle, In<HandleParameterType> param, Out<u32> result) {
|
||||
state.logger->Debug("handle: {}, param: {}", handle, param);
|
||||
|
||||
if (!handle)
|
||||
return PosixResult::InvalidArgument;
|
||||
|
||||
@ -103,6 +111,8 @@ namespace skyline::service::nvdrv::device {
|
||||
}
|
||||
|
||||
PosixResult NvMap::GetId(Out<NvMapCore::Handle::Id> id, In<NvMapCore::Handle::Id> handle) {
|
||||
state.logger->Debug("handle: {}", handle);
|
||||
|
||||
// See the comment in FromId for extra info on this function
|
||||
if (!handle) [[unlikely]]
|
||||
return PosixResult::InvalidArgument;
|
||||
|
Loading…
Reference in New Issue
Block a user