TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / cmds / check_features.cpp
diff --git a/src/type3_AndroidCloud/anbox-master/src/anbox/cmds/check_features.cpp b/src/type3_AndroidCloud/anbox-master/src/anbox/cmds/check_features.cpp
new file mode 100644 (file)
index 0000000..8a6f505
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2018 Simon Fels <morphis@gravedo.de>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "anbox/cmds/check_features.h"
+#include "anbox/utils.h"
+
+#include "cpu_features_macros.h"
+#if defined(CPU_FEATURES_ARCH_X86)
+#include "cpuinfo_x86.h"
+#endif
+
+namespace {
+std::vector<std::string> cpu_whitelist = {
+  // QEMU does not necessarily expose correctly that it supports SSE and friends even
+  // when started with `-cpu qemu64,+ssse3,+sse4.1,+sse4.2,+x2apic`
+  "QEMU",
+
+  // The following CPUs do not support AVX and without it cpu_features can't detect
+  // if SSE & friends are supported. See https://github.com/google/cpu_features/issues/4
+
+  // Intel Core i7 M620
+  "M 620",
+  // Intel Core i5 M460
+  "M 460",
+  // Intel Celeron N2840
+  "N2840",
+  // Intel Core i7 Q720
+  "Q 720",
+  // Intel Pentium T4500
+  "T4500", 
+  // Intel Core i7 Q720
+  "Q 720",
+  // Intel Xeon E5520
+  "E5520"
+  // Intel Core2 Duo T6500
+  "T6500"
+};
+} // namespace
+
+anbox::cmds::CheckFeatures::CheckFeatures()
+    : CommandWithFlagsAndAction{
+          cli::Name{"check-features"}, cli::Usage{"check-features"},
+          cli::Description{"Check that the host system supports all necessary features"}} {
+
+  action([this](const cli::Command::Context&) {
+#if defined(CPU_FEATURES_ARCH_X86)
+    const auto info = cpu_features::GetX86Info();
+    std::vector<std::string> missing_features;
+
+#define CHECK_BOOL(x, name) \
+  if (!x) \
+    missing_features.push_back(name)
+
+    CHECK_BOOL(info.features.sse4_1, "SSE 4.1");
+    CHECK_BOOL(info.features.sse4_2, "SSE 4.2");
+    CHECK_BOOL(info.features.ssse3, "SSSE 3");
+
+    char brand_string[49];
+    cpu_features::FillX86BrandString(brand_string);
+    std::string brand(brand_string);
+
+    // Check if we have a CPU which's features we can't detect correctly
+    auto is_whitelisted = false;
+    for (const auto &entry : cpu_whitelist) {
+      if (brand.find(entry) != std::string::npos) {
+        is_whitelisted = true;
+        break;
+      }
+    }
+
+    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: ";
+
+      for (size_t n = 0; n < missing_features.size(); n++) {
+        const auto feature = missing_features[n];
+        std::cerr << feature;
+        if (n < missing_features.size() - 1)
+          std::cerr << ", ";
+      }
+      std::cerr << std::endl;
+      std::cerr << "You can for example find more information about SSE" << std::endl
+                << "here https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions" << std::endl;
+
+      return EXIT_FAILURE;
+    }
+
+    std::cout << "Your computer does meet all requirements to run Anbox" << std::endl;
+
+    return EXIT_SUCCESS;
+#else
+    std::cerr << "You're running Anbox on a not yet supported architecture" << std::endl;
+    return EXIT_FAILURE;
+#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
+}