Files
FEX-Emu--FEX/External/FEXCore/Source/Interface/Config/Config.cpp
T
Ryan Houdek 37983006f0 Moves FEXCore's SignalDelegator and SyscallHandler to the frontend
Sadly these things can't be split without breaking functionality so it
turns in to a bit of a mess.

SyscallHandler is very much something that is a Linux only construct and
shouldn't be in FEXCore itself. Lets the frontend register a
Syscallhandler with FEXCore. FEXCore itself is then aware of the current
syscall ABI and handles the ABI in an optimal fashion.
So it is not a 100% clean break otherwise we would lose performance.

The SignalDelegator then needs to move to the frontend since the
SyscallHandler requires it for signal based syscalls.
The CPU backend signal handling still needs to happen in FEXCore because
it is a very tight coupling with the CPU backend.
Once we need to support more Signal handling we can give the backends
cleaner support to select which specific OS handler to handle.
2020-12-13 22:38:04 -08:00

256 lines
7.5 KiB
C++

#include "Common/StringConv.h"
#include <FEXCore/Utils/LogManager.h>
#include "Interface/Context/Context.h"
#include <FEXCore/Config/Config.h>
namespace FEXCore::Config {
void SetConfig(FEXCore::Context::Context *CTX, ConfigOption Option, uint64_t Config) {
switch (Option) {
case FEXCore::Config::CONFIG_MULTIBLOCK:
CTX->Config.Multiblock = Config != 0;
break;
case FEXCore::Config::CONFIG_MAXBLOCKINST:
CTX->Config.MaxInstPerBlock = Config;
break;
case FEXCore::Config::CONFIG_DEFAULTCORE:
CTX->Config.Core = static_cast<FEXCore::Config::ConfigCore>(Config);
break;
case FEXCore::Config::CONFIG_VIRTUALMEMSIZE:
CTX->Config.VirtualMemSize = Config;
break;
case FEXCore::Config::CONFIG_SINGLESTEP:
CTX->Config.RunningMode = Config != 0 ? FEXCore::Context::CoreRunningMode::MODE_SINGLESTEP : FEXCore::Context::CoreRunningMode::MODE_RUN;
break;
case FEXCore::Config::CONFIG_GDBSERVER:
Config != 0 ? CTX->StartGdbServer() : CTX->StopGdbServer();
break;
case FEXCore::Config::CONFIG_IS64BIT_MODE:
CTX->Config.Is64BitMode = Config != 0;
break;
case FEXCore::Config::CONFIG_TSO_ENABLED:
CTX->Config.TSOEnabled = Config != 0;
break;
case FEXCore::Config::CONFIG_SMC_CHECKS:
CTX->Config.SMCChecks = Config != 0;
break;
case FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS:
CTX->Config.ABILocalFlags = Config != 0;
break;
case FEXCore::Config::CONFIG_ABI_NO_PF:
CTX->Config.ABINoPF = Config != 0;
break;
default: LogMan::Msg::A("Unknown configuration option");
}
}
void SetConfig(FEXCore::Context::Context *CTX, ConfigOption Option, std::string const &Config) {
switch (Option) {
case CONFIG_ROOTFSPATH:
CTX->Config.RootFSPath = Config;
break;
case CONFIG_THUNKLIBSPATH:
CTX->Config.ThunkLibsPath = Config;
break;
case FEXCore::Config::CONFIG_DUMPIR:
CTX->Config.DumpIR = Config;
break;
default: LogMan::Msg::A("Unknown configuration option");
}
}
uint64_t GetConfig(FEXCore::Context::Context *CTX, ConfigOption Option) {
switch (Option) {
case FEXCore::Config::CONFIG_MULTIBLOCK:
return CTX->Config.Multiblock;
break;
case FEXCore::Config::CONFIG_MAXBLOCKINST:
return CTX->Config.MaxInstPerBlock;
break;
case FEXCore::Config::CONFIG_DEFAULTCORE:
return CTX->Config.Core;
break;
case FEXCore::Config::CONFIG_VIRTUALMEMSIZE:
return CTX->Config.VirtualMemSize;
break;
case FEXCore::Config::CONFIG_SINGLESTEP:
return CTX->Config.RunningMode == FEXCore::Context::CoreRunningMode::MODE_SINGLESTEP ? 1 : 0;
case FEXCore::Config::CONFIG_GDBSERVER:
return CTX->GetGdbServerStatus();
break;
case FEXCore::Config::CONFIG_IS64BIT_MODE:
return CTX->Config.Is64BitMode;
break;
case FEXCore::Config::CONFIG_TSO_ENABLED:
return CTX->Config.TSOEnabled;
break;
case FEXCore::Config::CONFIG_SMC_CHECKS:
return CTX->Config.SMCChecks;
break;
case FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS:
return CTX->Config.ABILocalFlags;
break;
case FEXCore::Config::CONFIG_ABI_NO_PF:
return CTX->Config.ABINoPF;
break;
default: LogMan::Msg::A("Unknown configuration option");
}
return 0;
}
static std::map<FEXCore::Config::LayerType, std::unique_ptr<FEXCore::Config::Layer>> ConfigLayers;
static FEXCore::Config::Layer *Meta{};
constexpr std::array<FEXCore::Config::LayerType, 6> LoadOrder = {
FEXCore::Config::LayerType::LAYER_MAIN,
FEXCore::Config::LayerType::LAYER_GLOBAL_APP,
FEXCore::Config::LayerType::LAYER_LOCAL_APP,
FEXCore::Config::LayerType::LAYER_ARGUMENTS,
FEXCore::Config::LayerType::LAYER_ENVIRONMENT,
FEXCore::Config::LayerType::LAYER_TOP
};
Layer::Layer(const LayerType _Type)
: Type {_Type} {
}
Layer::~Layer() {
}
class MetaLayer final : public FEXCore::Config::Layer {
public:
MetaLayer(const LayerType _Type)
: FEXCore::Config::Layer (_Type) {
}
~MetaLayer() {
}
void Load();
private:
void MergeConfigMap(const LayerOptions &Options);
};
void MetaLayer::Load() {
OptionMap.clear();
for (auto CurrentLayer = LoadOrder.begin(); CurrentLayer != LoadOrder.end(); ++CurrentLayer) {
auto it = ConfigLayers.find(*CurrentLayer);
if (it != ConfigLayers.end() && *CurrentLayer != Type) {
// Merge this layer's options to this layer
MergeConfigMap(it->second->GetOptionMap());
}
}
}
void MetaLayer::MergeConfigMap(const LayerOptions &Options) {
// Insert this layer's options, overlaying previous options that exist here
for (auto &it : Options) {
OptionMap.insert_or_assign(it.first, it.second);
}
}
void Initialize() {
AddLayer(std::make_unique<MetaLayer>(FEXCore::Config::LayerType::LAYER_TOP));
Meta = ConfigLayers.begin()->second.get();
}
void Shutdown() {
ConfigLayers.clear();
Meta = nullptr;
}
void Load() {
for (auto CurrentLayer = LoadOrder.begin(); CurrentLayer != LoadOrder.end(); ++CurrentLayer) {
auto it = ConfigLayers.find(*CurrentLayer);
if (it != ConfigLayers.end()) {
it->second->Load();
}
}
}
void ReloadMetaLayer() {
Meta->Load();
}
void AddLayer(std::unique_ptr<FEXCore::Config::Layer> _Layer) {
ConfigLayers.emplace(_Layer->GetLayerType(), std::move(_Layer));
}
bool Exists(ConfigOption Option) {
return Meta->OptionExists(Option);
}
std::optional<LayerValue*> All(ConfigOption Option) {
return Meta->All(Option);
}
std::optional<std::string*> Get(ConfigOption Option) {
return Meta->Get(Option);
}
void Set(ConfigOption Option, std::string Data) {
Meta->Set(Option, Data);
}
void EraseSet(ConfigOption Option, std::string Data) {
Meta->EraseSet(Option, Data);
}
template<typename T>
T Value<T>::Get(FEXCore::Config::ConfigOption Option) {
T Result;
auto Value = FEXCore::Config::Get(Option);
if (!FEXCore::StrConv::Conv(**Value, &Result)) {
assert(0 && "Attempted to convert invalid value");
}
return Result;
}
template<typename T>
T Value<T>::GetIfExists(FEXCore::Config::ConfigOption Option, T Default) {
T Result;
auto Value = FEXCore::Config::Get(Option);
if (Value && FEXCore::StrConv::Conv(**Value, &Result)) {
return Result;
}
else {
return Default;
}
}
template<>
std::string Value<std::string>::GetIfExists(FEXCore::Config::ConfigOption Option, std::string Default) {
auto Value = FEXCore::Config::Get(Option);
if (Value) {
return **Value;
}
else {
return Default;
}
}
template bool Value<bool>::GetIfExists(FEXCore::Config::ConfigOption Option, bool Default);
template uint8_t Value<uint8_t>::GetIfExists(FEXCore::Config::ConfigOption Option, uint8_t Default);
template uint64_t Value<uint64_t>::GetIfExists(FEXCore::Config::ConfigOption Option, uint64_t Default);
// Constructor
template Value<std::string>::Value(FEXCore::Config::ConfigOption _Option, std::string Default);
template Value<bool>::Value(FEXCore::Config::ConfigOption _Option, bool Default);
template Value<uint8_t>::Value(FEXCore::Config::ConfigOption _Option, uint8_t Default);
template Value<uint64_t>::Value(FEXCore::Config::ConfigOption _Option, uint64_t Default);
template<typename T>
void Value<T>::GetListIfExists(FEXCore::Config::ConfigOption Option, std::list<std::string> *List) {
auto Value = FEXCore::Config::All(Option);
List->clear();
if (Value) {
*List = **Value;
}
}
}