mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 13:00:15 +02:00
FEXCore: Removes syscall optimization
The JIT was doing a bunch of additional work where it was saving and restoring registers and then juggling the arguments back in to a stack frame. All of this is nonsensical without the optimization where we could call syscalls inline without a stack frame. Instead remove this optimization entirely and behave like a "generic" syscall path always. The Linux syscall handler now pulls the arguments out of the CPU context directly and stores the result back in to RAX directly as well. This has knock-on effects where technically syscalls are going to be slightly faster because no stack frame setup for the arguments, but additionally we are going to be able to have syscalls be proper serialization points where we can interrupt the syscall and long-jump out without problems. Bumps the DiskCache version again because it causes codegen to change.
This commit is contained in:
19 files changed
+158
-201
No files matched your search
@@ -108,15 +108,11 @@ ExitFunctionSuspendPoint:
|
||||
Name:; \
|
||||
adrp x16, WineSyscallDispatcher; \
|
||||
ldr x16, [x16, HASH:lo12:WineSyscallDispatcher]; \
|
||||
cbz x16, 1f; \
|
||||
mov x9, x30; \
|
||||
adrp x8, WineIdName; \
|
||||
ldr x8, [x8, HASH:lo12:WineIdName]; \
|
||||
blr x16; \
|
||||
ret; \
|
||||
1:; \
|
||||
svc HASH WindowsId; \
|
||||
ret
|
||||
|
||||
// Allows for continuing from a full native context, as the NTDLL NtContinue export takes in an x64 context with EC and
|
||||
// the conversion to that loses the ARM64EC ABI-disallowed registers that FEX uses.
|
||||
|
||||
@@ -513,11 +513,9 @@ static void RethrowGuestException(const EXCEPTION_RECORD& Rec, ARM64_NT_CONTEXT&
|
||||
|
||||
class ECSyscallHandler : public FEXCore::HLE::SyscallHandler, public FEXCore::Allocator::FEXAllocOperators {
|
||||
public:
|
||||
ECSyscallHandler() {
|
||||
OSABI = FEXCore::HLE::SyscallOSABI::OS_GENERIC;
|
||||
}
|
||||
ECSyscallHandler() = default;
|
||||
|
||||
uint64_t HandleSyscall(FEXCore::Core::CpuStateFrame* Frame, FEXCore::HLE::SyscallArguments* Args) override {
|
||||
void HandleSyscall(FEXCore::Core::CpuStateFrame* Frame) override {
|
||||
ProcessPendingCrossProcessEmulatorWork();
|
||||
|
||||
// Manually raise an exeption with the current JIT state packed into a native context, ntdll handles this and
|
||||
|
||||
@@ -417,6 +417,20 @@ bool HandleSuspendInterrupt(TLS TLS, CONTEXT* Context, uint64_t FaultAddress) {
|
||||
}
|
||||
} // namespace Context
|
||||
|
||||
// Calls a 1-argument function `Func` setting the parent unwind frame information to the given SP and PC
|
||||
__attribute__((naked)) extern "C" uint64_t SEHFrameTrampoline1Args(void* Arg0, void* Func, uint64_t Sp, uint64_t Pc) {
|
||||
asm(".seh_proc SEHFrameTrampoline1Args;"
|
||||
"stp x2, x3, [sp, #-0x10]!;"
|
||||
".seh_pushframe;"
|
||||
"stp x29, x30, [sp, #-0x10]!;"
|
||||
".seh_save_fplr_x 16;"
|
||||
".seh_endprologue;"
|
||||
"blr x1;"
|
||||
"ldp x29, x30, [sp], 0x20;"
|
||||
"ret;"
|
||||
".seh_endproc;");
|
||||
}
|
||||
|
||||
// Calls a 2-argument function `Func` setting the parent unwind frame information to the given SP and PC
|
||||
__attribute__((naked)) extern "C" uint64_t SEHFrameTrampoline2Args(void* Arg0, void* Arg1, void* Func, uint64_t Sp, uint64_t Pc) {
|
||||
asm(".seh_proc SEHFrameTrampoline2Args;"
|
||||
@@ -433,11 +447,9 @@ __attribute__((naked)) extern "C" uint64_t SEHFrameTrampoline2Args(void* Arg0, v
|
||||
|
||||
class WowSyscallHandler : public FEXCore::HLE::SyscallHandler, public FEXCore::Allocator::FEXAllocOperators {
|
||||
public:
|
||||
WowSyscallHandler() {
|
||||
OSABI = FEXCore::HLE::SyscallOSABI::OS_GENERIC;
|
||||
}
|
||||
WowSyscallHandler() = default;
|
||||
|
||||
static uint64_t HandleSyscallImpl(FEXCore::Core::CpuStateFrame* Frame, FEXCore::HLE::SyscallArguments* Args) {
|
||||
static void HandleSyscallImpl(FEXCore::Core::CpuStateFrame* Frame) {
|
||||
const uint64_t ReturnRIP = *(uint32_t*)(Frame->State.gregs[FEXCore::X86State::REG_RSP]); // Return address from the stack
|
||||
uint64_t ReturnRSP = Frame->State.gregs[FEXCore::X86State::REG_RSP] + 4; // Stack pointer after popping return address
|
||||
uint64_t ReturnRAX = 0;
|
||||
@@ -470,20 +482,16 @@ public:
|
||||
Context::LockJITContext(TLS);
|
||||
Frame->State.gregs[FEXCore::X86State::REG_RAX] = ReturnRAX;
|
||||
}
|
||||
|
||||
// NORETURNEDRESULT causes this result to be ignored since we restore all registers back from memory after a syscall anyway
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t HandleSyscall(FEXCore::Core::CpuStateFrame* Frame, FEXCore::HLE::SyscallArguments* Args) override {
|
||||
void HandleSyscall(FEXCore::Core::CpuStateFrame* Frame) override {
|
||||
const auto TLS = GetTLS();
|
||||
// Stash the the context pointer on the stack, as Simulate can be called from this syscall handler which would overwrite it
|
||||
CONTEXT* EntryContext = TLS.EntryContext();
|
||||
// Call the syscall handler with unwind information pointing to Simulate as its caller
|
||||
uint64_t Ret = SEHFrameTrampoline2Args(reinterpret_cast<void*>(Frame), reinterpret_cast<void*>(Args),
|
||||
reinterpret_cast<void*>(&HandleSyscallImpl), EntryContext->Sp, EntryContext->Pc);
|
||||
uint64_t Ret =
|
||||
SEHFrameTrampoline1Args(reinterpret_cast<void*>(Frame), reinterpret_cast<void*>(&HandleSyscallImpl), EntryContext->Sp, EntryContext->Pc);
|
||||
TLS.EntryContext() = EntryContext;
|
||||
return Ret;
|
||||
}
|
||||
|
||||
std::optional<FEXCore::ExecutableFileSectionInfo> LookupExecutableFileSection(FEXCore::Core::InternalThreadState*, uint64_t Address) override {
|
||||
|
||||
Reference in new issue
Block a user