cmds: implement CPU feature sanity check via builtin compiler functions

To prevent our whilelist from growing much more we know do an additional
sanity check via compiler builtin functions if we cannot detect all
mandatory CPU features via the cpu_features libray and if the CPU isn't
whitelisted. This should cover more or less all remaining cases unless
the compiler is unable to detect the features properly.
This commit is contained in:
Simon Fels 2018-09-11 19:40:56 +02:00
commit ae8cefb770
2 changed files with 34 additions and 2 deletions

View file

@ -52,7 +52,7 @@ anbox::cmds::CheckFeatures::CheckFeatures()
cli::Name{"check-features"}, cli::Usage{"check-features"},
cli::Description{"Check that the host system supports all necessary features"}} {
action([](const cli::Command::Context&) {
action([this](const cli::Command::Context&) {
#if defined(CPU_FEATURES_ARCH_X86)
const auto info = cpu_features::GetX86Info();
std::vector<std::string> missing_features;
@ -78,7 +78,7 @@ anbox::cmds::CheckFeatures::CheckFeatures()
}
}
if (missing_features.size() > 0 && !is_whitelisted) {
if (missing_features.size() > 0 && !is_whitelisted && !sanity_check_for_features()) {
std::cerr << "The CPU of your computer (" << brand_string << ") does not support all" << std::endl
<< "features Anbox requires." << std::endl
<< "It is missing support for the following features: ";
@ -105,3 +105,32 @@ anbox::cmds::CheckFeatures::CheckFeatures()
#endif
});
}
// In case that the CPU supports AVX we take the decision as from our analysis
// of the output from the cpu_features library. If it does not we have to check
// further via the compiler builtins if we the CPU supports all mandatory features
// or not. In case that any is missing we will fail the test.
//
// This uses the compiler builtin function __builtin_cpu_supports which allows us
// to detect certain CPU features.
// See https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html
bool anbox::cmds::CheckFeatures::sanity_check_for_features() {
#if defined(CPU_FEATURES_ARCH_X86)
if (__builtin_cpu_supports("avx"))
return true;
std::vector<std::string> missing_features;
#define CHECK_FEATURE(name) \
if (!__builtin_cpu_supports(name)) \
missing_features.push_back(name);
CHECK_FEATURE("sse4.1");
CHECK_FEATURE("sse4.2");
CHECK_FEATURE("ssse3");
return missing_features.empty();
#else
return true;
#endif
}

View file

@ -29,6 +29,9 @@ namespace cmds {
class CheckFeatures : public cli::CommandWithFlagsAndAction {
public:
CheckFeatures();
private:
bool sanity_check_for_features();
};
} // namespace cmds
} // namespace anbox