mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-13 11:00:29 +02:00
Implement support for additional provided volatile metadata
Only wired up for wow64 and arm64ec. Gives more granular control over TSO enabling and disabling. Matches arm64ec volatile metadata except with one more additional feature that whole modules can be disabled at a time. Once we know the mapped size of files in Linux then we'll be able to do the same thing there, but there's not a full mechanism wired up for that yet.
This commit is contained in:
7 files changed
+269
-13
No files matched your search
@@ -43,6 +43,7 @@ $end_info$
|
||||
#include "DummyHandlers.h"
|
||||
#include "BTInterface.h"
|
||||
#include "Windows/Common/SHMStats.h"
|
||||
#include "Windows/Common/VolatileMetadata.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
@@ -80,6 +81,7 @@ void* WineSyscallDispatcher;
|
||||
uint64_t WineNtContinueSyscallId;
|
||||
uint64_t WineNtAllocateVirtualMemorySyscallId;
|
||||
uint64_t WineNtProtectVirtualMemorySyscallId;
|
||||
static fextl::unordered_map<fextl::string, FEX::VolatileMetadata::ExtendedVolatileMetadata> ExtendedMetaData {};
|
||||
|
||||
NTSTATUS NtContinueNative(ARM64_NT_CONTEXT* NativeContext, BOOLEAN Alert);
|
||||
NTSTATUS NtAllocateVirtualMemoryNative(HANDLE, PVOID*, ULONG_PTR, SIZE_T*, ULONG, ULONG);
|
||||
@@ -267,11 +269,10 @@ void InitSyscalls() {
|
||||
PatchCallChecker();
|
||||
}
|
||||
|
||||
void LoadImageVolatileMetadata(uint64_t Address) {
|
||||
const auto Module = reinterpret_cast<HMODULE>(Address);
|
||||
IMAGE_NT_HEADERS* Nt = RtlImageNtHeader(Module);
|
||||
uint64_t EndAddress = Address + Nt->OptionalHeader.SizeOfImage;
|
||||
void LoadImageVolatileMetadata(fextl::set<uint64_t>& VolatileInstructions, FEXCore::IntervalList<uint64_t>& VolatileValidRanges,
|
||||
HMODULE Module, IMAGE_NT_HEADERS* Nt, uint64_t Address, uint64_t EndAddress) {
|
||||
ULONG Size;
|
||||
|
||||
const auto* LoadConfig =
|
||||
reinterpret_cast<_IMAGE_LOAD_CONFIG_DIRECTORY64*>(RtlImageDirectoryEntryToData(Module, true, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &Size));
|
||||
if (!LoadConfig || LoadConfig->Size <= offsetof(_IMAGE_LOAD_CONFIG_DIRECTORY64, VolatileMetadataPointer)) {
|
||||
@@ -288,7 +289,6 @@ void LoadImageVolatileMetadata(uint64_t Address) {
|
||||
return;
|
||||
}
|
||||
|
||||
fextl::set<uint64_t> VolatileInstructions;
|
||||
const auto* VolatileAccessTableBegin = reinterpret_cast<IMAGE_VOLATILE_RVA_METADATA*>(Address + VolatileMetadata->VolatileAccessTable);
|
||||
const auto* VolatileAccessTableEnd =
|
||||
VolatileAccessTableBegin + (VolatileMetadata->VolatileAccessTableSize / sizeof(IMAGE_VOLATILE_RVA_METADATA));
|
||||
@@ -296,13 +296,31 @@ void LoadImageVolatileMetadata(uint64_t Address) {
|
||||
VolatileInstructions.emplace(Address + It->Rva);
|
||||
}
|
||||
|
||||
FEXCore::IntervalList<uint64_t> VolatileValidRanges;
|
||||
const auto* VolatileInfoRangeTableBegin = reinterpret_cast<IMAGE_VOLATILE_RANGE_METADATA*>(Address + VolatileMetadata->VolatileInfoRangeTable);
|
||||
const auto* VolatileInfoRangeTableEnd =
|
||||
VolatileInfoRangeTableBegin + (VolatileMetadata->VolatileInfoRangeTableSize / sizeof(IMAGE_VOLATILE_RANGE_METADATA));
|
||||
for (auto It = VolatileInfoRangeTableBegin; It != VolatileInfoRangeTableEnd; It++) {
|
||||
VolatileValidRanges.Insert({Address + It->Rva, Address + It->Rva + It->Size});
|
||||
}
|
||||
}
|
||||
|
||||
void LoadImageVolatileMetadata(const fextl::string& ModuleName, uint64_t Address) {
|
||||
const auto Module = reinterpret_cast<HMODULE>(Address);
|
||||
IMAGE_NT_HEADERS* Nt = RtlImageNtHeader(Module);
|
||||
uint64_t EndAddress = Address + Nt->OptionalHeader.SizeOfImage;
|
||||
|
||||
fextl::set<uint64_t> VolatileInstructions {};
|
||||
FEXCore::IntervalList<uint64_t> VolatileValidRanges {};
|
||||
LoadImageVolatileMetadata(VolatileInstructions, VolatileValidRanges, Module, Nt, Address, EndAddress);
|
||||
|
||||
auto it = ExtendedMetaData.find(ModuleName);
|
||||
if (it != ExtendedMetaData.end()) {
|
||||
FEX::Windows::ApplyFEXExtendedVolatileMetadata(it->second, VolatileInstructions, VolatileValidRanges, Address, EndAddress);
|
||||
}
|
||||
|
||||
if (VolatileInstructions.empty() && VolatileValidRanges.Empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LogMan::Msg::DFmt("Loaded volatile metadata for {:X}: {} entries", Address, VolatileInstructions.size());
|
||||
std::scoped_lock Lock(CTX->GetCodeInvalidationMutex());
|
||||
@@ -314,7 +332,7 @@ void HandleImageMap(uint64_t Address) {
|
||||
LogMan::Msg::DFmt("Load module {}: {:X}", ModuleName, Address);
|
||||
FEX_CONFIG_OPT(VolatileMetadata, VOLATILEMETADATA);
|
||||
if (VolatileMetadata) {
|
||||
LoadImageVolatileMetadata(Address);
|
||||
LoadImageVolatileMetadata(ModuleName, Address);
|
||||
}
|
||||
InvalidationTracker->HandleImageMap(ModuleName, Address);
|
||||
}
|
||||
@@ -630,6 +648,9 @@ NTSTATUS ProcessInit() {
|
||||
|
||||
FEXCore::Context::InitializeStaticTables(FEXCore::Context::MODE_64BIT);
|
||||
|
||||
FEX_CONFIG_OPT(ExtendedVolatileMetadataConfig, EXTENDEDVOLATILEMETADATA);
|
||||
ExtendedMetaData = FEX::VolatileMetadata::ParseExtendedVolatileMetadata(ExtendedVolatileMetadataConfig());
|
||||
|
||||
SignalDelegator = fextl::make_unique<FEX::DummyHandlers::DummySignalDelegator>();
|
||||
SyscallHandler = fextl::make_unique<Exception::ECSyscallHandler>();
|
||||
Exception::HandlerConfig.emplace();
|
||||
@@ -941,7 +962,7 @@ NTSTATUS ThreadInit() {
|
||||
auto NewSegments = new FEXCore::Core::CPUState::gdt_segment[32];
|
||||
|
||||
// Setup initial code-segment GDT
|
||||
auto &GDT = NewSegments[FEXCore::Core::CPUState::DEFAULT_USER_CS];
|
||||
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
|
||||
@@ -1033,7 +1054,7 @@ NTSTATUS ThreadTerm(HANDLE Thread, LONG ExitCode) {
|
||||
auto ThreadState = CPUArea.ThreadState();
|
||||
|
||||
// GDT and LDT are mirrored, only free one.
|
||||
delete [] ThreadState->CurrentFrame->State.segment_arrays[FEXCore::Core::CPUState::SEGMENT_ARRAY_INDEX_GDT];
|
||||
delete[] ThreadState->CurrentFrame->State.segment_arrays[FEXCore::Core::CPUState::SEGMENT_ARRAY_INDEX_GDT];
|
||||
|
||||
FEX::Windows::CallRetStack::DestroyThread(ThreadState);
|
||||
CTX->DestroyThread(ThreadState);
|
||||
|
||||
Reference in new issue
Block a user