mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-27 04:25:12 +00:00
Merge cac372eb01
into 1b952bf173
This commit is contained in:
commit
57fc14fbce
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user