|
|
|
@ -13,7 +13,8 @@
|
|
|
|
|
using Core::Memory::YUZU_PAGESIZE;
|
|
|
|
|
|
|
|
|
|
namespace Service::Nvidia::NvCore {
|
|
|
|
|
NvMap::Handle::Handle(u64 size, Id id) : size(size), aligned_size(size), orig_size(size), id(id) {
|
|
|
|
|
NvMap::Handle::Handle(u64 size_, Id id_)
|
|
|
|
|
: size(size_), aligned_size(size), orig_size(size), id(id_) {
|
|
|
|
|
flags.raw = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -21,19 +22,21 @@ NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress)
|
|
|
|
|
std::scoped_lock lock(mutex);
|
|
|
|
|
|
|
|
|
|
// Handles cannot be allocated twice
|
|
|
|
|
if (allocated)
|
|
|
|
|
if (allocated) {
|
|
|
|
|
return NvResult::AccessDenied;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flags = pFlags;
|
|
|
|
|
kind = pKind;
|
|
|
|
|
align = pAlign < YUZU_PAGESIZE ? YUZU_PAGESIZE : pAlign;
|
|
|
|
|
|
|
|
|
|
// This flag is only applicable for handles with an address passed
|
|
|
|
|
if (pAddress)
|
|
|
|
|
flags.keep_uncached_after_free = 0;
|
|
|
|
|
else
|
|
|
|
|
if (pAddress) {
|
|
|
|
|
flags.keep_uncached_after_free.Assign(0);
|
|
|
|
|
} else {
|
|
|
|
|
LOG_CRITICAL(Service_NVDRV,
|
|
|
|
|
"Mapping nvmap handles without a CPU side address is unimplemented!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size = Common::AlignUp(size, YUZU_PAGESIZE);
|
|
|
|
|
aligned_size = Common::AlignUp(size, align);
|
|
|
|
@ -48,17 +51,19 @@ NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress)
|
|
|
|
|
|
|
|
|
|
NvResult NvMap::Handle::Duplicate(bool internal_session) {
|
|
|
|
|
// Unallocated handles cannot be duplicated as duplication requires memory accounting (in HOS)
|
|
|
|
|
if (!allocated) [[unlikely]]
|
|
|
|
|
if (!allocated) [[unlikely]] {
|
|
|
|
|
return NvResult::BadValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::scoped_lock lock(mutex);
|
|
|
|
|
|
|
|
|
|
// If we internally use FromId the duplication tracking of handles won't work accurately due to
|
|
|
|
|
// us not implementing per-process handle refs.
|
|
|
|
|
if (internal_session)
|
|
|
|
|
if (internal_session) {
|
|
|
|
|
internal_dupes++;
|
|
|
|
|
else
|
|
|
|
|
} else {
|
|
|
|
|
dupes++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NvResult::Success;
|
|
|
|
|
}
|
|
|
|
@ -92,8 +97,9 @@ bool NvMap::TryRemoveHandle(const Handle& handle_description) {
|
|
|
|
|
std::scoped_lock lock(handles_lock);
|
|
|
|
|
|
|
|
|
|
auto it{handles.find(handle_description.id)};
|
|
|
|
|
if (it != handles.end())
|
|
|
|
|
if (it != handles.end()) {
|
|
|
|
|
handles.erase(it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
@ -102,8 +108,9 @@ bool NvMap::TryRemoveHandle(const Handle& handle_description) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NvResult NvMap::CreateHandle(u64 size, std::shared_ptr<NvMap::Handle>& result_out) {
|
|
|
|
|
if (!size) [[unlikely]]
|
|
|
|
|
if (!size) [[unlikely]] {
|
|
|
|
|
return NvResult::BadValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u32 id{next_handle_id.fetch_add(HandleIdIncrement, std::memory_order_relaxed)};
|
|
|
|
|
auto handle_description{std::make_shared<Handle>(size, id)};
|
|
|
|
@ -133,8 +140,9 @@ VAddr NvMap::GetHandleAddress(Handle::Id handle) {
|
|
|
|
|
|
|
|
|
|
u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
|
|
|
|
|
auto handle_description{GetHandle(handle)};
|
|
|
|
|
if (!handle_description) [[unlikely]]
|
|
|
|
|
if (!handle_description) [[unlikely]] {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::scoped_lock lock(handle_description->mutex);
|
|
|
|
|
if (!handle_description->pins) {
|
|
|
|
@ -183,8 +191,9 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
|
|
|
|
|
|
|
|
|
|
void NvMap::UnpinHandle(Handle::Id handle) {
|
|
|
|
|
auto handle_description{GetHandle(handle)};
|
|
|
|
|
if (!handle_description)
|
|
|
|
|
if (!handle_description) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::scoped_lock lock(handle_description->mutex);
|
|
|
|
|
if (--handle_description->pins < 0) {
|
|
|
|
@ -226,12 +235,13 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna
|
|
|
|
|
|
|
|
|
|
// Try to remove the shared ptr to the handle from the map, if nothing else is using the
|
|
|
|
|
// handle then it will now be freed when `handle_description` goes out of scope
|
|
|
|
|
if (TryRemoveHandle(*handle_description))
|
|
|
|
|
if (TryRemoveHandle(*handle_description)) {
|
|
|
|
|
LOG_DEBUG(Service_NVDRV, "Removed nvmap handle: {}", handle);
|
|
|
|
|
else
|
|
|
|
|
} else {
|
|
|
|
|
LOG_DEBUG(Service_NVDRV,
|
|
|
|
|
"Tried to free nvmap handle: {} but didn't as it still has duplicates",
|
|
|
|
|
handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
freeInfo = {
|
|
|
|
|
.address = handle_description->address,
|
|
|
|
|