early-access version 4035

This commit is contained in:
pineappleEA
2023-12-26 19:43:46 +01:00
parent 78439b177e
commit 59fe352210
58 changed files with 834 additions and 363 deletions

View File

@@ -978,6 +978,7 @@ endif()
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
target_sources(core PRIVATE
arm/dynarmic/arm_dynarmic.cpp
arm/dynarmic/arm_dynarmic.h
arm/dynarmic/arm_dynarmic_64.cpp
arm/dynarmic/arm_dynarmic_64.h

View File

@@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef __linux__
#include "common/signal_chain.h"
#include "core/arm/dynarmic/arm_dynarmic.h"
#include "core/hle/kernel/k_process.h"
#include "core/memory.h"
namespace Core {
namespace {
thread_local Core::Memory::Memory* g_current_memory{};
std::once_flag g_registered{};
struct sigaction g_old_segv {};
void HandleSigSegv(int sig, siginfo_t* info, void* ctx) {
if (g_current_memory && g_current_memory->InvalidateSeparateHeap(info->si_addr)) {
return;
}
return g_old_segv.sa_sigaction(sig, info, ctx);
}
} // namespace
ScopedJitExecution::ScopedJitExecution(Kernel::KProcess* process) {
g_current_memory = std::addressof(process->GetMemory());
}
ScopedJitExecution::~ScopedJitExecution() {
g_current_memory = nullptr;
}
void ScopedJitExecution::RegisterHandler() {
std::call_once(g_registered, [] {
struct sigaction sa {};
sa.sa_sigaction = &HandleSigSegv;
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
Common::SigAction(SIGSEGV, std::addressof(sa), std::addressof(g_old_segv));
});
}
} // namespace Core
#endif

View File

@@ -26,4 +26,24 @@ constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) {
return static_cast<HaltReason>(hr);
}
#ifdef __linux__
class ScopedJitExecution {
public:
explicit ScopedJitExecution(Kernel::KProcess* process);
~ScopedJitExecution();
static void RegisterHandler();
};
#else
class ScopedJitExecution {
public:
explicit ScopedJitExecution(Kernel::KProcess* process) {}
~ScopedJitExecution() {}
static void RegisterHandler() {}
};
#endif
} // namespace Core

View File

@@ -331,11 +331,15 @@ bool ArmDynarmic32::IsInThumbMode() const {
}
HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Run());
}
HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Step());
}
@@ -377,6 +381,7 @@ ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, Kernel::KProc
m_cp15(std::make_shared<DynarmicCP15>(*this)), m_core_index{core_index} {
auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl();
m_jit = MakeJit(&page_table_impl);
ScopedJitExecution::RegisterHandler();
}
ArmDynarmic32::~ArmDynarmic32() = default;

View File

@@ -362,11 +362,15 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
}
HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Run());
}
HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Step());
}
@@ -406,6 +410,7 @@ ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, Kernel::KProc
auto& page_table = process->GetPageTable().GetBasePageTable();
auto& page_table_impl = page_table.GetImpl();
m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth());
ScopedJitExecution::RegisterHandler();
}
ArmDynarmic64::~ArmDynarmic64() = default;

View File

@@ -29,7 +29,6 @@ std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callbac
struct CoreTiming::Event {
s64 time;
u64 fifo_order;
std::uintptr_t user_data;
std::weak_ptr<EventType> type;
s64 reschedule_time;
heap_t::handle_type handle{};
@@ -67,17 +66,15 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
event_fifo_id = 0;
shutting_down = false;
cpu_ticks = 0;
const auto empty_timed_callback = [](std::uintptr_t, u64, std::chrono::nanoseconds)
-> std::optional<std::chrono::nanoseconds> { return std::nullopt; };
ev_lost = CreateEvent("_lost_event", empty_timed_callback);
if (is_multicore) {
timer_thread = std::make_unique<std::jthread>(ThreadEntry, std::ref(*this));
}
}
void CoreTiming::ClearPendingEvents() {
std::scoped_lock lock{basic_lock};
std::scoped_lock lock{advance_lock, basic_lock};
event_queue.clear();
event.Set();
}
void CoreTiming::Pause(bool is_paused) {
@@ -119,14 +116,12 @@ bool CoreTiming::HasPendingEvents() const {
}
void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
const std::shared_ptr<EventType>& event_type,
std::uintptr_t user_data, bool absolute_time) {
const std::shared_ptr<EventType>& event_type, bool absolute_time) {
{
std::scoped_lock scope{basic_lock};
const auto next_time{absolute_time ? ns_into_future : GetGlobalTimeNs() + ns_into_future};
auto h{event_queue.emplace(
Event{next_time.count(), event_fifo_id++, user_data, event_type, 0})};
auto h{event_queue.emplace(Event{next_time.count(), event_fifo_id++, event_type, 0})};
(*h).handle = h;
}
@@ -136,13 +131,13 @@ void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time,
std::chrono::nanoseconds resched_time,
const std::shared_ptr<EventType>& event_type,
std::uintptr_t user_data, bool absolute_time) {
bool absolute_time) {
{
std::scoped_lock scope{basic_lock};
const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time};
auto h{event_queue.emplace(Event{next_time.count(), event_fifo_id++, user_data, event_type,
resched_time.count()})};
auto h{event_queue.emplace(
Event{next_time.count(), event_fifo_id++, event_type, resched_time.count()})};
(*h).handle = h;
}
@@ -150,14 +145,14 @@ void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time,
}
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
std::uintptr_t user_data, bool wait) {
UnscheduleEventType type) {
{
std::scoped_lock lk{basic_lock};
std::vector<heap_t::handle_type> to_remove;
for (auto itr = event_queue.begin(); itr != event_queue.end(); itr++) {
const Event& e = *itr;
if (e.type.lock().get() == event_type.get() && e.user_data == user_data) {
if (e.type.lock().get() == event_type.get()) {
to_remove.push_back(itr->handle);
}
}
@@ -165,10 +160,12 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
for (auto h : to_remove) {
event_queue.erase(h);
}
event_type->sequence_number++;
}
// Force any in-progress events to finish
if (wait) {
if (type == UnscheduleEventType::Wait) {
std::scoped_lock lk{advance_lock};
}
}
@@ -208,28 +205,31 @@ std::optional<s64> CoreTiming::Advance() {
const Event& evt = event_queue.top();
if (const auto event_type{evt.type.lock()}) {
if (evt.reschedule_time == 0) {
const auto evt_user_data = evt.user_data;
const auto evt_time = evt.time;
const auto evt_time = evt.time;
const auto evt_sequence_num = event_type->sequence_number;
if (evt.reschedule_time == 0) {
event_queue.pop();
basic_lock.unlock();
event_type->callback(
evt_user_data, evt_time,
std::chrono::nanoseconds{GetGlobalTimeNs().count() - evt_time});
evt_time, std::chrono::nanoseconds{GetGlobalTimeNs().count() - evt_time});
basic_lock.lock();
} else {
basic_lock.unlock();
const auto new_schedule_time{event_type->callback(
evt.user_data, evt.time,
std::chrono::nanoseconds{GetGlobalTimeNs().count() - evt.time})};
evt_time, std::chrono::nanoseconds{GetGlobalTimeNs().count() - evt_time})};
basic_lock.lock();
if (evt_sequence_num != event_type->sequence_number) {
// Heap handle is invalidated after external modification.
continue;
}
const auto next_schedule_time{new_schedule_time.has_value()
? new_schedule_time.value().count()
: evt.reschedule_time};
@@ -241,8 +241,8 @@ std::optional<s64> CoreTiming::Advance() {
next_time = pause_end_time + next_schedule_time;
}
event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.user_data,
evt.type, next_schedule_time, evt.handle});
event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.type,
next_schedule_time, evt.handle});
}
}

