Merge pull request #705 from FEX-Emu/skmp/mmap-cache-flushing

Flush IR/Code cache on mmap, mmunmap & mprot
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis authored and GitHub committed 2021-03-03 12:59:29 +02:00
commit cc2b2cf346
13 files changed
+100 -33

No files matched your search

+1 -1
View File
@@ -34,7 +34,7 @@ namespace FEXCore::Config {
CTX->Config.TSOEnabled = Config != 0;
break;
case FEXCore::Config::CONFIG_SMC_CHECKS:
CTX->Config.SMCChecks = Config != 0;
CTX->Config.SMCChecks = static_cast<FEXCore::Config::ConfigSMCChecks>(Config);
break;
case FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS:
CTX->Config.ABILocalFlags = Config != 0;
+2 -2
View File
@@ -68,7 +68,7 @@ namespace FEXCore::Context {
bool Is64BitMode {true};
bool TSOEnabled {true};
bool SMCChecks {false};
FEXCore::Config::ConfigSMCChecks SMCChecks {FEXCore::Config::CONFIG_SMC_MMAN};
bool ABILocalFlags {false};
bool ABINoPF {false};
@@ -209,7 +209,7 @@ namespace FEXCore::Context {
void ExecutionThread(FEXCore::Core::InternalThreadState *Thread);
void NotifyPause();
void AddBlockMapping(FEXCore::Core::InternalThreadState *Thread, uint64_t Address, void *Ptr);
void AddBlockMapping(FEXCore::Core::InternalThreadState *Thread, uint64_t Address, void *Ptr, uint64_t Start, uint64_t Length);
FEXCore::CodeLoader *LocalLoader{};
+22 -7
View File
@@ -607,8 +607,8 @@ namespace FEXCore::Context {
return Thread;
}
void Context::AddBlockMapping(FEXCore::Core::InternalThreadState *Thread, uint64_t Address, void *Ptr) {
Thread->LookupCache->AddBlockMapping(Address, Ptr);
void Context::AddBlockMapping(FEXCore::Core::InternalThreadState *Thread, uint64_t Address, void *Ptr, uint64_t Start, uint64_t Length) {
Thread->LookupCache->AddBlockMapping(Address, Ptr, Start, Length);
}
void Context::ClearCodeCache(FEXCore::Core::InternalThreadState *Thread, bool AlsoClearIRCache) {
@@ -670,7 +670,7 @@ namespace FEXCore::Context {
TableInfo = Block.DecodedInstructions[i].TableInfo;
DecodedInfo = &Block.DecodedInstructions[i];
if (Config.SMCChecks) {
if (Config.SMCChecks == FEXCore::Config::CONFIG_SMC_FULL) {
auto ExistingCodePtr = reinterpret_cast<uint64_t*>(Block.Entry + BlockInstructionsLength);
auto CodeChanged = Thread->OpDispatcher->_ValidateCode(ExistingCodePtr[0], ExistingCodePtr[1], (uintptr_t)ExistingCodePtr - GuestRIP, DecodedInfo->InstSize);
@@ -853,7 +853,8 @@ namespace FEXCore::Context {
if (AOTEntry != Mod->end()) {
// verify hash
auto hash = fasthash64((void*)(AOTEntry->second.start + file->second.Start - file->second.Offset), AOTEntry->second.len, 0);
auto MappedStart = AOTEntry->second.start + file->second.Start - file->second.Offset;
auto hash = fasthash64((void*)MappedStart, AOTEntry->second.len, 0);
if (hash == AOTEntry->second.crc) {
IRList = AOTEntry->second.IR;
//LogMan::Msg::D("using %s + %lx -> %lx\n", file->second.fileid.c_str(), AOTEntry->first, GuestRIP);
@@ -862,7 +863,7 @@ namespace FEXCore::Context {
RAData = AOTEntry->second.RAData;
DebugData = new FEXCore::Core::DebugData();
StartAddr = AOTEntry->second.start;
StartAddr = MappedStart;
Length = AOTEntry->second.len;
GeneratedIR = true;
@@ -1117,7 +1118,7 @@ namespace FEXCore::Context {
--Thread->CompileBlockReentrantRefCount;
// Insert to lookup cache
AddBlockMapping(Thread, GuestRIP, CodePtr);
AddBlockMapping(Thread, GuestRIP, CodePtr, StartAddr, Length);
return (uintptr_t)CodePtr;
@@ -1177,6 +1178,20 @@ namespace FEXCore::Context {
SignalDelegation->UninstallTLSState(Thread);
}
void FlushCodeRange(FEXCore::Core::InternalThreadState *Thread, uint64_t Start, uint64_t Length) {
if (Thread->CTX->Config.SMCChecks == FEXCore::Config::CONFIG_SMC_MMAN) {
auto lower = Thread->LookupCache->CodePages.lower_bound(Start >> 12);
auto upper = Thread->LookupCache->CodePages.upper_bound((Start + Length) >> 12);
for (auto it = lower; it != upper; it++) {
for (auto Address: it->second)
Context::RemoveCodeEntry(Thread, Address);
it->second.clear();
}
}
}
void Context::RemoveCodeEntry(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestRIP) {
Thread->LocalIRCache.erase(GuestRIP);
Thread->LookupCache->Erase(GuestRIP);
@@ -1248,7 +1263,7 @@ namespace FEXCore::Context {
auto fileid = base_filename + "-" + std::to_string(filename_hash) + "-";
// append optimization flags to the fileid
fileid += Config.SMCChecks ? "S" : "s";
fileid += (Config.SMCChecks == FEXCore::Config::CONFIG_SMC_FULL) ? "S" : "s";
fileid += Config.TSOEnabled ? "T" : "t";
fileid += Config.ABILocalFlags ? "L" : "l";
fileid += Config.ABINoPF ? "p" : "P";
+8 -1
View File
@@ -35,10 +35,16 @@ public:
}
}
void AddBlockMapping(uint64_t Address, void *HostCode) {
std::map<uint64_t, std::vector<uint64_t>> CodePages;
void AddBlockMapping(uint64_t Address, void *HostCode, uint64_t Start, uint64_t Length) {
auto InsertPoint = BlockList.emplace(Address, (uintptr_t)HostCode);
LogMan::Throw::A(InsertPoint.second == true, "Dupplicate block mapping added");
for (auto CurrentPage = Start >> 12, EndPage = (Start + Length) >> 12; CurrentPage <= EndPage; CurrentPage++) {
CodePages[CurrentPage].push_back(Address);
}
// no need to update L1 or L2, they will get updated on first lookup
}
@@ -197,6 +203,7 @@ private:
}
};
std::map<BlockLinkTag, std::function<void()>> BlockLinks;
std::map<uint64_t, uint64_t> BlockList;
+6
View File
@@ -44,6 +44,12 @@ namespace FEXCore::Config {
CONFIG_CUSTOM,
};
enum ConfigSMCChecks {
CONFIG_SMC_NONE,
CONFIG_SMC_MMAN,
CONFIG_SMC_FULL,
};
void SetConfig(FEXCore::Context::Context *CTX, ConfigOption Option, uint64_t Config);
void SetConfig(FEXCore::Context::Context *CTX, ConfigOption Option, std::string const &Config);
uint64_t GetConfig(FEXCore::Context::Context *CTX, ConfigOption Option);
+1
View File
@@ -238,4 +238,5 @@ namespace FEXCore::Context {
void RemoveNamedRegion(FEXCore::Context::Context *CTX, uintptr_t Base, uintptr_t Length);
void SetAOTIRLoader(FEXCore::Context::Context *CTX, std::function<std::unique_ptr<std::istream>(const std::string&)> CacheReader);
bool WriteAOTIR(FEXCore::Context::Context *CTX, std::function<std::unique_ptr<std::ostream>(const std::string&)> CacheWriter);
void FlushCodeRange(FEXCore::Core::InternalThreadState *Thread, uint64_t Start, uint64_t Length);
}
+11 -6
View File
@@ -66,11 +66,11 @@ namespace FEX::ArgLoader {
.help("Number of physical hardware threads to tell the process we have")
.set_default(1);
CPUGroup.add_option("--smc-full-checks")
CPUGroup.add_option("--smc-checks")
.dest("SMCChecks")
.action("store_true")
.help("Checks code for modification before execution. Slow.")
.set_default(false);
.choices({"none", "mman", "full"})
.help("Checks code for modification before execution.\n\tnone: No checks\n\tmman: Invalidate on mmap, mprotect, munmap\n\tfull: Validate code before every run (slow)")
.set_default("mman");
CPUGroup.add_option("--unsafe-no-tso")
.dest("TSOEnabled")
@@ -229,8 +229,13 @@ namespace FEX::ArgLoader {
}
if (Options.is_set_by_user("SMCChecks")) {
bool SMCChecks = Options.get("SMCChecks");
Set(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, std::to_string(SMCChecks));
auto SMCChecks = Options["SMCChecks"];
if (SMCChecks == "none")
Set(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, "0");
else if (SMCChecks == "mman")
Set(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, "1");
else if (SMCChecks == "full")
Set(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, "2");
}
if (Options.is_set_by_user("AbiLocalFlags")) {
bool AbiLocalFlags = Options.get("AbiLocalFlags");
+1 -1
View File
@@ -205,7 +205,7 @@ int main(int argc, char **argv, char **const envp) {
FEXCore::Config::Value<std::string> OutputLog{FEXCore::Config::CONFIG_OUTPUTLOG, "stderr"};
FEXCore::Config::Value<std::string> DumpIR{FEXCore::Config::CONFIG_DUMPIR, "no"};
FEXCore::Config::Value<bool> TSOEnabledConfig{FEXCore::Config::CONFIG_TSO_ENABLED, true};
FEXCore::Config::Value<bool> SMCChecksConfig{FEXCore::Config::CONFIG_SMC_CHECKS, false};
FEXCore::Config::Value<uint8_t> SMCChecksConfig{FEXCore::Config::CONFIG_SMC_CHECKS, FEXCore::Config::CONFIG_SMC_MMAN};
FEXCore::Config::Value<bool> ABILocalFlags{FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS, false};
FEXCore::Config::Value<bool> AbiNoPF{FEXCore::Config::CONFIG_ABI_NO_PF, false};
FEXCore::Config::Value<bool> AOTIRCapture{FEXCore::Config::CONFIG_AOTIR_GENERATE, false};
+16 -6
View File
@@ -24,10 +24,13 @@ namespace FEX::HLE::x32 {
auto Result = (uint64_t)static_cast<FEX::HLE::x32::x32SyscallHandler*>(FEX::HLE::_SyscallHandler)->GetAllocator()->
mmap(reinterpret_cast<void*>(addr), length, prot,flags, fd, offset);
if (Result != -1 && !(flags & MAP_ANONYMOUS)) {
auto filename = get_fdpath(fd);
if (Result != -1) {
if (!(flags & MAP_ANONYMOUS)) {
auto filename = get_fdpath(fd);
FEXCore::Context::AddNamedRegion(Thread->CTX, Result, length, offset, filename);
FEXCore::Context::AddNamedRegion(Thread->CTX, Result, length, offset, filename);
}
FEXCore::Context::FlushCodeRange(Thread, (uintptr_t)Result, length);
}
return Result;
@@ -37,10 +40,13 @@ namespace FEX::HLE::x32 {
auto Result = (uint64_t)static_cast<FEX::HLE::x32::x32SyscallHandler*>(FEX::HLE::_SyscallHandler)->GetAllocator()->
mmap(reinterpret_cast<void*>(addr), length, prot,flags, fd, (uint64_t)pgoffset * 0x1000);
if (Result != -1 && !(flags & MAP_ANONYMOUS)) {
auto filename = get_fdpath(fd);
if (Result != -1) {
if (!(flags & MAP_ANONYMOUS)) {
auto filename = get_fdpath(fd);
FEXCore::Context::AddNamedRegion(Thread->CTX, Result, length, pgoffset * 0x1000, filename);
FEXCore::Context::AddNamedRegion(Thread->CTX, Result, length, pgoffset * 0x1000, filename);
}
FEXCore::Context::FlushCodeRange(Thread, (uintptr_t)Result, length);
}
return Result;
@@ -51,12 +57,16 @@ namespace FEX::HLE::x32 {
munmap(addr, length);
if (Result != -1) {
FEXCore::Context::RemoveNamedRegion(Thread->CTX, (uintptr_t)addr, length);
FEXCore::Context::FlushCodeRange(Thread, (uintptr_t)addr, length);
}
return Result;
});
REGISTER_SYSCALL_IMPL_X32(mprotect, [](FEXCore::Core::InternalThreadState *Thread, void *addr, uint32_t len, int prot) -> uint64_t {
uint64_t Result = ::mprotect(addr, len, prot);
if (Result != -1 && prot & PROT_EXEC) {
FEXCore::Context::FlushCodeRange(Thread, (uintptr_t)addr, len);
}
SYSCALL_ERRNO();
});
+10 -3
View File
@@ -25,6 +25,7 @@ namespace FEX::HLE::x64 {
uint64_t Result = ::munmap(addr, length);
if (Result != -1) {
FEXCore::Context::RemoveNamedRegion(Thread->CTX, (uintptr_t)addr, length);
FEXCore::Context::FlushCodeRange(Thread, (uintptr_t)addr, length);
}
SYSCALL_ERRNO();
});
@@ -32,10 +33,13 @@ namespace FEX::HLE::x64 {
REGISTER_SYSCALL_IMPL_X64(mmap, [](FEXCore::Core::InternalThreadState *Thread, void *addr, size_t length, int prot, int flags, int fd, off_t offset) -> uint64_t {
static FEXCore::Config::Value<bool> AOTIRLoad(FEXCore::Config::CONFIG_AOTIR_LOAD, false);
uint64_t Result = reinterpret_cast<uint64_t>(::mmap(addr, length, prot, flags, fd, offset));
if (Result != -1 && !(flags & MAP_ANONYMOUS)) {
auto filename = get_fdpath(fd);
if (Result != -1) {
if (!(flags & MAP_ANONYMOUS)) {
auto filename = get_fdpath(fd);
FEXCore::Context::AddNamedRegion(Thread->CTX, Result, length, offset, filename);
FEXCore::Context::AddNamedRegion(Thread->CTX, Result, length, offset, filename);
}
FEXCore::Context::FlushCodeRange(Thread, (uintptr_t)Result, length);
}
SYSCALL_ERRNO();
});
@@ -47,6 +51,9 @@ namespace FEX::HLE::x64 {
REGISTER_SYSCALL_IMPL_X64(mprotect, [](FEXCore::Core::InternalThreadState *Thread, void *addr, size_t len, int prot) -> uint64_t {
uint64_t Result = ::mprotect(addr, len, prot);
if (Result != -1 && prot & PROT_EXEC) {
FEXCore::Context::FlushCodeRange(Thread, (uintptr_t)addr, len);
}
SYSCALL_ERRNO();
});
+1 -1
View File
@@ -71,7 +71,7 @@ int main(int argc, char **argv, char **const envp) {
FEXCore::Config::Value<std::string> OutputLog{FEXCore::Config::CONFIG_OUTPUTLOG, "stderr"};
FEXCore::Config::Value<std::string> DumpIR{FEXCore::Config::CONFIG_DUMPIR, "no"};
FEXCore::Config::Value<bool> TSOEnabledConfig{FEXCore::Config::CONFIG_TSO_ENABLED, true};
FEXCore::Config::Value<bool> SMCChecksConfig{FEXCore::Config::CONFIG_SMC_CHECKS, false};
FEXCore::Config::Value<uint8_t> SMCChecksConfig{FEXCore::Config::CONFIG_SMC_CHECKS, FEXCore::Config::CONFIG_SMC_MMAN};
FEXCore::Config::Value<bool> ABILocalFlags{FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS, false};
FEXCore::Config::Value<bool> AbiNoPF{FEXCore::Config::CONFIG_ABI_NO_PF, false};
+20 -4
View File
@@ -301,11 +301,27 @@ namespace {
ConfigChanged = true;
}
ImGui::Text("SMC Checks: ");
int SMCChecks = FEXCore::Config::CONFIG_SMC_MMAN;
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS);
bool SMCChecks = Value.has_value() && **Value == "1";
if (ImGui::Checkbox("SMC Checks", &SMCChecks)) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, SMCChecks ? "1" : "0");
ConfigChanged = true;
if (Value.has_value()) {
if (**Value == "0") {
SMCChecks = FEXCore::Config::CONFIG_SMC_NONE;
} else if (**Value == "1") {
SMCChecks = FEXCore::Config::CONFIG_SMC_MMAN;
} else if (**Value == "2") {
SMCChecks = FEXCore::Config::CONFIG_SMC_FULL;
}
}
bool SMCChanged = false;
SMCChanged |= ImGui::RadioButton("None", &SMCChecks, FEXCore::Config::CONFIG_SMC_NONE); ImGui::SameLine();
SMCChanged |= ImGui::RadioButton("MMan", &SMCChecks, FEXCore::Config::CONFIG_SMC_MMAN); ImGui::SameLine();
SMCChanged |= ImGui::RadioButton("Full", &SMCChecks, FEXCore::Config::CONFIG_SMC_FULL);
if (SMCChanged) {
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_SMC_CHECKS, std::to_string(SMCChecks));
}
Value = LoadedConfig->Get(FEXCore::Config::ConfigOption::CONFIG_ABI_LOCAL_FLAGS);
+1 -1
View File
@@ -74,7 +74,7 @@ foreach(ASM_SRC ${ASM_SOURCES})
string(REPLACE " " ";" ARGS_LIST ${ARGS})
if (TEST_NAME MATCHES "SelfModifyingCode")
list(APPEND ARGS_LIST "--smc-full-checks")
list(APPEND ARGS_LIST "--smc-checks=full")
endif()
add_test(NAME ${TEST_NAME}