TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / cmds / check_features.cpp
1 /*
2  * Copyright (C) 2018 Simon Fels <morphis@gravedo.de>
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 3, as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranties of
10  * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11  * PURPOSE.  See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 #include "anbox/cmds/check_features.h"
19 #include "anbox/utils.h"
20
21 #include "cpu_features_macros.h"
22 #if defined(CPU_FEATURES_ARCH_X86)
23 #include "cpuinfo_x86.h"
24 #endif
25
26 namespace {
27 std::vector<std::string> cpu_whitelist = {
28   // QEMU does not necessarily expose correctly that it supports SSE and friends even
29   // when started with `-cpu qemu64,+ssse3,+sse4.1,+sse4.2,+x2apic`
30   "QEMU",
31
32   // The following CPUs do not support AVX and without it cpu_features can't detect
33   // if SSE & friends are supported. See https://github.com/google/cpu_features/issues/4
34
35   // Intel Core i7 M620
36   "M 620",
37   // Intel Core i5 M460
38   "M 460",
39   // Intel Celeron N2840
40   "N2840",
41   // Intel Core i7 Q720
42   "Q 720",
43   // Intel Pentium T4500
44   "T4500", 
45   // Intel Core i7 Q720
46   "Q 720",
47   // Intel Xeon E5520
48   "E5520"
49   // Intel Core2 Duo T6500
50   "T6500"
51 };
52 } // namespace
53
54 anbox::cmds::CheckFeatures::CheckFeatures()
55     : CommandWithFlagsAndAction{
56           cli::Name{"check-features"}, cli::Usage{"check-features"},
57           cli::Description{"Check that the host system supports all necessary features"}} {
58
59   action([this](const cli::Command::Context&) {
60 #if defined(CPU_FEATURES_ARCH_X86)
61     const auto info = cpu_features::GetX86Info();
62     std::vector<std::string> missing_features;
63
64 #define CHECK_BOOL(x, name) \
65   if (!x) \
66     missing_features.push_back(name)
67
68     CHECK_BOOL(info.features.sse4_1, "SSE 4.1");
69     CHECK_BOOL(info.features.sse4_2, "SSE 4.2");
70     CHECK_BOOL(info.features.ssse3, "SSSE 3");
71
72     char brand_string[49];
73     cpu_features::FillX86BrandString(brand_string);
74     std::string brand(brand_string);
75
76     // Check if we have a CPU which's features we can't detect correctly
77     auto is_whitelisted = false;
78     for (const auto &entry : cpu_whitelist) {
79       if (brand.find(entry) != std::string::npos) {
80         is_whitelisted = true;
81         break;
82       }
83     }
84
85     if (missing_features.size() > 0 && !is_whitelisted && !sanity_check_for_features()) {
86       std::cerr << "The CPU of your computer (" << brand_string << ") does not support all" << std::endl
87                 << "features Anbox requires." << std::endl
88                 << "It is missing support for the following features: ";
89
90       for (size_t n = 0; n < missing_features.size(); n++) {
91         const auto feature = missing_features[n];
92         std::cerr << feature;
93         if (n < missing_features.size() - 1)
94           std::cerr << ", ";
95       }
96       std::cerr << std::endl;
97       std::cerr << "You can for example find more information about SSE" << std::endl
98                 << "here https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions" << std::endl;
99
100       return EXIT_FAILURE;
101     }
102
103     std::cout << "Your computer does meet all requirements to run Anbox" << std::endl;
104
105     return EXIT_SUCCESS;
106 #else
107     std::cerr << "You're running Anbox on a not yet supported architecture" << std::endl;
108     return EXIT_FAILURE;
109 #endif
110   });
111 }
112
113 // In case that the CPU supports AVX we take the decision as from our analysis
114 // of the output from the cpu_features library. If it does not we have to check
115 // further via the compiler builtins if we the CPU supports all mandatory features
116 // or not. In case that any is missing we will fail the test.
117 //
118 // This uses the compiler builtin function __builtin_cpu_supports which allows us
119 // to detect certain CPU features.
120 // See https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html
121 bool anbox::cmds::CheckFeatures::sanity_check_for_features() {
122 #if defined(CPU_FEATURES_ARCH_X86)
123   if (__builtin_cpu_supports("avx"))
124     return true;
125
126   std::vector<std::string> missing_features;
127
128 #define CHECK_FEATURE(name) \
129   if (!__builtin_cpu_supports(name)) \
130     missing_features.push_back(name);
131
132   CHECK_FEATURE("sse4.1");
133   CHECK_FEATURE("sse4.2");
134   CHECK_FEATURE("ssse3");
135
136   return missing_features.empty();
137 #else
138   return true;
139 #endif
140 }