Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SignalDelegator: Let the frontend inform AVX support #4077

Merged
merged 1 commit into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions FEXCore/Source/Interface/Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,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
Loading