FEXCore: Move LDT/GDT management to the frontend

This will allow the frontend to manage LDT and GDT so that Linux will be
able to install 32-bit code segments.
This commit is contained in:
Ryan Houdek committed 2025-08-18 14:03:51 -07:00
1 parent 8d1042859d
commit 25a0752e58
5 files changed
+91 -30

No files matched your search

+26 -3
View File
@@ -644,6 +644,7 @@ NTSTATUS ProcessInit() {
CTX->SetSignalDelegator(SignalDelegator.get());
CTX->SetSyscallHandler(SyscallHandler.get());
CTX->InitCore();
InvalidationTracker.emplace(*CTX, Threads);
HandleImageMap(NtDllBase);
@@ -924,6 +925,24 @@ NTSTATUS ThreadInit() {
auto* Thread = CTX->CreateThread(0, 0);
// Default segment setup.
auto Frame = Thread->CurrentFrame;
auto NewSegments = new FEXCore::Core::CPUState::gdt_segment[32];
// Setup initial code-segment GDT
auto &GDT = NewSegments[FEXCore::Core::CPUState::DEFAULT_USER_CS];
FEXCore::Core::CPUState::SetGDTBase(&GDT, 0);
FEXCore::Core::CPUState::SetGDTLimit(&GDT, 0xF'FFFFU);
GDT.L = 1; // L = Long Mode = 64-bit
GDT.D = 0; // D = Default Operand SIze = Reserved
Frame->State.segment_arrays[FEXCore::Core::CPUState::SEGMENT_ARRAY_INDEX_GDT] = &NewSegments[0];
// TODO: LDTs are currently unsupported, mirror them to GDT.
Frame->State.segment_arrays[FEXCore::Core::CPUState::SEGMENT_ARRAY_INDEX_LDT] = &NewSegments[0];
Frame->State.cs_idx = FEXCore::Core::CPUState::DEFAULT_USER_CS << 3;
Frame->State.cs_cached = FEXCore::Core::CPUState::CalculateGDTBase(GDT);
FEX::Windows::CallRetStack::InitializeThread(Thread);
Thread->CurrentFrame->Pointers.Common.ExitFunctionEC = reinterpret_cast<uintptr_t>(&ExitFunctionEC);
CPUArea.StateFrame() = Thread->CurrentFrame;
@@ -935,7 +954,7 @@ NTSTATUS ThreadInit() {
CPUArea.DispatcherLoopTopEnterECFillSRA() = EnterECFillSRA;
CPUArea.ContextAmd64() = {.ContextFlags = CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT,
.AMD64_SegCs = 0x33,
.AMD64_SegCs = (FEXCore::Core::CPUState::DEFAULT_USER_CS << 3) | 3,
.AMD64_SegDs = 0x2b,
.AMD64_SegEs = 0x2b,
.AMD64_SegFs = 0x53,
@@ -1000,9 +1019,13 @@ NTSTATUS ThreadTerm(HANDLE Thread, LONG ExitCode) {
StatAllocHandler->DeallocateSlot(CPUArea.ThreadState()->ThreadStats);
}
}
auto ThreadState = CPUArea.ThreadState();
FEX::Windows::CallRetStack::DestroyThread(CPUArea.ThreadState());
CTX->DestroyThread(CPUArea.ThreadState());
// GDT and LDT are mirrored, only free one.
delete [] ThreadState->CurrentFrame->State.segment_arrays[FEXCore::Core::CPUState::SEGMENT_ARRAY_INDEX_GDT];
FEX::Windows::CallRetStack::DestroyThread(ThreadState);
CTX->DestroyThread(ThreadState);
::VirtualFree(reinterpret_cast<void*>(CPUArea.EmulatorStackLimit()), 0, MEM_RELEASE);
if (ThreadTID == GetCurrentThreadId()) {
FEX::Windows::DeinitCRTThread();