View File

@@ -22,17 +22,25 @@ namespace Core::Timing {
/// A callback that may be scheduled for a particular core timing event.
using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>(
std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)>;
s64 time, std::chrono::nanoseconds ns_late)>;
/// Contains the characteristics of a particular event.
struct EventType {
explicit EventType(TimedCallback&& callback_, std::string&& name_)
: callback{std::move(callback_)}, name{std::move(name_)} {}
: callback{std::move(callback_)}, name{std::move(name_)}, sequence_number{0} {}
/// The event's callback function.
TimedCallback callback;
/// A pointer to the name of the event.
const std::string name;
/// A monotonic sequence number, incremented when this event is
/// changed externally.
size_t sequence_number;
};
enum class UnscheduleEventType {
Wait,
NoWait,
};
/**
@@ -89,23 +97,17 @@ public:
/// Schedules an event in core timing
void ScheduleEvent(std::chrono::nanoseconds ns_into_future,
const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data = 0,
bool absolute_time = false);
const std::shared_ptr<EventType>& event_type, bool absolute_time = false);
/// Schedules an event which will automatically re-schedule itself with the given time, until
/// unscheduled
void ScheduleLoopingEvent(std::chrono::nanoseconds start_time,
std::chrono::nanoseconds resched_time,
const std::shared_ptr<EventType>& event_type,
std::uintptr_t user_data = 0, bool absolute_time = false);
bool absolute_time = false);
void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data,
bool wait = true);
void UnscheduleEventWithoutWait(const std::shared_ptr<EventType>& event_type,
std::uintptr_t user_data) {
UnscheduleEvent(event_type, user_data, false);
}
void UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
UnscheduleEventType type = UnscheduleEventType::Wait);
void AddTicks(u64 ticks_to_add);
@@ -158,7 +160,6 @@ private:
heap_t event_queue;
u64 event_fifo_id = 0;
std::shared_ptr<EventType> ev_lost;
Common::Event event{};
Common::Event pause_event{};
mutable std::mutex basic_lock;

View File

@@ -8,19 +8,22 @@
namespace Kernel {
void KAutoObjectWithListContainer::Register(KAutoObjectWithList* obj) {
KScopedLightLock lk(m_lock);
// KScopedInterruptDisable di;
KScopedSpinLock lk(m_lock);
m_object_list.insert_unique(*obj);
}
void KAutoObjectWithListContainer::Unregister(KAutoObjectWithList* obj) {
KScopedLightLock lk(m_lock);
// KScopedInterruptDisable di;
KScopedSpinLock lk(m_lock);
m_object_list.erase(*obj);
}
size_t KAutoObjectWithListContainer::GetOwnedCount(KProcess* owner) {
KScopedLightLock lk(m_lock);
// KScopedInterruptDisable di;
KScopedSpinLock lk(m_lock);
return std::count_if(m_object_list.begin(), m_object_list.end(),
[&](const auto& obj) { return obj.GetOwner() == owner; });

View File

@@ -7,7 +7,7 @@
#include "common/common_funcs.h"
#include "core/hle/kernel/k_auto_object.h"
#include "core/hle/kernel/k_light_lock.h"
#include "core/hle/kernel/k_spin_lock.h"
namespace Kernel {
@@ -21,32 +21,7 @@ public:
using ListType = boost::intrusive::rbtree<KAutoObjectWithList>;
class ListAccessor : public KScopedLightLock {
public:
explicit ListAccessor(KAutoObjectWithListContainer* container)
: KScopedLightLock(container->m_lock), m_list(container->m_object_list) {}
explicit ListAccessor(KAutoObjectWithListContainer& container)
: KScopedLightLock(container.m_lock), m_list(container.m_object_list) {}
typename ListType::iterator begin() const {
return m_list.begin();
}
typename ListType::iterator end() const {
return m_list.end();
}
typename ListType::iterator find(typename ListType::const_reference ref) const {
return m_list.find(ref);
}
private:
ListType& m_list;
};
friend class ListAccessor;
KAutoObjectWithListContainer(KernelCore& kernel) : m_lock(kernel), m_object_list() {}
KAutoObjectWithListContainer(KernelCore& kernel) : m_lock(), m_object_list() {}
void Initialize() {}
void Finalize() {}
@@ -56,7 +31,7 @@ public:
size_t GetOwnedCount(KProcess* owner);
private:
KLightLock m_lock;
KSpinLock m_lock;
ListType m_object_list;
};

View File

@@ -30,7 +30,7 @@ public:
public:
explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {}
Result Initialize(KProcess* owner, s32 size) {
Result Initialize(s32 size) {
// Check that the table size is valid.
R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory);
@@ -44,7 +44,6 @@ public:
m_next_linear_id = MinLinearId;
m_count = 0;
m_free_head_index = -1;
m_owner = owner;
// Free all entries.
for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) {
@@ -91,8 +90,7 @@ public:
// Handle pseudo-handles.
if constexpr (std::derived_from<KProcess, T>) {
if (handle == Svc::PseudoHandle::CurrentProcess) {
// TODO: this should be the current process
auto* const cur_process = m_owner;
auto* const cur_process = GetCurrentProcessPointer(m_kernel);
ASSERT(cur_process != nullptr);
return cur_process;
}
@@ -302,7 +300,6 @@ private:
private:
KernelCore& m_kernel;
KProcess* m_owner{};
std::array<EntryInfo, MaxTableSize> m_entry_infos{};
std::array<KAutoObject*, MaxTableSize> m_objects{};
mutable KSpinLock m_lock;

View File

@@ -10,15 +10,15 @@ namespace Kernel {
void KHardwareTimer::Initialize() {
// Create the timing callback to register with CoreTiming.
m_event_type = Core::Timing::CreateEvent(
"KHardwareTimer::Callback", [](std::uintptr_t timer_handle, s64, std::chrono::nanoseconds) {
reinterpret_cast<KHardwareTimer*>(timer_handle)->DoTask();
return std::nullopt;
});
m_event_type = Core::Timing::CreateEvent("KHardwareTimer::Callback",
[this](s64, std::chrono::nanoseconds) {
this->DoTask();
return std::nullopt;
});
}
void KHardwareTimer::Finalize() {
m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this));
m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type);
m_wakeup_time = std::numeric_limits<s64>::max();
m_event_type.reset();
}
@@ -57,13 +57,12 @@ void KHardwareTimer::EnableInterrupt(s64 wakeup_time) {
m_wakeup_time = wakeup_time;
m_kernel.System().CoreTiming().ScheduleEvent(std::chrono::nanoseconds{m_wakeup_time},
m_event_type, reinterpret_cast<uintptr_t>(this),
true);
m_event_type, true);
}
void KHardwareTimer::DisableInterrupt() {
m_kernel.System().CoreTiming().UnscheduleEventWithoutWait(m_event_type,
reinterpret_cast<uintptr_t>(this));
m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type,
Core::Timing::UnscheduleEventType::NoWait);
m_wakeup_time = std::numeric_limits<s64>::max();
}

View File

@@ -434,7 +434,7 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool
void KPageTableBase::Finalize() {
auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) {
if (Settings::IsFastmemEnabled()) {
m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size);
m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false);
}
};
@@ -5243,7 +5243,7 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) {
// Unmap.
R_ASSERT(this->Operate(updater.GetPageList(), cur_address,
cur_pages, 0, false, unmap_properties,
OperationType::Unmap, true));
OperationType::UnmapPhysical, true));
}
// Check if we're done.
@@ -5326,7 +5326,7 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) {
// Map the papges.
R_TRY(this->Operate(updater.GetPageList(), cur_address, map_pages,
cur_pg, map_properties,
OperationType::MapFirstGroup, false));
OperationType::MapFirstGroupPhysical, false));
}
}
@@ -5480,7 +5480,7 @@ Result KPageTableBase::UnmapPhysicalMemory(KProcessAddress address, size_t size)
// Unmap.
R_ASSERT(this->Operate(updater.GetPageList(), cur_address, cur_pages, 0, false,
unmap_properties, OperationType::Unmap, false));
unmap_properties, OperationType::UnmapPhysical, false));
}
// Check if we're done.
@@ -5655,7 +5655,10 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
// or free them to the page list, and so it goes unused (along with page properties).
switch (operation) {
case OperationType::Unmap: {
case OperationType::Unmap:
case OperationType::UnmapPhysical: {
const bool separate_heap = operation == OperationType::UnmapPhysical;
// Ensure that any pages we track are closed on exit.
KPageGroup pages_to_close(m_kernel, this->GetBlockInfoManager());
SCOPE_EXIT({ pages_to_close.CloseAndReset(); });
@@ -5664,7 +5667,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
this->MakePageGroup(pages_to_close, virt_addr, num_pages);
// Unmap.
m_memory->UnmapRegion(*m_impl, virt_addr, num_pages * PageSize);
m_memory->UnmapRegion(*m_impl, virt_addr, num_pages * PageSize, separate_heap);
R_SUCCEED();
}
@@ -5672,7 +5675,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
ASSERT(virt_addr != 0);
ASSERT(Common::IsAligned(GetInteger(virt_addr), PageSize));
m_memory->MapMemoryRegion(*m_impl, virt_addr, num_pages * PageSize, phys_addr,
ConvertToMemoryPermission(properties.perm));
ConvertToMemoryPermission(properties.perm), false);
// Open references to pages, if we should.
if (this->IsHeapPhysicalAddress(phys_addr)) {
@@ -5711,16 +5714,19 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
switch (operation) {
case OperationType::MapGroup:
case OperationType::MapFirstGroup: {
case OperationType::MapFirstGroup:
case OperationType::MapFirstGroupPhysical: {
const bool separate_heap = operation == OperationType::MapFirstGroupPhysical;
// We want to maintain a new reference to every page in the group.
KScopedPageGroup spg(page_group, operation != OperationType::MapFirstGroup);
KScopedPageGroup spg(page_group, operation == OperationType::MapGroup);
for (const auto& node : page_group) {
const size_t size{node.GetNumPages() * PageSize};
// Map the pages.
m_memory->MapMemoryRegion(*m_impl, virt_addr, size, node.GetAddress(),
ConvertToMemoryPermission(properties.perm));
ConvertToMemoryPermission(properties.perm), separate_heap);
virt_addr += size;
}

View File

@@ -104,6 +104,9 @@ protected:
ChangePermissionsAndRefresh = 5,
ChangePermissionsAndRefreshAndFlush = 6,
Separate = 7,
MapFirstGroupPhysical = 65000,
UnmapPhysical = 65001,
};
static constexpr size_t MaxPhysicalMapAlignment = 1_GiB;

View File

@@ -1237,8 +1237,10 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
auto& buffer = m_kernel.System().DeviceMemory().buffer;
const auto& code = code_set.CodeSegment();
const auto& patch = code_set.PatchSegment();
buffer.Protect(GetInteger(base_addr + code.addr), code.size, true, true, true);
buffer.Protect(GetInteger(base_addr + patch.addr), patch.size, true, true, true);
buffer.Protect(GetInteger(base_addr + code.addr), code.size,
Common::MemoryPermission::Read | Common::MemoryPermission::Execute);
buffer.Protect(GetInteger(base_addr + patch.addr), patch.size,
Common::MemoryPermission::Read | Common::MemoryPermission::Execute);
ReprotectSegment(code_set.PatchSegment(), Svc::MemoryPermission::None);
}
#endif

View File

@@ -552,7 +552,7 @@ private:
Result InitializeHandleTable(s32 size) {
// Try to initialize the handle table.
R_TRY(m_handle_table.Initialize(this, size));
R_TRY(m_handle_table.Initialize(size));
// We succeeded, so note that we did.
m_is_handle_table_initialized = true;

View File

@@ -1147,8 +1147,7 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server
*out_context =
std::make_shared<Service::HLERequestContext>(m_kernel, memory, this, client_thread);
(*out_context)->SetSessionRequestManager(manager);
(*out_context)
->PopulateFromIncomingCommandBuffer(*client_thread->GetOwnerProcess(), cmd_buf);
(*out_context)->PopulateFromIncomingCommandBuffer(cmd_buf);
// We succeeded.
R_SUCCEED();
} else {

View File

@@ -5,6 +5,7 @@
#include <optional>
#include "core/hle/kernel/k_light_lock.h"
#include "core/hle/kernel/k_page_group.h"
#include "core/hle/kernel/slab_helpers.h"
#include "core/hle/kernel/svc_types.h"

View File

@@ -238,7 +238,7 @@ struct KernelCore::Impl {
void InitializePreemption(KernelCore& kernel) {
preemption_event = Core::Timing::CreateEvent(
"PreemptionCallback",
[this, &kernel](std::uintptr_t, s64 time,
[this, &kernel](s64 time,
std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
{
KScopedSchedulerLock lock(kernel);

View File

@@ -1513,8 +1513,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx)
return;
}
auto transfer_mem =
system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
if (transfer_mem.IsNull()) {
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
@@ -1524,8 +1523,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx)
}
std::vector<u8> memory(transfer_mem->GetSize());
system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(),
memory.size());
ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
@@ -1547,8 +1545,7 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
return;
}
auto transfer_mem =
system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
if (transfer_mem.IsNull()) {
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
@@ -1558,8 +1555,7 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
}
std::vector<u8> memory(transfer_mem->GetSize());
system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(),
memory.size());
ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);

View File

@@ -454,10 +454,8 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
return;
}
const auto& handle_table{system.ApplicationProcess()->GetHandleTable()};
auto process{handle_table.GetObject<Kernel::KProcess>(process_handle)};
auto transfer_memory{
process->GetHandleTable().GetObject<Kernel::KTransferMemory>(transfer_memory_handle)};
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle)};
auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
const auto session_id{impl->GetSessionId()};
if (session_id == -1) {

View File

@@ -278,9 +278,7 @@ void HwOpus::OpenHardwareOpusDecoder(HLERequestContext& ctx) {
auto params = rp.PopRaw<OpusParameters>();
auto transfer_memory_size{rp.Pop<u32>()};
auto transfer_memory_handle{ctx.GetCopyHandle(0)};
auto transfer_memory{
system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
transfer_memory_handle)};
auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}",
params.sample_rate, params.channel_count, transfer_memory_size);
@@ -323,9 +321,7 @@ void HwOpus::OpenHardwareOpusDecoderForMultiStream(HLERequestContext& ctx) {
auto transfer_memory_size{rp.Pop<u32>()};
auto transfer_memory_handle{ctx.GetCopyHandle(0)};
auto transfer_memory{
system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
transfer_memory_handle)};
auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
LOG_DEBUG(Service_Audio,
"sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
@@ -374,9 +370,7 @@ void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) {
auto params = rp.PopRaw<OpusParametersEx>();
auto transfer_memory_size{rp.Pop<u32>()};
auto transfer_memory_handle{ctx.GetCopyHandle(0)};
auto transfer_memory{
system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
transfer_memory_handle)};
auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}",
params.sample_rate, params.channel_count, transfer_memory_size);
@@ -414,9 +408,7 @@ void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) {
auto transfer_memory_size{rp.Pop<u32>()};
auto transfer_memory_handle{ctx.GetCopyHandle(0)};
auto transfer_memory{
system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
transfer_memory_handle)};
auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
LOG_DEBUG(Service_Audio,
"sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "

View File

@@ -1850,8 +1850,7 @@ void IHidServer::InitializeSevenSixAxisSensor(HLERequestContext& ctx) {
ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes");
ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes");
auto t_mem_1 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
t_mem_1_handle);
auto t_mem_1 = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_1_handle);
if (t_mem_1.IsNull()) {
LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle);
@@ -1860,8 +1859,7 @@ void IHidServer::InitializeSevenSixAxisSensor(HLERequestContext& ctx) {
return;
}
auto t_mem_2 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
t_mem_2_handle);
auto t_mem_2 = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_2_handle);
if (t_mem_2.IsNull()) {
LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle);
@@ -2142,8 +2140,7 @@ void IHidServer::WritePalmaWaveEntry(HLERequestContext& ctx) {
ASSERT_MSG(t_mem_size == 0x3000, "t_mem_size is not 0x3000 bytes");
auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
t_mem_handle);
auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle);
if (t_mem.IsNull()) {
LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);

View File

@@ -49,10 +49,10 @@ HidBus::HidBus(Core::System& system_)
// Register update callbacks
hidbus_update_event = Core::Timing::CreateEvent(
"Hidbus::UpdateCallback",
[this](std::uintptr_t user_data, s64 time,
[this](s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
const auto guard = LockService();
UpdateHidbus(user_data, ns_late);
UpdateHidbus(ns_late);
return std::nullopt;
});
@@ -61,10 +61,10 @@ HidBus::HidBus(Core::System& system_)
}
HidBus::~HidBus() {
system.CoreTiming().UnscheduleEvent(hidbus_update_event, 0);
system.CoreTiming().UnscheduleEvent(hidbus_update_event);
}
void HidBus::UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) {
if (is_hidbus_enabled) {
for (std::size_t i = 0; i < devices.size(); ++i) {
if (!devices[i].is_device_initializated) {
@@ -448,8 +448,7 @@ void HidBus::EnableJoyPollingReceiveMode(HLERequestContext& ctx) {
ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes");
auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
t_mem_handle);
auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle);
if (t_mem.IsNull()) {
LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);

View File

@@ -108,7 +108,7 @@ private:
void DisableJoyPollingReceiveMode(HLERequestContext& ctx);
void SetStatusManagerType(HLERequestContext& ctx);
void UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateHidbus(std::chrono::nanoseconds ns_late);
std::optional<std::size_t> GetDeviceIndexFromHandle(BusHandle handle) const;
template <typename T>

View File

@@ -197,8 +197,7 @@ void IRS::RunImageTransferProcessor(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
const auto t_mem_handle{ctx.GetCopyHandle(0)};
auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
t_mem_handle);
auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle);
if (t_mem.IsNull()) {
LOG_ERROR(Service_IRS, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);
@@ -444,8 +443,7 @@ void IRS::RunImageTransferExProcessor(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
const auto t_mem_handle{ctx.GetCopyHandle(0)};
auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
t_mem_handle);
auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle);
LOG_INFO(Service_IRS,
"called, npad_type={}, npad_id={}, transfer_memory_size={}, "

View File

@@ -227,8 +227,7 @@ void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) {
applet_resource->EnableTouchScreen(aruid, is_enabled);
}
void ResourceManager::UpdateControllers(std::uintptr_t user_data,
std::chrono::nanoseconds ns_late) {
void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
debug_pad->OnUpdate(core_timing);
digitizer->OnUpdate(core_timing);
@@ -241,20 +240,19 @@ void ResourceManager::UpdateControllers(std::uintptr_t user_data,
capture_button->OnUpdate(core_timing);
}
void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
void ResourceManager::UpdateNpad(std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
npad->OnUpdate(core_timing);
}
void ResourceManager::UpdateMouseKeyboard(std::uintptr_t user_data,
std::chrono::nanoseconds ns_late) {
void ResourceManager::UpdateMouseKeyboard(std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
mouse->OnUpdate(core_timing);
debug_mouse->OnUpdate(core_timing);
keyboard->OnUpdate(core_timing);
}
void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
void ResourceManager::UpdateMotion(std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
six_axis->OnUpdate(core_timing);
seven_six_axis->OnUpdate(core_timing);
@@ -273,34 +271,34 @@ IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<Resource
// Register update callbacks
npad_update_event = Core::Timing::CreateEvent(
"HID::UpdatePadCallback",
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
-> std::optional<std::chrono::nanoseconds> {
[this, resource](
s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
const auto guard = LockService();
resource->UpdateNpad(user_data, ns_late);
resource->UpdateNpad(ns_late);
return std::nullopt;
});
default_update_event = Core::Timing::CreateEvent(
"HID::UpdateDefaultCallback",
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
-> std::optional<std::chrono::nanoseconds> {
[this, resource](
s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
const auto guard = LockService();
resource->UpdateControllers(user_data, ns_late);
resource->UpdateControllers(ns_late);
return std::nullopt;
});
mouse_keyboard_update_event = Core::Timing::CreateEvent(
"HID::UpdateMouseKeyboardCallback",
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
-> std::optional<std::chrono::nanoseconds> {
[this, resource](
s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
const auto guard = LockService();
resource->UpdateMouseKeyboard(user_data, ns_late);
resource->UpdateMouseKeyboard(ns_late);
return std::nullopt;
});
motion_update_event = Core::Timing::CreateEvent(
"HID::UpdateMotionCallback",
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
-> std::optional<std::chrono::nanoseconds> {
[this, resource](
s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
const auto guard = LockService();
resource->UpdateMotion(user_data, ns_late);
resource->UpdateMotion(ns_late);
return std::nullopt;
});
@@ -314,10 +312,10 @@ IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<Resource
}
IAppletResource::~IAppletResource() {
system.CoreTiming().UnscheduleEvent(npad_update_event, 0);
system.CoreTiming().UnscheduleEvent(default_update_event, 0);
system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
system.CoreTiming().UnscheduleEvent(npad_update_event);
system.CoreTiming().UnscheduleEvent(default_update_event);
system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event);
system.CoreTiming().UnscheduleEvent(motion_update_event);
resource_manager->FreeAppletResourceId(aruid);
}

View File

@@ -81,10 +81,10 @@ public:
void EnablePadInput(u64 aruid, bool is_enabled);
void EnableTouchScreen(u64 aruid, bool is_enabled);
void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateControllers(std::chrono::nanoseconds ns_late);
void UpdateNpad(std::chrono::nanoseconds ns_late);
void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late);
void UpdateMotion(std::chrono::nanoseconds ns_late);
private:
Result CreateAppletResourceImpl(u64 aruid);

View File

@@ -146,10 +146,7 @@ HLERequestContext::HLERequestContext(Kernel::KernelCore& kernel_, Core::Memory::
HLERequestContext::~HLERequestContext() = default;
void HLERequestContext::ParseCommandBuffer(Kernel::KProcess& process, u32_le* src_cmdbuf,
bool incoming) {
client_handle_table = &process.GetHandleTable();
void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
IPC::RequestParser rp(src_cmdbuf);
command_header = rp.PopRaw<IPC::CommandHeader>();
@@ -162,7 +159,7 @@ void HLERequestContext::ParseCommandBuffer(Kernel::KProcess& process, u32_le* sr
if (command_header->enable_handle_descriptor) {
handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>();
if (handle_descriptor_header->send_current_pid) {
pid = process.GetProcessId();
pid = thread->GetOwnerProcess()->GetProcessId();
rp.Skip(2, false);
}
if (incoming) {
@@ -270,9 +267,10 @@ void HLERequestContext::ParseCommandBuffer(Kernel::KProcess& process, u32_le* sr
rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
}
Result HLERequestContext::PopulateFromIncomingCommandBuffer(Kernel::KProcess& process,
u32_le* src_cmdbuf) {
ParseCommandBuffer(process, src_cmdbuf, true);
Result HLERequestContext::PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf) {
client_handle_table = &thread->GetOwnerProcess()->GetHandleTable();
ParseCommandBuffer(src_cmdbuf, true);
if (command_header->IsCloseCommand()) {
// Close does not populate the rest of the IPC header
@@ -284,9 +282,9 @@ Result HLERequestContext::PopulateFromIncomingCommandBuffer(Kernel::KProcess& pr
return ResultSuccess;
}
Result HLERequestContext::WriteToOutgoingCommandBuffer(Kernel::KThread& requesting_thread) {
Result HLERequestContext::WriteToOutgoingCommandBuffer() {
auto current_offset = handles_offset;
auto& owner_process = *requesting_thread.GetOwnerProcess();
auto& owner_process = *thread->GetOwnerProcess();
auto& handle_table = owner_process.GetHandleTable();
for (auto& object : outgoing_copy_objects) {
@@ -319,7 +317,7 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(Kernel::KThread& requesti
}
// Copy the translated command buffer back into the thread's command buffer area.
memory.WriteBlock(requesting_thread.GetTlsAddress(), cmd_buf.data(), write_size * sizeof(u32));
memory.WriteBlock(thread->GetTlsAddress(), cmd_buf.data(), write_size * sizeof(u32));
return ResultSuccess;
}

View File

@@ -17,6 +17,7 @@
#include "common/concepts.h"
#include "common/swap.h"
#include "core/hle/ipc.h"
#include "core/hle/kernel/k_handle_table.h"
#include "core/hle/kernel/svc_common.h"
union Result;
@@ -196,10 +197,10 @@ public:
}
/// Populates this context with data from the requesting process/thread.
Result PopulateFromIncomingCommandBuffer(Kernel::KProcess& process, u32_le* src_cmdbuf);
Result PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf);
/// Writes data from this context back to the requesting process/thread.
Result WriteToOutgoingCommandBuffer(Kernel::KThread& requesting_thread);
Result WriteToOutgoingCommandBuffer();
[[nodiscard]] u32_le GetHipcCommand() const {
return command;
@@ -359,8 +360,17 @@ public:
return *thread;
}
Kernel::KHandleTable& GetClientHandleTable() {
return *client_handle_table;
[[nodiscard]] Core::Memory::Memory& GetMemory() const {
return memory;
}
template <typename T>
Kernel::KScopedAutoObject<T> GetObjectFromHandle(u32 handle) {
auto obj = client_handle_table->GetObjectForIpc(handle, thread);
if (obj.IsNotNull()) {
return obj->DynamicCast<T*>();
}
return nullptr;
}
[[nodiscard]] std::shared_ptr<SessionRequestManager> GetManager() const {
@@ -378,7 +388,7 @@ public:
private:
friend class IPC::ResponseBuilder;
void ParseCommandBuffer(Kernel::KProcess& process, u32_le* src_cmdbuf, bool incoming);
void ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming);
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
Kernel::KServerSession* server_session{};

View File

@@ -26,7 +26,7 @@ public:
explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx,
CodeRange user_ro)
: ServiceFramework{system_, "IJitEnvironment"}, process{&process_},
context{system_.ApplicationMemory()} {
context{process->GetMemory()} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IJitEnvironment::GenerateCode, "GenerateCode"},
@@ -188,7 +188,7 @@ public:
return;
}
auto tmem{process->GetHandleTable().GetObject<Kernel::KTransferMemory>(tmem_handle)};
auto tmem{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(tmem_handle)};
if (tmem.IsNull()) {
LOG_ERROR(Service_JIT, "attempted to load plugin with invalid transfer memory handle");
IPC::ResponseBuilder rb{ctx, 2};
@@ -356,11 +356,7 @@ public:
return;
}
// Fetch using the handle table for the application process here,
// since we are not multiprocess yet.
const auto& handle_table{system.ApplicationProcess()->GetHandleTable()};
auto process{handle_table.GetObject<Kernel::KProcess>(process_handle)};
auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle)};
if (process.IsNull()) {
LOG_ERROR(Service_JIT, "process is null for handle=0x{:08X}", process_handle);
IPC::ResponseBuilder rb{ctx, 2};
@@ -368,7 +364,7 @@ public:
return;
}
auto rx_mem{handle_table.GetObject<Kernel::KCodeMemory>(rx_mem_handle)};
auto rx_mem{ctx.GetObjectFromHandle<Kernel::KCodeMemory>(rx_mem_handle)};
if (rx_mem.IsNull()) {
LOG_ERROR(Service_JIT, "rx_mem is null for handle=0x{:08X}", rx_mem_handle);
IPC::ResponseBuilder rb{ctx, 2};
@@ -376,7 +372,7 @@ public:
return;
}
auto ro_mem{handle_table.GetObject<Kernel::KCodeMemory>(ro_mem_handle)};
auto ro_mem{ctx.GetObjectFromHandle<Kernel::KCodeMemory>(ro_mem_handle)};
if (ro_mem.IsNull()) {
LOG_ERROR(Service_JIT, "ro_mem is null for handle=0x{:08X}", ro_mem_handle);
IPC::ResponseBuilder rb{ctx, 2};

View File

@@ -67,7 +67,7 @@ Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_
// Schedule the screen composition events
multi_composition_event = Core::Timing::CreateEvent(
"ScreenComposition",
[this](std::uintptr_t, s64 time,
[this](s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
vsync_signal.Set();
return std::chrono::nanoseconds(GetNextTicks());
@@ -75,7 +75,7 @@ Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_
single_composition_event = Core::Timing::CreateEvent(
"ScreenComposition",
[this](std::uintptr_t, s64 time,
[this](s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
const auto lock_guard = Lock();
Compose();
@@ -93,11 +93,11 @@ Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_
Nvnflinger::~Nvnflinger() {
if (system.IsMulticore()) {
system.CoreTiming().UnscheduleEvent(multi_composition_event, {});
system.CoreTiming().UnscheduleEvent(multi_composition_event);
vsync_thread.request_stop();
vsync_signal.Set();
} else {
system.CoreTiming().UnscheduleEvent(single_composition_event, {});
system.CoreTiming().UnscheduleEvent(single_composition_event);
}
ShutdownLayers();

View File

@@ -651,10 +651,9 @@ private:
void RegisterProcessHandle(HLERequestContext& ctx) {
LOG_DEBUG(Service_LDR, "(called)");
auto process_h = ctx.GetClientHandleTable().GetObject(ctx.GetCopyHandle(0));
auto process = ctx.GetObjectFromHandle<Kernel::KProcess>(ctx.GetCopyHandle(0));
auto client_pid = ctx.GetPID();
auto result = interface.RegisterProcessHandle(client_pid,
process_h->DynamicCast<Kernel::KProcess*>());
auto result = interface.RegisterProcessHandle(client_pid, process.GetPointerUnsafe());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -671,12 +670,11 @@ private:
IPC::RequestParser rp{ctx};
auto params = rp.PopRaw<InputParameters>();
auto process_h = ctx.GetClientHandleTable().GetObject(ctx.GetCopyHandle(0));
auto process = ctx.GetObjectFromHandle<Kernel::KProcess>(ctx.GetCopyHandle(0));
auto client_pid = ctx.GetPID();
auto result =
interface.RegisterProcessModuleInfo(client_pid, params.nrr_address, params.nrr_size,
process_h->DynamicCast<Kernel::KProcess*>());
auto result = interface.RegisterProcessModuleInfo(
client_pid, params.nrr_address, params.nrr_size, process.GetPointerUnsafe());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);

View File

@@ -203,7 +203,7 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session,
// If emulation was shutdown, we are closing service threads, do not write the response back to
// memory that may be shutting down as well.
if (system.IsPoweredOn()) {
ctx.WriteToOutgoingCommandBuffer(ctx.GetThread());
ctx.WriteToOutgoingCommandBuffer();
}
return result;

View File

@@ -10,6 +10,7 @@
#include "common/assert.h"
#include "common/atomic_ops.h"
#include "common/common_types.h"
#include "common/heap_tracker.h"
#include "common/logging/log.h"
#include "common/page_table.h"
#include "common/scope_exit.h"
@@ -52,10 +53,18 @@ struct Memory::Impl {
} else {
current_page_table->fastmem_arena = nullptr;
}
#ifdef __linux__
heap_tracker.emplace(system.DeviceMemory().buffer);
buffer = std::addressof(*heap_tracker);
#else
buffer = std::addressof(system.DeviceMemory().buffer);
#endif
}
void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
Common::PhysicalAddress target, Common::MemoryPermission perms) {
Common::PhysicalAddress target, Common::MemoryPermission perms,
bool separate_heap) {
ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size);
ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base));
ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}",
@@ -64,19 +73,20 @@ struct Memory::Impl {
Common::PageType::Memory);
if (current_page_table->fastmem_arena) {
system.DeviceMemory().buffer.Map(GetInteger(base),
GetInteger(target) - DramMemoryMap::Base, size, perms);
buffer->Map(GetInteger(base), GetInteger(target) - DramMemoryMap::Base, size, perms,
separate_heap);
}
}
void UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) {
void UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
bool separate_heap) {
ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size);
ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base));
MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, 0,
Common::PageType::Unmapped);
if (current_page_table->fastmem_arena) {
system.DeviceMemory().buffer.Unmap(GetInteger(base), size);
buffer->Unmap(GetInteger(base), size, separate_heap);
}
}
@@ -89,11 +99,6 @@ struct Memory::Impl {
return;
}
const bool is_r = True(perms & Common::MemoryPermission::Read);
const bool is_w = True(perms & Common::MemoryPermission::Write);
const bool is_x =
True(perms & Common::MemoryPermission::Execute) && Settings::IsNceEnabled();
u64 protect_bytes{};
u64 protect_begin{};
for (u64 addr = vaddr; addr < vaddr + size; addr += YUZU_PAGESIZE) {
@@ -102,8 +107,7 @@ struct Memory::Impl {
switch (page_type) {
case Common::PageType::RasterizerCachedMemory:
if (protect_bytes > 0) {
system.DeviceMemory().buffer.Protect(protect_begin, protect_bytes, is_r, is_w,
is_x);
buffer->Protect(protect_begin, protect_bytes, perms);
protect_bytes = 0;
}
break;
@@ -116,7 +120,7 @@ struct Memory::Impl {
}
if (protect_bytes > 0) {
system.DeviceMemory().buffer.Protect(protect_begin, protect_bytes, is_r, is_w, is_x);
buffer->Protect(protect_begin, protect_bytes, perms);
}
}
@@ -486,7 +490,9 @@ struct Memory::Impl {
}
if (current_page_table->fastmem_arena) {
system.DeviceMemory().buffer.Protect(vaddr, size, !debug, !debug);
const auto perm{debug ? Common::MemoryPermission{}
: Common::MemoryPermission::ReadWrite};
buffer->Protect(vaddr, size, perm);
}
// Iterate over a contiguous CPU address space, marking/unmarking the region.
@@ -543,9 +549,14 @@ struct Memory::Impl {
}
if (current_page_table->fastmem_arena) {
const bool is_read_enable =
!Settings::values.use_reactive_flushing.GetValue() || !cached;
system.DeviceMemory().buffer.Protect(vaddr, size, is_read_enable, !cached);
Common::MemoryPermission perm{};
if (!Settings::values.use_reactive_flushing.GetValue() || !cached) {
perm |= Common::MemoryPermission::Read;
}
if (!cached) {
perm |= Common::MemoryPermission::Write;
}
buffer->Protect(vaddr, size, perm);
}
// Iterate over a contiguous CPU address space, which corresponds to the specified GPU
@@ -856,6 +867,13 @@ struct Memory::Impl {
std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{};
std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
std::mutex sys_core_guard;
std::optional<Common::HeapTracker> heap_tracker;
#ifdef __linux__
Common::HeapTracker* buffer{};
#else
Common::HostMemory* buffer{};
#endif
};
Memory::Memory(Core::System& system_) : system{system_} {
@@ -873,12 +891,14 @@ void Memory::SetCurrentPageTable(Kernel::KProcess& process) {
}
void Memory::MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
Common::PhysicalAddress target, Common::MemoryPermission perms) {
impl->MapMemoryRegion(page_table, base, size, target, perms);
Common::PhysicalAddress target, Common::MemoryPermission perms,
bool separate_heap) {
impl->MapMemoryRegion(page_table, base, size, target, perms, separate_heap);
}
void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) {
impl->UnmapRegion(page_table, base, size);
void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
bool separate_heap) {
impl->UnmapRegion(page_table, base, size, separate_heap);
}
void Memory::ProtectRegion(Common::PageTable& page_table, Common::ProcessAddress vaddr, u64 size,
@@ -1048,7 +1068,9 @@ void Memory::FlushRegion(Common::ProcessAddress dest_addr, size_t size) {
}
bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
bool mapped = true;
[[maybe_unused]] bool mapped = true;
[[maybe_unused]] bool rasterizer = false;
u8* const ptr = impl->GetPointerImpl(
GetInteger(vaddr),
[&] {
@@ -1056,8 +1078,26 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
GetInteger(vaddr));
mapped = false;
},
[&] { impl->system.GPU().InvalidateRegion(GetInteger(vaddr), size); });
[&] {
impl->system.GPU().InvalidateRegion(GetInteger(vaddr), size);
rasterizer = true;
});
#ifdef __linux__
if (!rasterizer && mapped) {
impl->buffer->DeferredMapSeparateHeap(GetInteger(vaddr));
}
#endif
return mapped && ptr != nullptr;
}
bool Memory::InvalidateSeparateHeap(void* fault_address) {
#ifdef __linux__
return impl->buffer->DeferredMapSeparateHeap(static_cast<u8*>(fault_address));
#else
return false;
#endif
}
} // namespace Core::Memory

View File

@@ -86,7 +86,8 @@ public:
* @param perms The permissions to map the memory with.
*/
void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
Common::PhysicalAddress target, Common::MemoryPermission perms);
Common::PhysicalAddress target, Common::MemoryPermission perms,
bool separate_heap);
/**
* Unmaps a region of the emulated process address space.
@@ -95,7 +96,8 @@ public:
* @param base The address to begin unmapping at.
* @param size The amount of bytes to unmap.
*/
void UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size);
void UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
bool separate_heap);
/**
* Protects a region of the emulated process address space with the new permissions.
@@ -486,6 +488,7 @@ public:
void SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers);
void InvalidateRegion(Common::ProcessAddress dest_addr, size_t size);
bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size);
bool InvalidateSeparateHeap(void* fault_address);
void FlushRegion(Common::ProcessAddress dest_addr, size_t size);
private:

View File

@@ -190,15 +190,15 @@ CheatEngine::CheatEngine(System& system_, std::vector<CheatEntry> cheats_,
}
CheatEngine::~CheatEngine() {
core_timing.UnscheduleEvent(event, 0);
core_timing.UnscheduleEvent(event);
}
void CheatEngine::Initialize() {
event = Core::Timing::CreateEvent(
"CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
[this](std::uintptr_t user_data, s64 time,
[this](s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
FrameCallback(user_data, ns_late);
FrameCallback(ns_late);
return std::nullopt;
});
core_timing.ScheduleLoopingEvent(CHEAT_ENGINE_NS, CHEAT_ENGINE_NS, event);
@@ -239,7 +239,7 @@ void CheatEngine::Reload(std::vector<CheatEntry> reload_cheats) {
MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70));
void CheatEngine::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) {
void CheatEngine::FrameCallback(std::chrono::nanoseconds ns_late) {
if (is_pending_reload.exchange(false)) {
vm.LoadProgram(cheats);
}

View File

@@ -70,7 +70,7 @@ public:
void Reload(std::vector<CheatEntry> reload_cheats);
private:
void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void FrameCallback(std::chrono::nanoseconds ns_late);
DmntCheatVm vm;
CheatProcessMetadata metadata;

View File

@@ -51,18 +51,17 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v
Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
: core_timing{core_timing_}, memory{memory_} {
event = Core::Timing::CreateEvent(
"MemoryFreezer::FrameCallback",
[this](std::uintptr_t user_data, s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
FrameCallback(user_data, ns_late);
return std::nullopt;
});
event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback",
[this](s64 time, std::chrono::nanoseconds ns_late)
-> std::optional<std::chrono::nanoseconds> {
FrameCallback(ns_late);
return std::nullopt;
});
core_timing.ScheduleEvent(memory_freezer_ns, event);
}
Freezer::~Freezer() {
core_timing.UnscheduleEvent(event, 0);
core_timing.UnscheduleEvent(event);
}
void Freezer::SetActive(bool is_active) {
@@ -159,7 +158,7 @@ Freezer::Entries::const_iterator Freezer::FindEntry(VAddr address) const {
[address](const Entry& entry) { return entry.address == address; });
}
void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) {
void Freezer::FrameCallback(std::chrono::nanoseconds ns_late) {
if (!IsActive()) {
LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events.");
return;

View File

@@ -77,7 +77,7 @@ private:
Entries::iterator FindEntry(VAddr address);
Entries::const_iterator FindEntry(VAddr address) const;
void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void FrameCallback(std::chrono::nanoseconds ns_late);
void FillEntryReads();
std::atomic_bool active{false};