This commit is contained in:
squidbus 2025-05-22 00:12:46 +07:00 committed by GitHub
commit 57fc14fbce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 46 additions and 38 deletions

View File

@ -402,10 +402,7 @@ static const std::unordered_map<ZydisMnemonic, PatchInfo> Patches = {
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
#if defined(_WIN32)
// Windows needs a trampoline.
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, true}},
#elif !defined(__APPLE__)
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, false}},
#endif
};
@ -674,24 +671,12 @@ static bool TryPatchJit(void* code_address) {
return TryPatch(code, module).first;
}
static void TryPatchAot(void* code_address, u64 code_size) {
auto* code = static_cast<u8*>(code_address);
auto* module = GetModule(code);
if (module == nullptr) {
return;
}
std::unique_lock lock{module->mutex};
const auto* end = code + code_size;
while (code < end) {
code += TryPatch(code, module).second;
}
}
#ifdef _WIN32
// Used for patching TCB accesses on Windows.
static bool PatchesAccessViolationHandler(void* context, void* /* fault_address */) {
return TryPatchJit(Common::GetRip(context));
}
#endif
static bool PatchesIllegalInstructionHandler(void* context) {
void* code_address = Common::GetRip(context);
@ -719,7 +704,9 @@ static void PatchesInit() {
auto* signals = Signals::Instance();
// Should be called last.
constexpr auto priority = std::numeric_limits<u32>::max();
#ifdef _WIN32
signals->RegisterAccessViolationHandler(PatchesAccessViolationHandler, priority);
#endif
signals->RegisterIllegalInstructionHandler(PatchesIllegalInstructionHandler, priority);
}
}
@ -735,14 +722,4 @@ void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_are
trampoline_area_size));
}
void PrePatchInstructions(u64 segment_addr, u64 segment_size) {
#if !defined(_WIN32) && !defined(__APPLE__)
// Linux and others have an FS segment pointing to valid memory, so continue to do full
// ahead-of-time patching for now until a better solution is worked out.
if (!Patches.empty()) {
TryPatchAot(reinterpret_cast<void*>(segment_addr), segment_size);
}
#endif
}
} // namespace Core

View File

@ -11,7 +11,4 @@ namespace Core {
void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_area_ptr,
u64 trampoline_area_size);
/// Applies CPU patches that need to be done before beginning executions.
void PrePatchInstructions(u64 segment_addr, u64 segment_size);
} // namespace Core

View File

@ -163,11 +163,6 @@ void Module::LoadModuleToMemory(u32& max_tls_index) {
LOG_INFO(Core_Linker, "segment_mode ..........: {}", segment_mode);
add_segment(elf_pheader[i]);
#ifdef ARCH_X86_64
if (elf_pheader[i].p_flags & PF_EXEC) {
PrePatchInstructions(segment_addr, segment_file_size);
}
#endif
break;
}
case PT_DYNAMIC:

View File

@ -46,6 +46,8 @@ Tcb* GetTcbBase() {
return reinterpret_cast<Tcb*>(TlsGetValue(GetTcbKey()));
}
void SwapTcb() {}
#elif defined(__APPLE__) && defined(ARCH_X86_64)
// Apple x86_64
@ -151,6 +153,8 @@ Tcb* GetTcbBase() {
return tcb;
}
void SwapTcb() {}
#elif defined(ARCH_X86_64)
// Other POSIX x86_64
@ -165,6 +169,17 @@ Tcb* GetTcbBase() {
return tcb;
}
void SwapTcb() {
void* fs;
void* gs;
asm volatile("rdfsbase %0" : "=r"(fs)::"memory");
asm volatile("rdgsbase %0" : "=r"(gs)::"memory");
// Swap FS and GS
asm volatile("wrfsbase %0" ::"r"(gs) : "memory");
asm volatile("wrgsbase %0" ::"r"(fs) : "memory");
}
#else
// POSIX non-x86_64
@ -191,6 +206,8 @@ Tcb* GetTcbBase() {
return static_cast<Tcb*>(pthread_getspecific(GetTcbKey()));
}
void SwapTcb() {}
#endif
thread_local std::once_flag init_tls_flag;

View File

@ -39,6 +39,9 @@ void SetTcbBase(void* image_address);
/// Retrieves Tcb structure for the calling thread.
Tcb* GetTcbBase();
/// Swaps the TCB in or out of the fs register, if required by the platform.
void SwapTcb();
/// Makes sure TLS is initialized for the thread before entering guest.
void EnsureThreadInitialized();
@ -54,7 +57,17 @@ ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), CallArgs&&
EnsureThreadInitialized();
// clear stack to avoid trash from EnsureThreadInitialized
ClearStack<13_KB>();
return func(std::forward<CallArgs>(args)...);
if constexpr (std::is_same_v<ReturnType, void>) {
SwapTcb();
func(std::forward<CallArgs>(args)...);
SwapTcb();
} else {
SwapTcb();
auto ret = func(std::forward<CallArgs>(args)...);
SwapTcb();
return ret;
}
}
template <class F, F f>
@ -63,7 +76,16 @@ struct HostCallWrapperImpl;
template <class ReturnType, class... Args, PS4_SYSV_ABI ReturnType (*func)(Args...)>
struct HostCallWrapperImpl<PS4_SYSV_ABI ReturnType (*)(Args...), func> {
static ReturnType PS4_SYSV_ABI wrap(Args... args) {
return func(args...);
if constexpr (std::is_same_v<ReturnType, void>) {
SwapTcb();
func(args...);
SwapTcb();
} else {
SwapTcb();
auto ret = func(args...);
SwapTcb();
return ret;
}
}
};