Skip to content

Commit

Permalink
Merge pull request #4077 from Sonicadvance1/frontend_informed_support…
Browse files Browse the repository at this point in the history
…savx

SignalDelegator: Let the frontend inform AVX support
  • Loading branch information
lioncash authored Sep 27, 2024
2 parents 4d62e75 + e7605c9 commit 9100235
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 40 deletions.
2 changes: 0 additions & 2 deletions FEXCore/Source/Interface/Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,6 @@ bool ContextImpl::InitCore() {

// Set up the SignalDelegator config since core is initialized.
FEXCore::SignalDelegator::SignalDelegatorConfig SignalConfig {
.SupportsAVX = HostFeatures.SupportsAVX,

.DispatcherBegin = Dispatcher->Start,
.DispatcherEnd = Dispatcher->End,

Expand Down
2 changes: 0 additions & 2 deletions FEXCore/include/FEXCore/Core/SignalDelegator.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ class SignalDelegator {
virtual ~SignalDelegator() = default;

struct SignalDelegatorConfig {
bool SupportsAVX {};

// Dispatcher information
uint64_t DispatcherBegin;
uint64_t DispatcherEnd;
Expand Down
4 changes: 3 additions & 1 deletion Source/Tools/FEXLoader/FEXLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,16 +498,18 @@ int main(int argc, char** argv, char** const envp) {
// System allocator is now system allocator or FEX
FEXCore::Context::InitializeStaticTables(Loader.Is64BitMode() ? FEXCore::Context::MODE_64BIT : FEXCore::Context::MODE_32BIT);

bool SupportsAVX {};
fextl::unique_ptr<FEXCore::Context::Context> CTX;
{
auto HostFeatures = FEX::FetchHostFeatures();
CTX = FEXCore::Context::Context::CreateNewContext(HostFeatures);
SupportsAVX = HostFeatures.SupportsAVX;
}

// Setup TSO hardware emulation immediately after initializing the context.
FEX::TSO::SetupTSOEmulation(CTX.get());

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

auto SyscallHandler = Loader.Is64BitMode() ? FEX::HLE::x64::CreateHandler(CTX.get(), SignalDelegation.get()) :
FEX::HLE::x32::CreateHandler(CTX.get(), SignalDelegation.get(), std::move(Allocator));
Expand Down
20 changes: 10 additions & 10 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ void SignalDelegator::SpillSRA(FEXCore::Core::InternalThreadState* Thread, void*
Thread->CurrentFrame->State.gregs[i] = ArchHelpers::Context::GetArmReg(ucontext, SRAIdxMap);
}

if (Config.SupportsAVX) {
if (SupportsAVX) {
// TODO: This doesn't save the upper 128-bits of the 256-bit registers.
// This needs to be implemented still.
for (size_t i = 0; i < Config.SRAFPRCount; i++) {
Expand Down Expand Up @@ -178,8 +178,6 @@ ArchHelpers::Context::ContextBackup* SignalDelegator::StoreThreadState(FEXCore::
}

void SignalDelegator::RestoreThreadState(FEXCore::Core::InternalThreadState* Thread, void* ucontext, RestoreType Type) {
const bool IsAVXEnabled = Config.SupportsAVX;

uint64_t OldSP {};
if (Type == RestoreType::TYPE_PAUSE) [[unlikely]] {
OldSP = ArchHelpers::Context::GetSp(ucontext);
Expand All @@ -203,7 +201,7 @@ void SignalDelegator::RestoreThreadState(FEXCore::Core::InternalThreadState* Thr
GuestSP += sizeof(siginfo_t);
GuestSP = FEXCore::AlignUp(GuestSP, alignof(siginfo_t));

if (IsAVXEnabled) {
if (SupportsAVX) {
GuestSP += sizeof(FEXCore::x86_64::xstate);
GuestSP = FEXCore::AlignUp(GuestSP, alignof(FEXCore::x86_64::xstate));
} else {
Expand All @@ -221,7 +219,7 @@ void SignalDelegator::RestoreThreadState(FEXCore::Core::InternalThreadState* Thr
GuestSP += sizeof(SigFrame_i32) - 8;
GuestSP = FEXCore::AlignUp(GuestSP, alignof(SigFrame_i32));

if (IsAVXEnabled) {
if (SupportsAVX) {
GuestSP += sizeof(FEXCore::x86::xstate);
GuestSP = FEXCore::AlignUp(GuestSP, alignof(FEXCore::x86::xstate));
} else {
Expand All @@ -238,7 +236,7 @@ void SignalDelegator::RestoreThreadState(FEXCore::Core::InternalThreadState* Thr
GuestSP += sizeof(RTSigFrame_i32) - 4;
GuestSP = FEXCore::AlignUp(GuestSP, alignof(RTSigFrame_i32));

if (IsAVXEnabled) {
if (SupportsAVX) {
GuestSP += sizeof(FEXCore::x86::xstate);
GuestSP = FEXCore::AlignUp(GuestSP, alignof(FEXCore::x86::xstate));
} else {
Expand Down Expand Up @@ -833,9 +831,10 @@ void SignalDelegator::QueueSignal(pid_t tgid, pid_t tid, int Signal, siginfo_t*
}
}

SignalDelegator::SignalDelegator(FEXCore::Context::Context* _CTX, const std::string_view ApplicationName)
SignalDelegator::SignalDelegator(FEXCore::Context::Context* _CTX, const std::string_view ApplicationName, bool SupportsAVX)
: CTX {_CTX}
, ApplicationName {ApplicationName} {
, ApplicationName {ApplicationName}
, SupportsAVX {SupportsAVX} {
// Signal zero isn't real
HostHandlers[0].Installed = true;

Expand Down Expand Up @@ -1295,7 +1294,8 @@ uint64_t SignalDelegator::GuestSignalFD(int fd, const uint64_t* set, size_t sigs
return Result == -1 ? -errno : Result;
}

fextl::unique_ptr<FEX::HLE::SignalDelegator> CreateSignalDelegator(FEXCore::Context::Context* CTX, const std::string_view ApplicationName) {
return fextl::make_unique<FEX::HLE::SignalDelegator>(CTX, ApplicationName);
fextl::unique_ptr<FEX::HLE::SignalDelegator>
CreateSignalDelegator(FEXCore::Context::Context* CTX, const std::string_view ApplicationName, bool SupportsAVX) {
return fextl::make_unique<FEX::HLE::SignalDelegator>(CTX, ApplicationName, SupportsAVX);
}
} // namespace FEX::HLE
6 changes: 4 additions & 2 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class SignalDelegator final : public FEXCore::SignalDelegator, public FEXCore::A

// Returns true if the host handled the signal
// Arguments are the same as sigaction handler
SignalDelegator(FEXCore::Context::Context* _CTX, const std::string_view ApplicationName);
SignalDelegator(FEXCore::Context::Context* _CTX, const std::string_view ApplicationName, bool SupportsAVX);
~SignalDelegator() override;

// Called from the signal trampoline function.
Expand Down Expand Up @@ -274,7 +274,9 @@ class SignalDelegator final : public FEXCore::SignalDelegator, public FEXCore::A

std::mutex HostDelegatorMutex;
std::mutex GuestDelegatorMutex;
bool SupportsAVX;
};

fextl::unique_ptr<FEX::HLE::SignalDelegator> CreateSignalDelegator(FEXCore::Context::Context* CTX, const std::string_view ApplicationName);
fextl::unique_ptr<FEX::HLE::SignalDelegator>
CreateSignalDelegator(FEXCore::Context::Context* CTX, const std::string_view ApplicationName, bool SupportsAVX);
} // namespace FEX::HLE
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ static void SetXStateInfo(T* xstate, bool is_avx_enabled) {

void SignalDelegator::RestoreFrame_x64(FEXCore::Core::InternalThreadState* Thread, ArchHelpers::Context::ContextBackup* Context,
FEXCore::Core::CpuStateFrame* Frame, void* ucontext) {
const bool IsAVXEnabled = Config.SupportsAVX;

auto* guest_uctx = reinterpret_cast<FEXCore::x86_64::ucontext_t*>(Context->UContextLocation);
[[maybe_unused]] auto* guest_siginfo = reinterpret_cast<siginfo_t*>(Context->SigInfoLocation);

Expand Down Expand Up @@ -155,7 +153,7 @@ void SignalDelegator::RestoreFrame_x64(FEXCore::Core::InternalThreadState* Threa
// Copy float registers
memcpy(Frame->State.mm, fpstate->_st, sizeof(Frame->State.mm));

if (IsAVXEnabled) {
if (SupportsAVX) {
CTX->SetXMMRegistersFromState(Thread, fpstate->_xmm, xstate->ymmh.ymmh_space);
} else {
CTX->SetXMMRegistersFromState(Thread, fpstate->_xmm, nullptr);
Expand All @@ -176,8 +174,6 @@ void SignalDelegator::RestoreFrame_x64(FEXCore::Core::InternalThreadState* Threa

void SignalDelegator::RestoreFrame_ia32(FEXCore::Core::InternalThreadState* Thread, ArchHelpers::Context::ContextBackup* Context,
FEXCore::Core::CpuStateFrame* Frame, void* ucontext) {
const bool IsAVXEnabled = Config.SupportsAVX;

SigFrame_i32* guest_uctx = reinterpret_cast<SigFrame_i32*>(Context->UContextLocation);
// If the guest modified the RIP then we need to take special precautions here
if (Context->OriginalRIP != guest_uctx->sc.ip || Context->FaultToTopAndGeneratedException) {
Expand Down Expand Up @@ -228,7 +224,7 @@ void SignalDelegator::RestoreFrame_ia32(FEXCore::Core::InternalThreadState* Thre
}

// Extended XMM state
if (IsAVXEnabled) {
if (SupportsAVX) {
CTX->SetXMMRegistersFromState(Thread, fpstate->_xmm, xstate->ymmh.ymmh_space);
} else {
CTX->SetXMMRegistersFromState(Thread, fpstate->_xmm, nullptr);
Expand All @@ -249,8 +245,6 @@ void SignalDelegator::RestoreFrame_ia32(FEXCore::Core::InternalThreadState* Thre

void SignalDelegator::RestoreRTFrame_ia32(FEXCore::Core::InternalThreadState* Thread, ArchHelpers::Context::ContextBackup* Context,
FEXCore::Core::CpuStateFrame* Frame, void* ucontext) {
const bool IsAVXEnabled = Config.SupportsAVX;

RTSigFrame_i32* guest_uctx = reinterpret_cast<RTSigFrame_i32*>(Context->UContextLocation);
// If the guest modified the RIP then we need to take special precautions here
if (Context->OriginalRIP != guest_uctx->uc.uc_mcontext.gregs[FEXCore::x86::FEX_REG_EIP] || Context->FaultToTopAndGeneratedException) {
Expand Down Expand Up @@ -302,7 +296,7 @@ void SignalDelegator::RestoreRTFrame_ia32(FEXCore::Core::InternalThreadState* Th
}

// Extended XMM state
if (IsAVXEnabled) {
if (SupportsAVX) {
CTX->SetXMMRegistersFromState(Thread, fpstate->_xmm, xstate->ymmh.ymmh_space);
} else {
CTX->SetXMMRegistersFromState(Thread, fpstate->_xmm, nullptr);
Expand All @@ -329,8 +323,6 @@ uint64_t SignalDelegator::SetupFrame_x64(FEXCore::Core::InternalThreadState* Thr
// 32-bit doesn't have a redzone
NewGuestSP -= 128;

const bool IsAVXEnabled = Config.SupportsAVX;

// On 64-bit the kernel sets up the siginfo_t and ucontext_t regardless of SA_SIGINFO set.
// This allows the application to /always/ get the siginfo and ucontext even if it didn't set this flag.
//
Expand All @@ -345,7 +337,7 @@ uint64_t SignalDelegator::SetupFrame_x64(FEXCore::Core::InternalThreadState* Thr

uint64_t HostStackLocation = NewGuestSP;

if (IsAVXEnabled) {
if (SupportsAVX) {
NewGuestSP -= sizeof(FEXCore::x86_64::xstate);
NewGuestSP = FEXCore::AlignDown(NewGuestSP, alignof(FEXCore::x86_64::xstate));
} else {
Expand Down Expand Up @@ -378,7 +370,7 @@ uint64_t SignalDelegator::SetupFrame_x64(FEXCore::Core::InternalThreadState* Thr
// Pointer to where the fpreg memory is
guest_uctx->uc_mcontext.fpregs = reinterpret_cast<FEXCore::x86_64::_libc_fpstate*>(FPStateLocation);
auto* xstate = reinterpret_cast<FEXCore::x86_64::xstate*>(FPStateLocation);
SetXStateInfo(xstate, IsAVXEnabled);
SetXStateInfo(xstate, SupportsAVX);

guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_RIP] = ContextBackup->OriginalRIP;
guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_EFL] = eflags;
Expand Down Expand Up @@ -427,7 +419,7 @@ uint64_t SignalDelegator::SetupFrame_x64(FEXCore::Core::InternalThreadState* Thr
// Copy float registers
memcpy(fpstate->_st, Frame->State.mm, sizeof(Frame->State.mm));

if (IsAVXEnabled) {
if (SupportsAVX) {
CTX->ReconstructXMMRegisters(Thread, fpstate->_xmm, xstate->ymmh.ymmh_space);
} else {
CTX->ReconstructXMMRegisters(Thread, fpstate->_xmm, nullptr);
Expand Down Expand Up @@ -472,15 +464,14 @@ uint64_t SignalDelegator::SetupFrame_ia32(FEXCore::Core::InternalThreadState* Th
FEXCore::Core::CpuStateFrame* Frame, int Signal, siginfo_t* HostSigInfo, void* ucontext,
GuestSigAction* GuestAction, stack_t* GuestStack, uint64_t NewGuestSP, const uint32_t eflags) {

const bool IsAVXEnabled = Config.SupportsAVX;
const uint64_t SignalReturn = reinterpret_cast<uint64_t>(VDSOPointers.VDSO_kernel_sigreturn);

NewGuestSP -= sizeof(uint64_t);
NewGuestSP = FEXCore::AlignDown(NewGuestSP, alignof(uint64_t));

uint64_t HostStackLocation = NewGuestSP;

if (IsAVXEnabled) {
if (SupportsAVX) {
NewGuestSP -= sizeof(FEXCore::x86::xstate);
NewGuestSP = FEXCore::AlignDown(NewGuestSP, alignof(FEXCore::x86::xstate));
} else {
Expand All @@ -505,7 +496,7 @@ uint64_t SignalDelegator::SetupFrame_ia32(FEXCore::Core::InternalThreadState* Th
// Pointer to where the fpreg memory is
guest_uctx->sc.fpstate = static_cast<uint32_t>(FPStateLocation);
auto* xstate = reinterpret_cast<FEXCore::x86::xstate*>(FPStateLocation);
SetXStateInfo(xstate, IsAVXEnabled);
SetXStateInfo(xstate, SupportsAVX);

guest_uctx->sc.cs = Frame->State.cs_idx;
guest_uctx->sc.ds = Frame->State.ds_idx;
Expand Down Expand Up @@ -549,7 +540,7 @@ uint64_t SignalDelegator::SetupFrame_ia32(FEXCore::Core::InternalThreadState* Th
// Extended XMM state
fpstate->status = FEXCore::x86::fpstate_magic::MAGIC_XFPSTATE;

if (IsAVXEnabled) {
if (SupportsAVX) {
CTX->ReconstructXMMRegisters(Thread, fpstate->_xmm, xstate->ymmh.ymmh_space);
} else {
CTX->ReconstructXMMRegisters(Thread, fpstate->_xmm, nullptr);
Expand Down Expand Up @@ -601,15 +592,14 @@ uint64_t SignalDelegator::SetupRTFrame_ia32(FEXCore::Core::InternalThreadState*
FEXCore::Core::CpuStateFrame* Frame, int Signal, siginfo_t* HostSigInfo, void* ucontext,
GuestSigAction* GuestAction, stack_t* GuestStack, uint64_t NewGuestSP, const uint32_t eflags) {

const bool IsAVXEnabled = Config.SupportsAVX;
const uint64_t SignalReturn = reinterpret_cast<uint64_t>(VDSOPointers.VDSO_kernel_rt_sigreturn);

NewGuestSP -= sizeof(uint64_t);
NewGuestSP = FEXCore::AlignDown(NewGuestSP, alignof(uint64_t));

uint64_t HostStackLocation = NewGuestSP;

if (IsAVXEnabled) {
if (SupportsAVX) {
NewGuestSP -= sizeof(FEXCore::x86::xstate);
NewGuestSP = FEXCore::AlignDown(NewGuestSP, alignof(FEXCore::x86::xstate));
} else {
Expand Down Expand Up @@ -638,7 +628,7 @@ uint64_t SignalDelegator::SetupRTFrame_ia32(FEXCore::Core::InternalThreadState*
// Pointer to where the fpreg memory is
guest_uctx->uc.uc_mcontext.fpregs = static_cast<uint32_t>(FPStateLocation);
auto* xstate = reinterpret_cast<FEXCore::x86::xstate*>(FPStateLocation);
SetXStateInfo(xstate, IsAVXEnabled);
SetXStateInfo(xstate, SupportsAVX);

guest_uctx->uc.uc_mcontext.gregs[FEXCore::x86::FEX_REG_CS] = Frame->State.cs_idx;
guest_uctx->uc.uc_mcontext.gregs[FEXCore::x86::FEX_REG_DS] = Frame->State.ds_idx;
Expand Down Expand Up @@ -684,7 +674,7 @@ uint64_t SignalDelegator::SetupRTFrame_ia32(FEXCore::Core::InternalThreadState*
// Extended XMM state
fpstate->status = FEXCore::x86::fpstate_magic::MAGIC_XFPSTATE;

if (IsAVXEnabled) {
if (SupportsAVX) {
CTX->ReconstructXMMRegisters(Thread, fpstate->_xmm, xstate->ymmh.ymmh_space);
} else {
CTX->ReconstructXMMRegisters(Thread, fpstate->_xmm, nullptr);
Expand Down
2 changes: 1 addition & 1 deletion Source/Tools/TestHarnessRunner/TestHarnessRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ int main(int argc, char** argv, char** const envp) {
auto CTX = FEXCore::Context::Context::CreateNewContext(HostFeatures);

#ifndef _WIN32
auto SignalDelegation = FEX::HLE::CreateSignalDelegator(CTX.get(), {});
auto SignalDelegation = FEX::HLE::CreateSignalDelegator(CTX.get(), {}, HostFeatures.SupportsAVX);
#else
// Enable exit on HLT while Wine's longjump is broken.
//
Expand Down

0 comments on commit 9100235

Please sign in to comment.