mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-09 13:36:35 +00:00
[nvdrv] Reset process resources for homebrew handoff
Track NVDRV sessions by process and aruid so in-place homebrew handoffs can close process-owned device files and sessions before loading the next NRO. Also unlock nvmap device-shared pages during session cleanup to avoid stale GPU mappings leaking across repeated handoffs.
This commit is contained in:
@@ -1,10 +1,15 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||||
// SPDX-FileCopyrightText: 2022 Skyline Team and Contributors
|
// SPDX-FileCopyrightText: 2022 Skyline Team and Contributors
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/service/nvdrv/core/container.h"
|
#include "core/hle/service/nvdrv/core/container.h"
|
||||||
@@ -40,6 +45,16 @@ Container::Container(Tegra::Host1x::Host1x& host1x_) {
|
|||||||
|
|
||||||
Container::~Container() = default;
|
Container::~Container() = default;
|
||||||
|
|
||||||
|
static bool IsSameProcess(Kernel::KProcess* lhs, Kernel::KProcess* rhs) {
|
||||||
|
if (lhs == rhs) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (lhs == nullptr || rhs == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return lhs->GetProcessId() == rhs->GetProcessId();
|
||||||
|
}
|
||||||
|
|
||||||
SessionId Container::OpenSession(Kernel::KProcess* process) {
|
SessionId Container::OpenSession(Kernel::KProcess* process) {
|
||||||
using namespace Common::Literals;
|
using namespace Common::Literals;
|
||||||
|
|
||||||
@@ -48,7 +63,7 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
|
|||||||
if (!session.is_active) {
|
if (!session.is_active) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (session.process == process) {
|
if (IsSameProcess(session.process, process)) {
|
||||||
session.ref_count++;
|
session.ref_count++;
|
||||||
return session.id;
|
return session.id;
|
||||||
}
|
}
|
||||||
@@ -116,7 +131,15 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
|
|||||||
|
|
||||||
void Container::CloseSession(SessionId session_id) {
|
void Container::CloseSession(SessionId session_id) {
|
||||||
std::scoped_lock lk(impl->session_guard);
|
std::scoped_lock lk(impl->session_guard);
|
||||||
|
if (session_id.id >= impl->sessions.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& session = impl->sessions[session_id.id];
|
auto& session = impl->sessions[session_id.id];
|
||||||
|
if (!session.is_active || session.ref_count <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (--session.ref_count > 0) {
|
if (--session.ref_count > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -134,6 +157,73 @@ void Container::CloseSession(SessionId session_id) {
|
|||||||
impl->id_pool.emplace_front(session_id.id);
|
impl->id_pool.emplace_front(session_id.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Container::CloseSessions(std::span<const SessionId> session_ids) {
|
||||||
|
std::vector<SessionId> valid_session_ids;
|
||||||
|
valid_session_ids.reserve(session_ids.size());
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock lk(impl->session_guard);
|
||||||
|
for (const auto session_id : session_ids) {
|
||||||
|
if (session_id.id >= impl->sessions.size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& session = impl->sessions[session_id.id];
|
||||||
|
if (!session.is_active) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto duplicate = std::ranges::any_of(
|
||||||
|
valid_session_ids, [session_id](const auto candidate) {
|
||||||
|
return candidate.id == session_id.id;
|
||||||
|
});
|
||||||
|
if (duplicate) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
session.ref_count = 1;
|
||||||
|
valid_session_ids.push_back(session_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto session_id : valid_session_ids) {
|
||||||
|
CloseSession(session_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid_session_ids.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SessionId> Container::GetSessionIdsForProcess(Kernel::KProcess* process) {
|
||||||
|
std::vector<SessionId> session_ids;
|
||||||
|
std::scoped_lock lk(impl->session_guard);
|
||||||
|
for (const auto& session : impl->sessions) {
|
||||||
|
if (!session.is_active || !IsSameProcess(session.process, process)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
session_ids.push_back(session.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return session_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SessionId> Container::GetActiveSessionIds() const {
|
||||||
|
std::vector<SessionId> session_ids;
|
||||||
|
std::scoped_lock lk(impl->session_guard);
|
||||||
|
for (const auto& session : impl->sessions) {
|
||||||
|
if (session.is_active) {
|
||||||
|
session_ids.push_back(session.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return session_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Container::IsSessionActive(SessionId session_id) const {
|
||||||
|
std::scoped_lock lk(impl->session_guard);
|
||||||
|
return session_id.id < impl->sessions.size() && impl->sessions[session_id.id].is_active;
|
||||||
|
}
|
||||||
|
|
||||||
Session* Container::GetSession(SessionId session_id) {
|
Session* Container::GetSession(SessionId session_id) {
|
||||||
std::atomic_thread_fence(std::memory_order_acquire);
|
std::atomic_thread_fence(std::memory_order_acquire);
|
||||||
return &impl->sessions[session_id.id];
|
return &impl->sessions[session_id.id];
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <span>
|
||||||
|
#include <cstddef>
|
||||||
#include <ankerl/unordered_dense.h>
|
#include <ankerl/unordered_dense.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "core/device_memory_manager.h"
|
#include "core/device_memory_manager.h"
|
||||||
#include "core/hle/service/nvdrv/nvdata.h"
|
#include "core/hle/service/nvdrv/nvdata.h"
|
||||||
@@ -59,6 +62,10 @@ public:
|
|||||||
|
|
||||||
SessionId OpenSession(Kernel::KProcess* process);
|
SessionId OpenSession(Kernel::KProcess* process);
|
||||||
void CloseSession(SessionId id);
|
void CloseSession(SessionId id);
|
||||||
|
size_t CloseSessions(std::span<const SessionId> session_ids);
|
||||||
|
std::vector<SessionId> GetSessionIdsForProcess(Kernel::KProcess* process);
|
||||||
|
std::vector<SessionId> GetActiveSessionIds() const;
|
||||||
|
bool IsSessionActive(SessionId id) const;
|
||||||
|
|
||||||
Session* GetSession(SessionId id);
|
Session* GetSession(SessionId id);
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,12 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/service/nvdrv/core/container.h"
|
#include "core/hle/service/nvdrv/core/container.h"
|
||||||
#include "core/hle/service/nvdrv/core/heap_mapper.h"
|
#include "core/hle/service/nvdrv/core/heap_mapper.h"
|
||||||
#include "core/hle/service/nvdrv/core/nvmap.h"
|
#include "core/hle/service/nvdrv/core/nvmap.h"
|
||||||
@@ -326,19 +328,65 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NvMap::UnmapAllHandles(NvCore::SessionId session_id) {
|
void NvMap::UnmapAllHandles(NvCore::SessionId session_id) {
|
||||||
auto handles_copy = [&] {
|
auto* session = core.GetSession(session_id);
|
||||||
|
auto* process = session != nullptr ? session->process : nullptr;
|
||||||
|
auto handle_ids = [&] {
|
||||||
std::scoped_lock lk{handles_lock};
|
std::scoped_lock lk{handles_lock};
|
||||||
return handles;
|
std::vector<Handle::Id> ids;
|
||||||
|
ids.reserve(handles.size());
|
||||||
|
|
||||||
|
for (const auto& entry : handles) {
|
||||||
|
ids.push_back(entry.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
for (auto& [id, handle] : handles_copy) {
|
for (const auto id : handle_ids) {
|
||||||
{
|
bool unlocked_pages = false;
|
||||||
std::scoped_lock lk{handle->mutex};
|
while (true) {
|
||||||
if (handle->session_id.id != session_id.id || handle->dupes <= 0) {
|
bool last_user_reference = false;
|
||||||
continue;
|
VAddr address = 0;
|
||||||
|
size_t size = 0;
|
||||||
|
{
|
||||||
|
const auto handle = GetHandle(id);
|
||||||
|
if (!handle) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::scoped_lock lk{handle->mutex};
|
||||||
|
if (handle->session_id.id != session_id.id || handle->dupes <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_user_reference = handle->dupes == 1;
|
||||||
|
address = handle->address;
|
||||||
|
size = handle->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto free_info = FreeHandle(id, false);
|
||||||
|
if (!free_info) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!unlocked_pages && process != nullptr && address != 0 && size != 0 &&
|
||||||
|
(free_info->can_unlock || last_user_reference)) {
|
||||||
|
const auto unlock_result =
|
||||||
|
process->GetPageTable().UnlockForDeviceAddressSpace(address, size);
|
||||||
|
if (unlock_result.IsError()) {
|
||||||
|
LOG_WARNING(Service_NVDRV,
|
||||||
|
"NextLoad: nvmap session cleanup unlock failed, "
|
||||||
|
"handle={}, session={}, address=0x{:016X}, size=0x{:X}, "
|
||||||
|
"result={:#X}",
|
||||||
|
id, session_id.id, address, size, unlock_result.raw);
|
||||||
|
}
|
||||||
|
unlocked_pages = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_user_reference) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FreeHandle(id, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2021 yuzu Emulator Project
|
||||||
// SPDX-FileCopyrightText: 2021 Skyline Team and Contributors
|
// SPDX-FileCopyrightText: 2021 Skyline Team and Contributors
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <fmt/ranges.h>
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/k_event.h"
|
#include "core/hle/kernel/k_event.h"
|
||||||
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
#include "core/hle/service/nvdrv/core/container.h"
|
#include "core/hle/service/nvdrv/core/container.h"
|
||||||
#include "core/hle/service/nvdrv/devices/nvdevice.h"
|
#include "core/hle/service/nvdrv/devices/nvdevice.h"
|
||||||
@@ -133,6 +138,9 @@ DeviceFD Module::Open(const std::string& device_name, NvCore::SessionId session_
|
|||||||
auto device = builder(fd)->second;
|
auto device = builder(fd)->second;
|
||||||
|
|
||||||
device->OnOpen(session_id, fd);
|
device->OnOpen(session_id, fd);
|
||||||
|
if (container.IsSessionActive(session_id)) {
|
||||||
|
open_file_sessions.emplace(fd, session_id);
|
||||||
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
@@ -204,6 +212,7 @@ NvResult Module::Close(DeviceFD fd) {
|
|||||||
itr->second->OnClose(fd);
|
itr->second->OnClose(fd);
|
||||||
|
|
||||||
open_files.erase(itr);
|
open_files.erase(itr);
|
||||||
|
open_file_sessions.erase(fd);
|
||||||
|
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
@@ -228,4 +237,98 @@ NvResult Module::QueryEvent(DeviceFD fd, u32 event_id, Kernel::KEvent*& event) {
|
|||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ContainsSession(std::span<const NvCore::SessionId> session_ids,
|
||||||
|
NvCore::SessionId session_id) {
|
||||||
|
return std::ranges::any_of(session_ids, [session_id](const auto candidate) {
|
||||||
|
return candidate.id == session_id.id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AppendUniqueSession(std::vector<NvCore::SessionId>& session_ids,
|
||||||
|
NvCore::SessionId session_id) {
|
||||||
|
if (!ContainsSession(session_ids, session_id)) {
|
||||||
|
session_ids.push_back(session_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Module::CloseFilesForSessions(std::span<const NvCore::SessionId> session_ids) {
|
||||||
|
std::vector<DeviceFD> fds;
|
||||||
|
fds.reserve(open_file_sessions.size());
|
||||||
|
|
||||||
|
for (const auto& [fd, session_id] : open_file_sessions) {
|
||||||
|
if (ContainsSession(session_ids, session_id)) {
|
||||||
|
fds.push_back(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto fd : fds) {
|
||||||
|
Close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fds.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::CloseSession(NvCore::SessionId session_id) {
|
||||||
|
container.CloseSession(session_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::TrackSessionAruid(NvCore::SessionId session_id, u64 aruid) {
|
||||||
|
const bool active = container.IsSessionActive(session_id);
|
||||||
|
if (active) {
|
||||||
|
session_aruids[session_id.id] = aruid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<NvCore::SessionId> Module::GetSessionIdsForAruid(u64 aruid) const {
|
||||||
|
std::vector<NvCore::SessionId> session_ids;
|
||||||
|
for (const auto& [session_id, session_aruid] : session_aruids) {
|
||||||
|
if (session_aruid == aruid) {
|
||||||
|
session_ids.push_back(NvCore::SessionId{session_id});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return session_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Module::ResetForProcess(Kernel::KProcess* process) {
|
||||||
|
const auto process_id = process != nullptr ? process->GetProcessId() : 0;
|
||||||
|
auto session_ids = container.GetSessionIdsForProcess(process);
|
||||||
|
|
||||||
|
if (process_id != 0) {
|
||||||
|
for (const auto session_id : GetSessionIdsForAruid(process_id)) {
|
||||||
|
AppendUniqueSession(session_ids, session_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto active_session_ids = container.GetActiveSessionIds();
|
||||||
|
const auto active_before = active_session_ids.size();
|
||||||
|
const bool has_active_candidate =
|
||||||
|
std::ranges::any_of(session_ids, [this](const auto session_id) {
|
||||||
|
return container.IsSessionActive(session_id);
|
||||||
|
});
|
||||||
|
bool used_active_sessions = false;
|
||||||
|
if (!has_active_candidate && !active_session_ids.empty()) {
|
||||||
|
for (const auto session_id : active_session_ids) {
|
||||||
|
AppendUniqueSession(session_ids, session_id);
|
||||||
|
}
|
||||||
|
used_active_sessions = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto closed_files = CloseFilesForSessions(session_ids);
|
||||||
|
const auto closed_sessions = container.CloseSessions(session_ids);
|
||||||
|
for (const auto session_id : session_ids) {
|
||||||
|
if (!container.IsSessionActive(session_id)) {
|
||||||
|
session_aruids.erase(session_id.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (used_active_sessions) {
|
||||||
|
LOG_WARNING(Service_NVDRV,
|
||||||
|
"NextLoad: NVDRV reset used active sessions because process-owned "
|
||||||
|
"sessions were not found, process_id={}, sessions={}, files={}, active_before={}",
|
||||||
|
process_id, closed_sessions, closed_files, active_before);
|
||||||
|
}
|
||||||
|
return closed_sessions;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::Nvidia
|
} // namespace Service::Nvidia
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <ankerl/unordered_dense.h>
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
@@ -26,6 +27,7 @@ class System;
|
|||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
class KEvent;
|
class KEvent;
|
||||||
|
class KProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::Nvidia {
|
namespace Service::Nvidia {
|
||||||
@@ -89,6 +91,9 @@ public:
|
|||||||
NvResult Close(DeviceFD fd);
|
NvResult Close(DeviceFD fd);
|
||||||
|
|
||||||
NvResult QueryEvent(DeviceFD fd, u32 event_id, Kernel::KEvent*& event);
|
NvResult QueryEvent(DeviceFD fd, u32 event_id, Kernel::KEvent*& event);
|
||||||
|
void CloseSession(NvCore::SessionId session_id);
|
||||||
|
void TrackSessionAruid(NvCore::SessionId session_id, u64 aruid);
|
||||||
|
size_t ResetForProcess(Kernel::KProcess* process);
|
||||||
|
|
||||||
NvCore::Container& GetContainer() {
|
NvCore::Container& GetContainer() {
|
||||||
return container;
|
return container;
|
||||||
@@ -106,12 +111,17 @@ private:
|
|||||||
using FilesContainerType = ankerl::unordered_dense::map<DeviceFD, std::shared_ptr<Devices::nvdevice>>;
|
using FilesContainerType = ankerl::unordered_dense::map<DeviceFD, std::shared_ptr<Devices::nvdevice>>;
|
||||||
/// Mapping of file descriptors to the devices they reference.
|
/// Mapping of file descriptors to the devices they reference.
|
||||||
FilesContainerType open_files;
|
FilesContainerType open_files;
|
||||||
|
ankerl::unordered_dense::map<DeviceFD, NvCore::SessionId> open_file_sessions;
|
||||||
|
ankerl::unordered_dense::map<size_t, u64> session_aruids;
|
||||||
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
KernelHelpers::ServiceContext service_context;
|
||||||
|
|
||||||
EventInterface events_interface;
|
EventInterface events_interface;
|
||||||
|
|
||||||
ankerl::unordered_dense::map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
|
ankerl::unordered_dense::map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
|
||||||
|
|
||||||
|
size_t CloseFilesForSessions(std::span<const NvCore::SessionId> session_ids);
|
||||||
|
std::vector<NvCore::SessionId> GetSessionIdsForAruid(u64 aruid) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void LoopProcess(Core::System& system);
|
void LoopProcess(Core::System& system);
|
||||||
|
|||||||
@@ -212,7 +212,10 @@ void NVDRV::QueryEvent(HLERequestContext& ctx) {
|
|||||||
void NVDRV::SetAruid(HLERequestContext& ctx) {
|
void NVDRV::SetAruid(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
pid = rp.Pop<u64>();
|
pid = rp.Pop<u64>();
|
||||||
LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid={:#x}", pid);
|
LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid={:#X}", pid);
|
||||||
|
if (is_initialized) {
|
||||||
|
nvdrv->TrackSessionAruid(session_id, pid);
|
||||||
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
|||||||
Reference in New Issue
Block a user