mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 14:00:16 +02:00
Merge pull request #1247 from Sonicadvance1/handle_xmm_state_32bit
Linux: Handle fpstate in the signal delegator correctly
This commit is contained in:
3 files changed
+69
-33
No files matched your search
@@ -184,20 +184,27 @@ bool Dispatcher::HandleGuestSignal(int Signal, void *info, void *ucontext, Guest
|
||||
|
||||
// Setup ucontext a bit
|
||||
if (Is64BitMode) {
|
||||
NewGuestSP -= sizeof(FEXCore::x86_64::_libc_fpstate);
|
||||
NewGuestSP = AlignDown(NewGuestSP, alignof(FEXCore::x86_64::_libc_fpstate));
|
||||
uint64_t FPStateLocation = NewGuestSP;
|
||||
|
||||
NewGuestSP -= sizeof(FEXCore::x86_64::ucontext_t);
|
||||
NewGuestSP = AlignDown(NewGuestSP, alignof(FEXCore::x86_64::ucontext_t));
|
||||
uint64_t UContextLocation = NewGuestSP;
|
||||
|
||||
NewGuestSP -= sizeof(siginfo_t);
|
||||
NewGuestSP = AlignDown(NewGuestSP, alignof(siginfo_t));
|
||||
uint64_t SigInfoLocation = NewGuestSP;
|
||||
|
||||
FEXCore::x86_64::ucontext_t *guest_uctx = reinterpret_cast<FEXCore::x86_64::ucontext_t*>(UContextLocation);
|
||||
siginfo_t *guest_siginfo = reinterpret_cast<siginfo_t*>(SigInfoLocation);
|
||||
|
||||
// We have extended float information
|
||||
guest_uctx->uc_flags |= FEXCore::x86_64::UC_FP_XSTATE;
|
||||
guest_uctx->uc_flags = FEXCore::x86_64::UC_FP_XSTATE;
|
||||
|
||||
// Pointer to where the fpreg memory is
|
||||
guest_uctx->uc_mcontext.fpregs = &guest_uctx->__fpregs_mem;
|
||||
guest_uctx->uc_mcontext.fpregs = reinterpret_cast<FEXCore::x86_64::_libc_fpstate*>(FPStateLocation);
|
||||
FEXCore::x86_64::_libc_fpstate *fpstate = reinterpret_cast<FEXCore::x86_64::_libc_fpstate*>(FPStateLocation);
|
||||
|
||||
guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_RIP] = Frame->State.rip;
|
||||
guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_EFL] = 0;
|
||||
@@ -228,15 +235,15 @@ bool Dispatcher::HandleGuestSignal(int Signal, void *info, void *ucontext, Guest
|
||||
#undef COPY_REG
|
||||
|
||||
// Copy float registers
|
||||
memcpy(guest_uctx->__fpregs_mem._st, Frame->State.mm, sizeof(Frame->State.mm));
|
||||
memcpy(guest_uctx->__fpregs_mem._xmm, Frame->State.xmm, sizeof(Frame->State.xmm));
|
||||
memcpy(fpstate->_st, Frame->State.mm, sizeof(Frame->State.mm));
|
||||
memcpy(fpstate->_xmm, Frame->State.xmm, sizeof(Frame->State.xmm));
|
||||
|
||||
// FCW store default
|
||||
guest_uctx->__fpregs_mem.fcw = Frame->State.FCW;
|
||||
guest_uctx->__fpregs_mem.ftw = Frame->State.FTW;
|
||||
fpstate->fcw = Frame->State.FCW;
|
||||
fpstate->ftw = Frame->State.FTW;
|
||||
|
||||
// Reconstruct FSW
|
||||
guest_uctx->__fpregs_mem.fsw =
|
||||
fpstate->fsw =
|
||||
(Frame->State.flags[FEXCore::X86State::X87FLAG_TOP_LOC] << 11) |
|
||||
(Frame->State.flags[FEXCore::X86State::X87FLAG_C0_LOC] << 8) |
|
||||
(Frame->State.flags[FEXCore::X86State::X87FLAG_C1_LOC] << 9) |
|
||||
@@ -257,20 +264,27 @@ bool Dispatcher::HandleGuestSignal(int Signal, void *info, void *ucontext, Guest
|
||||
Frame->State.gregs[X86State::REG_RDX] = UContextLocation;
|
||||
}
|
||||
else {
|
||||
// XXX: 32bit Support
|
||||
NewGuestSP -= sizeof(FEXCore::x86::_libc_fpstate);
|
||||
NewGuestSP = AlignDown(NewGuestSP, alignof(FEXCore::x86::_libc_fpstate));
|
||||
uint64_t FPStateLocation = NewGuestSP;
|
||||
|
||||
NewGuestSP -= sizeof(FEXCore::x86::ucontext_t);
|
||||
NewGuestSP = AlignDown(NewGuestSP, alignof(FEXCore::x86::ucontext_t));
|
||||
uint64_t UContextLocation = NewGuestSP;
|
||||
|
||||
NewGuestSP -= sizeof(FEXCore::x86::siginfo_t);
|
||||
NewGuestSP = AlignDown(NewGuestSP, alignof(FEXCore::x86::siginfo_t));
|
||||
uint64_t SigInfoLocation = NewGuestSP;
|
||||
|
||||
FEXCore::x86::ucontext_t *guest_uctx = reinterpret_cast<FEXCore::x86::ucontext_t*>(UContextLocation);
|
||||
FEXCore::x86::siginfo_t *guest_siginfo = reinterpret_cast<FEXCore::x86::siginfo_t*>(SigInfoLocation);
|
||||
|
||||
// We have extended float information
|
||||
guest_uctx->uc_flags |= FEXCore::x86::UC_FP_XSTATE;
|
||||
guest_uctx->uc_flags = FEXCore::x86::UC_FP_XSTATE;
|
||||
|
||||
// Pointer to where the fpreg memory is
|
||||
guest_uctx->uc_mcontext.fpregs = static_cast<uint32_t>(reinterpret_cast<uint64_t>(&guest_uctx->__fpregs_mem));
|
||||
guest_uctx->uc_mcontext.fpregs = static_cast<uint32_t>(FPStateLocation);
|
||||
FEXCore::x86::_libc_fpstate *fpstate = reinterpret_cast<FEXCore::x86::_libc_fpstate*>(FPStateLocation);
|
||||
|
||||
guest_uctx->uc_mcontext.gregs[FEXCore::x86::FEX_REG_GS] = Frame->State.gs;
|
||||
guest_uctx->uc_mcontext.gregs[FEXCore::x86::FEX_REG_FS] = Frame->State.fs;
|
||||
@@ -297,20 +311,20 @@ bool Dispatcher::HandleGuestSignal(int Signal, void *info, void *ucontext, Guest
|
||||
#undef COPY_REG
|
||||
|
||||
// Copy float registers
|
||||
memcpy(guest_uctx->__fpregs_mem._st, Frame->State.mm, sizeof(Frame->State.mm));
|
||||
if (0) {
|
||||
// XXX: Handle XMM
|
||||
// memcpy(guest_uctx->__fpregs_mem._xmm, Frame->State.xmm, sizeof(Frame->State.xmm));
|
||||
guest_uctx->__fpregs_mem.status = FEXCore::x86::fpstate_magic::MAGIC_XFPSTATE;
|
||||
}
|
||||
else {
|
||||
guest_uctx->__fpregs_mem.status = FEXCore::x86::fpstate_magic::MAGIC_FPU;
|
||||
for (size_t i = 0; i < 8; ++i) {
|
||||
// 32-bit st register size is only 10 bytes. Not padded to 16byte like x86-64
|
||||
memcpy(&fpstate->_st[i], &Frame->State.mm[i], 10);
|
||||
}
|
||||
|
||||
// Extended XMM state
|
||||
fpstate->status = FEXCore::x86::fpstate_magic::MAGIC_XFPSTATE;
|
||||
memcpy(fpstate->_xmm, Frame->State.xmm, sizeof(Frame->State.xmm));
|
||||
|
||||
// FCW store default
|
||||
guest_uctx->__fpregs_mem.fcw = Frame->State.FCW;
|
||||
guest_uctx->__fpregs_mem.ftw = Frame->State.FTW;
|
||||
fpstate->fcw = Frame->State.FCW;
|
||||
fpstate->ftw = Frame->State.FTW;
|
||||
// Reconstruct FSW
|
||||
guest_uctx->__fpregs_mem.fsw =
|
||||
fpstate->fsw =
|
||||
(Frame->State.flags[FEXCore::X86State::X87FLAG_TOP_LOC] << 11) |
|
||||
(Frame->State.flags[FEXCore::X86State::X87FLAG_C0_LOC] << 8) |
|
||||
(Frame->State.flags[FEXCore::X86State::X87FLAG_C1_LOC] << 9) |
|
||||
@@ -347,9 +361,14 @@ bool Dispatcher::HandleGuestSignal(int Signal, void *info, void *ucontext, Guest
|
||||
guest_siginfo->_sifields._sigchld.utime = HostSigInfo->si_utime;
|
||||
guest_siginfo->_sifields._sigchld.stime = HostSigInfo->si_stime;
|
||||
break;
|
||||
case SIGALRM:
|
||||
case SIGVTALRM:
|
||||
guest_siginfo->_sifields._timer.tid = HostSigInfo->si_timerid;
|
||||
guest_siginfo->_sifields._timer.overrun = HostSigInfo->si_overrun;
|
||||
guest_siginfo->_sifields._timer.sigval.sival_int = HostSigInfo->si_int;
|
||||
break;
|
||||
default:
|
||||
// Hope for the best, most things just copy over
|
||||
memcpy(&guest_siginfo->_sifields, &HostSigInfo->_sifields, sizeof(siginfo_t));
|
||||
LogMan::Msg::E("Unhandled siginfo_t for signal: %d\n", Signal);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+23
-7
@@ -86,12 +86,10 @@ namespace FEXCore {
|
||||
FEXCore::x86_64::stack_t uc_stack;
|
||||
FEXCore::x86_64::mcontext_t uc_mcontext;
|
||||
FEXCore::x86_64::sigset_t uc_sigmask;
|
||||
FEXCore::x86_64::_libc_fpstate __fpregs_mem;
|
||||
uint64_t __ssp[4];
|
||||
};
|
||||
static_assert(offsetof(FEXCore::x86_64::ucontext_t, uc_mcontext) == 40, "Needs to be correct");
|
||||
|
||||
static_assert(sizeof(FEXCore::x86_64::ucontext_t) == 968, "This needs to be the right size");
|
||||
static_assert(sizeof(FEXCore::x86_64::ucontext_t) == 424, "This needs to be the right size");
|
||||
}
|
||||
|
||||
namespace x86 {
|
||||
@@ -123,6 +121,11 @@ namespace FEXCore {
|
||||
};
|
||||
static_assert(FEX_REG_SS == 18, "Oops");
|
||||
|
||||
union sigval_t {
|
||||
int sival_int;
|
||||
uint32_t sival_ptr; // XXX: Should be compat_ptr<void>
|
||||
};
|
||||
|
||||
struct FEX_PACKED siginfo_t {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
@@ -141,6 +144,12 @@ namespace FEXCore {
|
||||
int32_t utime;
|
||||
int32_t stime;
|
||||
} _sigchld;
|
||||
/* SIGALRM, SIGVTALRM */
|
||||
struct {
|
||||
int tid;
|
||||
int overrun;
|
||||
FEXCore::x86::sigval_t sigval;
|
||||
} _timer;
|
||||
} _sifields;
|
||||
};
|
||||
static_assert(sizeof(FEXCore::x86::siginfo_t) == 128, "This needs to be the right size");
|
||||
@@ -183,8 +192,17 @@ namespace FEXCore {
|
||||
uint32_t datasel;
|
||||
FEXCore::x86::_libc_fpreg _st[8];
|
||||
uint32_t status;
|
||||
|
||||
// Extended FPU data
|
||||
uint32_t pad[6]; // Ignored FXSR data
|
||||
uint32_t mxcsr;
|
||||
uint32_t reserved;
|
||||
__uint128_t _st_pad[8]; // Ignored st data
|
||||
__uint128_t _xmm[8]; // First 8 XMM registers
|
||||
uint32_t pad2[44]; // Second 8 XMM registers plus padding
|
||||
uint32_t pad3[12]; // extended state encoding
|
||||
};
|
||||
static_assert(sizeof(FEXCore::x86::_libc_fpstate) == 112, "This needs to be the right size");
|
||||
static_assert(sizeof(FEXCore::x86::_libc_fpstate) == 624, "This needs to be the right size");
|
||||
|
||||
struct FEX_PACKED ucontext_t {
|
||||
uint32_t uc_flags;
|
||||
@@ -192,10 +210,8 @@ namespace FEXCore {
|
||||
FEXCore::x86::stack_t uc_stack;
|
||||
FEXCore::x86::mcontext_t uc_mcontext;
|
||||
FEXCore::x86_64::sigset_t uc_sigmask; // This matches across architectures
|
||||
FEXCore::x86::_libc_fpstate __fpregs_mem;
|
||||
uint32_t __ssp[4];
|
||||
};
|
||||
static_assert(sizeof(FEXCore::x86::ucontext_t) == 364, "This needs to be the right size");
|
||||
static_assert(sizeof(FEXCore::x86::ucontext_t) == 236, "This needs to be the right size");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -174,9 +174,10 @@ namespace FEX::HLE {
|
||||
// Now install the thunk handler
|
||||
SignalHandler.HostAction.sigaction = SignalHandlerThunk;
|
||||
|
||||
if (SignalHandler.GuestAction.sa_flags & SA_NODEFER) {
|
||||
// If the guest is using NODEFER then make sure to set it for the host as well
|
||||
SignalHandler.HostAction.sa_flags |= SA_NODEFER;
|
||||
if ((SignalHandler.HostAction.sa_flags ^ SignalHandler.GuestAction.sa_flags) & SA_NODEFER) {
|
||||
// If the guest is using SA_NODEFER then make sure to set it for the host as well
|
||||
SignalHandler.HostAction.sa_flags &= ~SA_NODEFER;
|
||||
SignalHandler.HostAction.sa_flags |= SignalHandler.GuestAction.sa_flags & SA_NODEFER;
|
||||
}
|
||||
|
||||
if ((SignalHandler.HostAction.sa_flags ^ SignalHandler.GuestAction.sa_flags) & SA_RESTART) {
|
||||
|
||||
Reference in new issue
Block a user