From ae8cefb77028ea3f4f3e8aeb5abf722cae6dca87 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 11 Sep 2018 19:40:56 +0200 Subject: [PATCH] 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. --- src/anbox/cmds/check_features.cpp | 33 +++++++++++++++++++++++++++++-- src/anbox/cmds/check_features.h | 3 +++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/anbox/cmds/check_features.cpp b/src/anbox/cmds/check_features.cpp index a1e1943..4b6f448 100644 --- a/src/anbox/cmds/check_features.cpp +++ b/src/anbox/cmds/check_features.cpp @@ -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 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 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 +} diff --git a/src/anbox/cmds/check_features.h b/src/anbox/cmds/check_features.h index e6c6ff7..8402ca6 100644 --- a/src/anbox/cmds/check_features.h +++ b/src/anbox/cmds/check_features.h @@ -29,6 +29,9 @@ namespace cmds { class CheckFeatures : public cli::CommandWithFlagsAndAction { public: CheckFeatures(); + + private: + bool sanity_check_for_features(); }; } // namespace cmds } // namespace anbox