Skip to content

Commit

Permalink
Merge pull request #4075 from Sonicadvance1/move_thunkhandler
Browse files Browse the repository at this point in the history
Thunks: Move to the frontend
  • Loading branch information
lioncash authored Sep 28, 2024
2 parents 5745b41 + 926fa3c commit f640dcc
Show file tree
Hide file tree
Showing 23 changed files with 374 additions and 337 deletions.
1 change: 0 additions & 1 deletion FEXCore/Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ set (SRCS
Interface/Core/X86Tables/VEXTables.cpp
Interface/Core/X86Tables/X87Tables.cpp
Interface/Core/X86Tables/XOPTables.cpp
Interface/HLE/Thunks/Thunks.cpp
Interface/GDBJIT/GDBJIT.cpp
Interface/IR/AOTIR.cpp
Interface/IR/IRDumper.cpp
Expand Down
5 changes: 5 additions & 0 deletions FEXCore/Source/Interface/Context/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <FEXCore/Core/CPUID.h>
#include <FEXCore/Core/HostFeatures.h>
#include <FEXCore/Core/SignalDelegator.h>
#include <FEXCore/Core/Thunks.h>
#include "FEXCore/Debug/InternalThreadState.h"

#include <string.h>
Expand Down Expand Up @@ -48,6 +49,10 @@ void FEXCore::Context::ContextImpl::SetSyscallHandler(FEXCore::HLE::SyscallHandl
SourcecodeResolver = Handler->GetSourcecodeResolver();
}

void FEXCore::Context::ContextImpl::SetThunkHandler(FEXCore::ThunkHandler* Handler) {
ThunkHandler = Handler;
}

FEXCore::CPUID::FunctionResults FEXCore::Context::ContextImpl::RunCPUIDFunction(uint32_t Function, uint32_t Leaf) {
return CPUID.RunFunction(Function, Leaf);
}
Expand Down
23 changes: 7 additions & 16 deletions FEXCore/Source/Interface/Context/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,9 @@ struct CustomIRResult {
void* Creator;
void* Data;

explicit operator bool() const noexcept {
return !lock;
}

CustomIRResult(std::unique_lock<std::shared_mutex>&& lock, void* Creator, void* Data)
CustomIRResult(void* Creator, void* Data)
: Creator(Creator)
, Data(Data)
, lock(std::move(lock)) {}

private:
std::unique_lock<std::shared_mutex> lock;
, Data(Data) {}
};

using BlockDelinkerFunc = void (*)(FEXCore::Core::CpuStateFrame* Frame, FEXCore::Context::ExitFunctionLinkData* Record);
Expand Down Expand Up @@ -155,6 +147,7 @@ class ContextImpl final : public FEXCore::Context::Context {
#endif
void SetSignalDelegator(FEXCore::SignalDelegator* SignalDelegation) override;
void SetSyscallHandler(FEXCore::HLE::SyscallHandler* Handler) override;
void SetThunkHandler(FEXCore::ThunkHandler* Handler) override;

FEXCore::CPUID::FunctionResults RunCPUIDFunction(uint32_t Function, uint32_t Leaf) override;
FEXCore::CPUID::XCRResults RunXCRFunction(uint32_t Function) override;
Expand Down Expand Up @@ -194,9 +187,10 @@ class ContextImpl final : public FEXCore::Context::Context {
bool IsAddressInCodeBuffer(FEXCore::Core::InternalThreadState* Thread, uintptr_t Address) const override;

// returns false if a handler was already registered
CustomIRResult AddCustomIREntrypoint(uintptr_t Entrypoint, CustomIREntrypointHandler Handler, void* Creator = nullptr, void* Data = nullptr);
std::optional<CustomIRResult>
AddCustomIREntrypoint(uintptr_t Entrypoint, CustomIREntrypointHandler Handler, void* Creator = nullptr, void* Data = nullptr);

void AppendThunkDefinitions(std::span<const FEXCore::IR::ThunkDefinition> Definitions) override;
void AddThunkTrampolineIRHandler(uintptr_t Entrypoint, uintptr_t GuestThunkEntrypoint) override;

public:
friend class FEXCore::HLE::SyscallHandler;
Expand Down Expand Up @@ -228,9 +222,6 @@ class ContextImpl final : public FEXCore::Context::Context {
FEX_CONFIG_OPT(SMCChecks, SMCCHECKS);
FEX_CONFIG_OPT(MaxInstPerBlock, MAXINST);
FEX_CONFIG_OPT(RootFSPath, ROOTFS);
FEX_CONFIG_OPT(ThunkHostLibsPath, THUNKHOSTLIBS);
FEX_CONFIG_OPT(ThunkHostLibsPath32, THUNKHOSTLIBS32);
FEX_CONFIG_OPT(ThunkConfigFile, THUNKCONFIG);
FEX_CONFIG_OPT(GlobalJITNaming, GLOBALJITNAMING);
FEX_CONFIG_OPT(LibraryJITNaming, LIBRARYJITNAMING);
FEX_CONFIG_OPT(BlockJITNaming, BLOCKJITNAMING);
Expand All @@ -255,7 +246,7 @@ class ContextImpl final : public FEXCore::Context::Context {
FEXCore::CPUIDEmu CPUID;
FEXCore::HLE::SyscallHandler* SyscallHandler {};
FEXCore::HLE::SourcecodeResolver* SourcecodeResolver {};
fextl::unique_ptr<FEXCore::ThunkHandler> ThunkHandler;
FEXCore::ThunkHandler* ThunkHandler {};
fextl::unique_ptr<FEXCore::CPU::Dispatcher> Dispatcher;

FEXCore::Context::ExitHandler CustomExitHandler;
Expand Down
1 change: 0 additions & 1 deletion FEXCore/Source/Interface/Core/ArchHelpers/Arm64Emitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "FEXCore/Utils/AllocatorHooks.h"
#include "Interface/Core/Dispatcher/Dispatcher.h"
#include "Interface/Context/Context.h"
#include "Interface/HLE/Thunks/Thunks.h"

#include <FEXCore/Core/CoreState.h>
#include <FEXCore/Utils/LogManager.h>
Expand Down
63 changes: 47 additions & 16 deletions FEXCore/Source/Interface/Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ desc: Glues Frontend, OpDispatcher and IR Opts & Compilation, LookupCache, Dispa
#include "Interface/Core/JIT/JITCore.h"
#include "Interface/Core/Dispatcher/Dispatcher.h"
#include "Interface/Core/X86Tables/X86Tables.h"
#include "Interface/HLE/Thunks/Thunks.h"
#include "Interface/IR/IR.h"
#include "Interface/IR/IREmitter.h"
#include "Interface/IR/Passes/RegisterAllocationPass.h"
Expand All @@ -34,6 +33,7 @@ desc: Glues Frontend, OpDispatcher and IR Opts & Compilation, LookupCache, Dispa
#include <FEXCore/Core/Context.h>
#include <FEXCore/Core/CoreState.h>
#include <FEXCore/Core/SignalDelegator.h>
#include <FEXCore/Core/Thunks.h>
#include <FEXCore/Core/X86Enums.h>
#include <FEXCore/Debug/InternalThreadState.h>
#include <FEXCore/HLE/SyscallHandler.h>
Expand Down Expand Up @@ -346,7 +346,6 @@ bool ContextImpl::InitCore() {
SignalDelegation->SetConfig(SignalConfig);

#ifndef _WIN32
ThunkHandler = FEXCore::ThunkHandler::Create();
#elif !defined(_M_ARM64EC)
// WOW64 always needs the interrupt fault check to be enabled.
Config.NeedsPendingInterruptFaultCheck = true;
Expand Down Expand Up @@ -386,9 +385,6 @@ void ContextImpl::ExecuteThread(FEXCore::Core::InternalThreadState* Thread) {

void ContextImpl::InitializeThreadTLSData(FEXCore::Core::InternalThreadState* Thread) {
// Let's do some initial bookkeeping here
if (ThunkHandler) {
ThunkHandler->RegisterTLSState(Thread);
}
#ifndef _WIN32
Alloc::OSAllocator::RegisterTLSData(Thread);
#endif
Expand Down Expand Up @@ -982,7 +978,8 @@ void ContextImpl::ThreadRemoveCodeEntry(FEXCore::Core::InternalThreadState* Thre
Thread->LookupCache->Erase(Thread->CurrentFrame, GuestRIP);
}

CustomIRResult ContextImpl::AddCustomIREntrypoint(uintptr_t Entrypoint, CustomIREntrypointHandler Handler, void* Creator, void* Data) {
std::optional<CustomIRResult>
ContextImpl::AddCustomIREntrypoint(uintptr_t Entrypoint, CustomIREntrypointHandler Handler, void* Creator, void* Data) {
LOGMAN_THROW_A_FMT(Config.Is64BitMode || !(Entrypoint >> 32), "64-bit Entrypoint in 32-bit mode {:x}", Entrypoint);

std::unique_lock lk(CustomIRMutex);
Expand All @@ -992,10 +989,50 @@ CustomIRResult ContextImpl::AddCustomIREntrypoint(uintptr_t Entrypoint, CustomIR

if (!InsertedIterator.second) {
const auto& [fn, Creator, Data] = InsertedIterator.first->second;
return CustomIRResult(std::move(lk), Creator, Data);
} else {
lk.unlock();
return CustomIRResult(std::move(lk), 0, 0);
return CustomIRResult(Creator, Data);
}

return std::nullopt;
}

void ContextImpl::AddThunkTrampolineIRHandler(uintptr_t Entrypoint, uintptr_t GuestThunkEntrypoint) {
LOGMAN_THROW_AA_FMT(Entrypoint, "Tried to link null pointer address to guest function");
LOGMAN_THROW_AA_FMT(GuestThunkEntrypoint, "Tried to link address to null pointer guest function");
if (!Config.Is64BitMode) {
LOGMAN_THROW_AA_FMT((Entrypoint >> 32) == 0, "Tried to link 64-bit address in 32-bit mode");
LOGMAN_THROW_AA_FMT((GuestThunkEntrypoint >> 32) == 0, "Tried to link 64-bit address in 32-bit mode");
}

LogMan::Msg::DFmt("Thunks: Adding guest trampoline from address {:#x} to guest function {:#x}", Entrypoint, GuestThunkEntrypoint);

auto Result = AddCustomIREntrypoint(
Entrypoint,
[this, GuestThunkEntrypoint](uintptr_t Entrypoint, FEXCore::IR::IREmitter* emit) {
auto IRHeader = emit->_IRHeader(emit->Invalid(), Entrypoint, 0, 0);
auto Block = emit->CreateCodeNode();
IRHeader.first->Blocks = emit->WrapNode(Block);
emit->SetCurrentCodeBlock(Block);

const uint8_t GPRSize = GetGPRSize();

if (GPRSize == 8) {
emit->_StoreRegister(emit->_Constant(Entrypoint), X86State::REG_R11, IR::GPRClass, GPRSize);
} else {
emit->_StoreContext(GPRSize, IR::FPRClass, emit->_VCastFromGPR(8, 8, emit->_Constant(Entrypoint)), offsetof(Core::CPUState, mm[0][0]));
}
emit->_ExitFunction(emit->_Constant(GuestThunkEntrypoint));
},
ThunkHandler, (void*)GuestThunkEntrypoint);

if (Result.has_value()) {
if (Result->Creator != ThunkHandler) {
ERROR_AND_DIE_FMT("Input address for AddThunkTrampoline is already linked by another module");
}
if (Result->Data != (void*)GuestThunkEntrypoint) {
// NOTE: This may happen in Vulkan thunks if the Vulkan driver resolves two different symbols
// to the same function (e.g. vkGetPhysicalDeviceFeatures2/vkGetPhysicalDeviceFeatures2KHR)
LogMan::Msg::EFmt("Input address for AddThunkTrampoline is already linked elsewhere");
}
}
}

Expand All @@ -1018,12 +1055,6 @@ void ContextImpl::UnloadAOTIRCacheEntry(IR::AOTIRCacheEntry* Entry) {
IRCaptureCache.UnloadAOTIRCacheEntry(Entry);
}

void ContextImpl::AppendThunkDefinitions(std::span<const FEXCore::IR::ThunkDefinition> Definitions) {
if (ThunkHandler) {
ThunkHandler->AppendThunkDefinitions(Definitions);
}
}

void ContextImpl::ConfigureAOTGen(FEXCore::Core::InternalThreadState* Thread, fextl::set<uint64_t>* ExternalBranches, uint64_t SectionMaxAddress) {
Thread->FrontendDecoder->SetExternalBranches(ExternalBranches);
Thread->FrontendDecoder->SetSectionMaxAddress(SectionMaxAddress);
Expand Down
3 changes: 2 additions & 1 deletion FEXCore/Source/Interface/Core/JIT/Arm64/Arm64Relocations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ desc: relocation logic of the arm64 splatter backend
*/
#include "Interface/Context/Context.h"
#include "Interface/Core/JIT/Arm64/JITClass.h"
#include "Interface/HLE/Thunks/Thunks.h"

#include <FEXCore/Core/Thunks.h>

namespace FEXCore::CPU {

Expand Down
2 changes: 1 addition & 1 deletion FEXCore/Source/Interface/Core/JIT/Arm64/BranchOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ tags: backend|arm64

#include "Interface/Core/JIT/Arm64/JITClass.h"

#include <FEXCore/Core/Thunks.h>
#include <FEXCore/Core/X86Enums.h>
#include <FEXCore/Debug/InternalThreadState.h>
#include <FEXCore/HLE/SyscallHandler.h>
#include <FEXCore/Utils/MathUtils.h>
#include <Interface/HLE/Thunks/Thunks.h>

namespace FEXCore::CPU {
#define DEF_OP(x) void Arm64JITCore::Op_##x(IR::IROp_Header const* IROp, IR::NodeID Node)
Expand Down
18 changes: 10 additions & 8 deletions FEXCore/include/FEXCore/Core/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace FEXCore {
class CodeLoader;
struct HostFeatures;
class ForkableSharedMutex;
class ThunkHandler;
} // namespace FEXCore

namespace FEXCore::Core {
Expand Down Expand Up @@ -175,6 +176,7 @@ class Context {
#endif
FEX_DEFAULT_VISIBILITY virtual void SetSignalDelegator(FEXCore::SignalDelegator* SignalDelegation) = 0;
FEX_DEFAULT_VISIBILITY virtual void SetSyscallHandler(FEXCore::HLE::SyscallHandler* Handler) = 0;
FEX_DEFAULT_VISIBILITY virtual void SetThunkHandler(FEXCore::ThunkHandler* Handler) = 0;

FEX_DEFAULT_VISIBILITY virtual FEXCore::CPUID::FunctionResults RunCPUIDFunction(uint32_t Function, uint32_t Leaf) = 0;
FEX_DEFAULT_VISIBILITY virtual FEXCore::CPUID::XCRResults RunXCRFunction(uint32_t Function) = 0;
Expand Down Expand Up @@ -211,14 +213,6 @@ class Context {
*/
FEX_DEFAULT_VISIBILITY virtual bool IsAddressInCodeBuffer(FEXCore::Core::InternalThreadState* Thread, uintptr_t Address) const = 0;

/**
* @brief Allows the frontend to register its own thunk handlers independent of what is controlled in the backend.
*
* @param CTX A valid non-null context instance.
* @param Definitions A vector of thunk definitions that the frontend controls
*/
FEX_DEFAULT_VISIBILITY virtual void AppendThunkDefinitions(std::span<const FEXCore::IR::ThunkDefinition> Definitions) = 0;

/**
* @brief Informs the context if hardware TSO is supported.
* Once hardware TSO is enabled, then TSO emulation through atomics is disabled and relies on the hardware.
Expand All @@ -235,6 +229,14 @@ class Context {
*/
FEX_DEFAULT_VISIBILITY virtual void EnableExitOnHLT() = 0;

/**
* @brief Adds a new Thunk trampoline handler
*
* @param Entrypoint The guest PC that the custom thunk trampoline IR handler will be installed at.
* @param GuestThunkEntrypoint The thunk entrypoint that the IR handler will redirect to.
*/
FEX_DEFAULT_VISIBILITY virtual void AddThunkTrampolineIRHandler(uintptr_t Entrypoint, uintptr_t GuestThunkEntrypoint) = 0;

private:
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ tags: glue|thunks

#pragma once

#include "Interface/IR/IR.h"

#include <FEXCore/fextl/memory.h>
#include <FEXCore/fextl/vector.h>
#include <FEXCore/IR/IR.h>

namespace FEXCore::Context {
class ContextImpl;
class Context;
}

namespace FEXCore::Core {
Expand All @@ -30,11 +29,6 @@ typedef void ThunkedFunction(void* ArgsRv);
class ThunkHandler {
public:
virtual ThunkedFunction* LookupThunk(const IR::SHA256Sum& sha256) = 0;
virtual void RegisterTLSState(FEXCore::Core::InternalThreadState* Thread) = 0;
virtual ~ThunkHandler() {}

static fextl::unique_ptr<ThunkHandler> Create();

virtual void AppendThunkDefinitions(std::span<const FEXCore::IR::ThunkDefinition> Definitions) = 0;
};
}; // namespace FEXCore
11 changes: 8 additions & 3 deletions Source/Tools/FEXLoader/FEXLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ desc: Glues the ELF loader, FEXCore and LinuxSyscalls to launch an elf under fex
#include "LinuxSyscalls/x64/Syscalls.h"
#include "LinuxSyscalls/SignalDelegator.h"
#include "Linux/Utils/ELFContainer.h"
#include "Thunks.h"

#include <FEXCore/Config/Config.h>
#include <FEXCore/Core/Context.h>
Expand Down Expand Up @@ -510,9 +511,11 @@ int main(int argc, char** argv, char** const envp) {
FEX::TSO::SetupTSOEmulation(CTX.get());

auto SignalDelegation = FEX::HLE::CreateSignalDelegator(CTX.get(), Program.ProgramName, SupportsAVX);
auto ThunkHandler = FEX::HLE::CreateThunkHandler();

auto SyscallHandler = Loader.Is64BitMode() ? FEX::HLE::x64::CreateHandler(CTX.get(), SignalDelegation.get()) :
FEX::HLE::x32::CreateHandler(CTX.get(), SignalDelegation.get(), std::move(Allocator));
auto SyscallHandler = Loader.Is64BitMode() ?
FEX::HLE::x64::CreateHandler(CTX.get(), SignalDelegation.get(), ThunkHandler.get()) :
FEX::HLE::x32::CreateHandler(CTX.get(), SignalDelegation.get(), ThunkHandler.get(), std::move(Allocator));

// Load VDSO in to memory prior to mapping our ELFs.
auto VDSOMapping = FEX::VDSO::LoadVDSOThunks(Loader.Is64BitMode(), SyscallHandler.get());
Expand Down Expand Up @@ -545,6 +548,7 @@ int main(int argc, char** argv, char** const envp) {

CTX->SetSignalDelegator(SignalDelegation.get());
CTX->SetSyscallHandler(SyscallHandler.get());
CTX->SetThunkHandler(ThunkHandler.get());

FEX_CONFIG_OPT(GdbServer, GDBSERVER);
fextl::unique_ptr<FEX::GdbServer> DebugServer;
Expand All @@ -559,9 +563,10 @@ int main(int argc, char** argv, char** const envp) {
auto ParentThread = SyscallHandler->TM.CreateThread(Loader.DefaultRIP(), Loader.GetStackPointer());
SyscallHandler->TM.TrackThread(ParentThread);
SignalDelegation->RegisterTLSState(ParentThread);
ThunkHandler->RegisterTLSState(ParentThread);

// Pass in our VDSO thunks
CTX->AppendThunkDefinitions(FEX::VDSO::GetVDSOThunkDefinitions());
ThunkHandler->AppendThunkDefinitions(FEX::VDSO::GetVDSOThunkDefinitions());
SignalDelegation->SetVDSOSigReturn();

SyscallHandler->DeserializeSeccompFD(ParentThread, FEXSeccompFD);
Expand Down
1 change: 1 addition & 0 deletions Source/Tools/LinuxEmulation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ add_compile_options(-fno-operator-names)

set (SRCS
VDSO_Emulation.cpp
Thunks.cpp
LinuxSyscalls/GdbServer.cpp
LinuxSyscalls/EmulatedFiles/EmulatedFiles.cpp
LinuxSyscalls/FaultSafeUserMemAccess.cpp
Expand Down
15 changes: 13 additions & 2 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ desc: Glue logic, brk allocations
#include "LinuxSyscalls/x64/Syscalls.h"
#include "LinuxSyscalls/x32/Types.h"
#include "LinuxSyscalls/x64/Types.h"
#include "Thunks.h"

#include <FEXCore/Config/Config.h>
#include <FEXCore/Core/Context.h>
Expand Down Expand Up @@ -740,12 +741,13 @@ void SyscallHandler::DefaultProgramBreak(uint64_t Base, uint64_t Size) {
DataSpaceStartingSize = Size;
}

SyscallHandler::SyscallHandler(FEXCore::Context::Context* _CTX, FEX::HLE::SignalDelegator* _SignalDelegation)
SyscallHandler::SyscallHandler(FEXCore::Context::Context* _CTX, FEX::HLE::SignalDelegator* _SignalDelegation, FEX::HLE::ThunkHandler* ThunkHandler)
: TM {_CTX, _SignalDelegation}
, SeccompEmulator {this, _SignalDelegation}
, FM {_CTX}
, CTX {_CTX}
, SignalDelegation {_SignalDelegation} {
, SignalDelegation {_SignalDelegation}
, ThunkHandler {ThunkHandler} {
FEX::HLE::_SyscallHandler = this;
HostKernelVersion = CalculateHostKernelVersion();
GuestKernelVersion = CalculateGuestKernelVersion();
Expand Down Expand Up @@ -872,6 +874,15 @@ void SyscallHandler::UnlockAfterFork(FEXCore::Core::InternalThreadState* LiveThr
TM.UnlockAfterFork(LiveThread, Child);
}

void SyscallHandler::RegisterTLSState(FEX::HLE::ThreadStateObject* Thread) {
SignalDelegation->RegisterTLSState(Thread);
ThunkHandler->RegisterTLSState(Thread);
}

void SyscallHandler::UninstallTLSState(FEX::HLE::ThreadStateObject* Thread) {
SignalDelegation->UninstallTLSState(Thread);
}

static bool isHEX(char c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
}
Expand Down
Loading

0 comments on commit f640dcc

Please sign in to comment.