Files
dolphin/Source/UnitTests/Core/PageFaultTest.cpp
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

108 lines
3.2 KiB
C++
Raw Normal View History

2015-05-24 06:32:32 +02:00
// Copyright 2014 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
2015-05-24 06:32:32 +02:00
2014-10-19 20:31:15 -04:00
#include <chrono>
2022-06-13 17:20:13 -07:00
#include <fmt/format.h>
2014-10-19 20:31:15 -04:00
#include "Common/CommonTypes.h"
#include "Common/ScopeGuard.h"
2014-10-19 20:31:15 -04:00
#include "Common/Timer.h"
#include "Core/Core.h"
2014-10-19 20:31:15 -04:00
#include "Core/MemTools.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
2018-12-02 14:16:17 +01:00
#include "Core/PowerPC/JitInterface.h"
#include "Core/System.h"
2014-10-19 20:31:15 -04:00
// include order is important
#include <gtest/gtest.h> // NOLINT
2014-10-19 20:31:15 -04:00
enum
{
#ifdef _WIN32
PAGE_GRAN = 0x10000
#else
PAGE_GRAN = 0x1000
#endif
};
class PageFaultFakeJit : public JitBase
{
public:
explicit PageFaultFakeJit(Core::System& system) : JitBase(system) {}
2014-10-19 20:31:15 -04:00
// CPUCoreBase methods
void Init() override {}
void Shutdown() override {}
void ClearCache() override {}
void Run() override {}
void SingleStep() override {}
const char* GetName() const override { return nullptr; }
2014-10-19 20:31:15 -04:00
// JitBase methods
JitBaseBlockCache* GetBlockCache() override { return nullptr; }
void Jit(u32 em_address) override {}
const CommonAsmRoutinesBase* GetAsmRoutines() override { return nullptr; }
virtual bool HandleFault(uintptr_t access_address, SContext* ctx) override
{
2014-10-19 20:31:15 -04:00
m_pre_unprotect_time = std::chrono::high_resolution_clock::now();
2016-08-07 13:03:07 -04:00
Common::UnWriteProtectMemory(m_data, PAGE_GRAN, /*allowExecute*/ false);
2014-10-19 20:31:15 -04:00
m_post_unprotect_time = std::chrono::high_resolution_clock::now();
return true;
}
2014-10-19 20:31:15 -04:00
void* m_data = nullptr;
2014-10-19 20:31:15 -04:00
std::chrono::time_point<std::chrono::high_resolution_clock> m_pre_unprotect_time,
m_post_unprotect_time;
};
#ifdef _MSC_VER
#define ASAN_DISABLE __declspec(no_sanitize_address)
#else
#define ASAN_DISABLE
#endif
static void ASAN_DISABLE perform_invalid_access(void* data)
{
*(volatile int*)data = 5;
}
2014-10-19 20:31:15 -04:00
TEST(PageFault, PageFault)
{
if (!EMM::IsExceptionHandlerSupported())
GTEST_SKIP() << "Skipping PageFault test because exception handler is unsupported.";
2014-10-19 20:31:15 -04:00
EMM::InstallExceptionHandler();
2016-08-07 13:03:07 -04:00
void* data = Common::AllocateMemoryPages(PAGE_GRAN);
2014-10-19 20:31:15 -04:00
EXPECT_NE(data, nullptr);
2016-08-07 13:03:07 -04:00
Common::WriteProtectMemory(data, PAGE_GRAN, false);
2014-10-19 20:31:15 -04:00
Core::DeclareAsCPUThread();
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
2023-03-25 16:17:46 +01:00
auto& system = Core::System::GetInstance();
auto unique_pfjit = std::make_unique<PageFaultFakeJit>(system);
auto& pfjit = *unique_pfjit;
system.GetJitInterface().SetJit(std::move(unique_pfjit));
2014-10-19 20:31:15 -04:00
pfjit.m_data = data;
auto start = std::chrono::high_resolution_clock::now();
perform_invalid_access(data);
2014-10-19 20:31:15 -04:00
auto end = std::chrono::high_resolution_clock::now();
2022-06-13 17:20:13 -07:00
auto difference_in_nanoseconds = [](auto start, auto end) {
return std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
};
2014-10-19 20:31:15 -04:00
EMM::UninstallExceptionHandler();
2022-06-13 17:20:13 -07:00
fmt::print("page fault timing:\n");
fmt::print("start->HandleFault {} ns\n",
difference_in_nanoseconds(start, pfjit.m_pre_unprotect_time));
fmt::print("UnWriteProtectMemory {} ns\n",
difference_in_nanoseconds(pfjit.m_pre_unprotect_time, pfjit.m_post_unprotect_time));
fmt::print("HandleFault->end {} ns\n",
difference_in_nanoseconds(pfjit.m_post_unprotect_time, end));
fmt::print("total {} ns\n", difference_in_nanoseconds(start, end));
2023-03-25 16:17:46 +01:00
system.GetJitInterface().SetJit(nullptr);
2014-10-19 20:31:15 -04:00
}