Browse Source

[nce] Added "tainted" page fault handling inside dual channel

vkexperiments1
CamilleLaVey 7 days ago
parent
commit
ca42578d4e
  1. 22
      src/core/arm/nce/arm_nce.cpp
  2. 10
      src/core/arm/nce/arm_nce.h

22
src/core/arm/nce/arm_nce.cpp

@ -44,6 +44,7 @@ fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) {
using namespace Common::Literals; using namespace Common::Literals;
constexpr u32 StackSize = 128_KiB; constexpr u32 StackSize = 128_KiB;
constexpr u64 SplitPageAccessWindow = 64; constexpr u64 SplitPageAccessWindow = 64;
constexpr size_t MaxPreciseAccessPages = 256;
[[nodiscard]] constexpr u64 AlignDownPage(u64 addr) { [[nodiscard]] constexpr u64 AlignDownPage(u64 addr) {
return addr & ~u64{Memory::YUZU_PAGEMASK}; return addr & ~u64{Memory::YUZU_PAGEMASK};
@ -191,15 +192,18 @@ bool ArmNce::HandleGuestAccessFault(GuestContext* guest_ctx, void* raw_info, voi
auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext; auto& host_ctx = static_cast<ucontext_t*>(raw_context)->uc_mcontext;
auto* fpctx = GetFloatingPointState(host_ctx); auto* fpctx = GetFloatingPointState(host_ctx);
auto* info = static_cast<siginfo_t*>(raw_info); auto* info = static_cast<siginfo_t*>(raw_info);
auto* parent = guest_ctx->parent;
const u64 fault_addr = reinterpret_cast<u64>(info->si_addr); const u64 fault_addr = reinterpret_cast<u64>(info->si_addr);
const Common::ProcessAddress addr = fault_addr & ~Memory::YUZU_PAGEMASK; const Common::ProcessAddress addr = fault_addr & ~Memory::YUZU_PAGEMASK;
const u64 page_offset = fault_addr & Memory::YUZU_PAGEMASK; const u64 page_offset = fault_addr & Memory::YUZU_PAGEMASK;
auto& memory = guest_ctx->parent->m_running_thread->GetOwnerProcess()->GetMemory();
const bool prefer_precise_channel = ShouldUsePreciseAccessChannel(guest_ctx, fault_addr);
auto& memory = parent->m_running_thread->GetOwnerProcess()->GetMemory();
const bool prefer_precise_channel = ShouldUsePreciseAccessChannel(guest_ctx, fault_addr) ||
parent->IsPreciseAccessPage(fault_addr);
if (prefer_precise_channel) { if (prefer_precise_channel) {
if (auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx, fpctx); next_pc) { if (auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx, fpctx); next_pc) {
parent->MarkPreciseAccessPage(fault_addr);
host_ctx.pc = *next_pc; host_ctx.pc = *next_pc;
return true; return true;
} }
@ -220,6 +224,7 @@ bool ArmNce::HandleGuestAccessFault(GuestContext* guest_ctx, void* raw_info, voi
} }
if (auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx, fpctx); next_pc) { if (auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx, fpctx); next_pc) {
parent->MarkPreciseAccessPage(fault_addr);
host_ctx.pc = *next_pc; host_ctx.pc = *next_pc;
return true; return true;
} }
@ -236,6 +241,19 @@ void ArmNce::HandleHostAccessFault(int sig, void* raw_info, void* raw_context) {
return g_orig_segv_action.sa_sigaction(sig, static_cast<siginfo_t*>(raw_info), raw_context); return g_orig_segv_action.sa_sigaction(sig, static_cast<siginfo_t*>(raw_info), raw_context);
} }
bool ArmNce::IsPreciseAccessPage(u64 addr) const {
const std::scoped_lock lk{m_precise_pages_guard};
return m_precise_pages.contains(AlignDownPage(addr));
}
void ArmNce::MarkPreciseAccessPage(u64 addr) {
const std::scoped_lock lk{m_precise_pages_guard};
if (m_precise_pages.size() >= MaxPreciseAccessPages) {
m_precise_pages.clear();
}
m_precise_pages.insert(AlignDownPage(addr));
}
void ArmNce::LockThread(Kernel::KThread* thread) { void ArmNce::LockThread(Kernel::KThread* thread) {
auto* thread_params = &thread->GetNativeExecutionParameters(); auto* thread_params = &thread->GetNativeExecutionParameters();
LockThreadParameters(thread_params); LockThreadParameters(thread_params);

10
src/core/arm/nce/arm_nce.h

@ -1,9 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include <mutex> #include <mutex>
#include <unordered_set>
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
#include "core/arm/nce/guest_context.h" #include "core/arm/nce/guest_context.h"
@ -77,6 +81,9 @@ private:
static void HandleHostAlignmentFault(int sig, void* info, void* raw_context); static void HandleHostAlignmentFault(int sig, void* info, void* raw_context);
static void HandleHostAccessFault(int sig, void* info, void* raw_context); static void HandleHostAccessFault(int sig, void* info, void* raw_context);
bool IsPreciseAccessPage(u64 addr) const;
void MarkPreciseAccessPage(u64 addr);
public: public:
Core::System& m_system; Core::System& m_system;
@ -88,6 +95,9 @@ public:
GuestContext m_guest_ctx{}; GuestContext m_guest_ctx{};
Kernel::KThread* m_running_thread{}; Kernel::KThread* m_running_thread{};
mutable std::mutex m_precise_pages_guard{};
std::unordered_set<u64> m_precise_pages{};
// Stack for signal processing. // Stack for signal processing.
std::unique_ptr<u8[]> m_stack{}; std::unique_ptr<u8[]> m_stack{};
}; };

Loading…
Cancel
Save