diff --git a/CheckTool/.clang-format b/CheckTool/.clang-format new file mode 100644 index 00000000..912f947f --- /dev/null +++ b/CheckTool/.clang-format @@ -0,0 +1,7 @@ +# Refer to: +# https://android.googlesource.com/platform/external/qemu/+/emu-master-dev/android/.clang-format + +BasedOnStyle: Chromium +IndentWidth: 4 +ContinuationIndentWidth: 8 +AccessModifierOffset: -4 diff --git a/CheckTool/.gitignore b/CheckTool/.gitignore new file mode 100644 index 00000000..539f86a8 --- /dev/null +++ b/CheckTool/.gitignore @@ -0,0 +1,6 @@ +# Windows +*.obj + +# macOS +*.o + diff --git a/CheckTool/CMakeLists.txt b/CheckTool/CMakeLists.txt new file mode 100644 index 00000000..745d979b --- /dev/null +++ b/CheckTool/CMakeLists.txt @@ -0,0 +1,54 @@ +# Minimum requirement for CMake version +cmake_minimum_required(VERSION 3.4) + +# Project information +project(checktool) + +set(CMAKE_CXX_STANDARD 11) + +set(COMMON_SRCS) +list(APPEND COMMON_SRCS + ${PROJECT_SOURCE_DIR}/arg_parser.cpp + ${PROJECT_SOURCE_DIR}/common.cpp + ${PROJECT_SOURCE_DIR}/cpuid.cpp + ${PROJECT_SOURCE_DIR}/feature_detector.cpp + ${PROJECT_SOURCE_DIR}/main.cpp +) + +set(PLATFORM_SRCS) +if(WIN32) + list(APPEND PLATFORM_SRCS + ${PROJECT_SOURCE_DIR}/os_windows.cpp + ) + # Replace MDd/MD with MTd/MT to use a multi-threaded statically-linked + # runtime library for building a standalone executable. + set(CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + ) + foreach(flag ${CXX_FLAGS}) + string(REPLACE "/MD" "/MT" ${flag} "${${flag}}") + endforeach() +elseif(APPLE) + list(APPEND PLATFORM_SRCS + ${PROJECT_SOURCE_DIR}/os_darwin.cpp + ) +else() + message(FATAL_ERROR "Unsupported Platform") +endif() + +if(WIN32) + set(RESOURCES) + list(APPEND RESOURCES + ${PROJECT_SOURCE_DIR}/version.rc + ) +endif() + +# Target +add_executable(checktool ${COMMON_SRCS} ${PLATFORM_SRCS} ${RESOURCES}) + +if(APPLE) + target_link_options(checktool PRIVATE + LINKER:-sectcreate,__TEXT,__info_plist,${PROJECT_SOURCE_DIR}/Info.plist + ) +endif() diff --git a/CheckTool/CMakeSettings.json b/CheckTool/CMakeSettings.json new file mode 100644 index 00000000..7780c154 --- /dev/null +++ b/CheckTool/CMakeSettings.json @@ -0,0 +1,59 @@ +{ + "configurations": [ + { + "name": "x86-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ + "msvc_x86" + ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + + { + "name": "x86-Release", + "generator": "Ninja", + "configurationType": "Release", + "inheritEnvironments": [ + "msvc_x86" + ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ + "msvc_x64_x64" + ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "Release", + "inheritEnvironments": [ + "msvc_x64_x64" + ], + "buildRoot": "${projectDir}\\build\\${name}", + "installRoot": "${projectDir}\\build\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + } + ] +} diff --git a/CheckTool/Info.plist b/CheckTool/Info.plist new file mode 100644 index 00000000..d9ebd842 --- /dev/null +++ b/CheckTool/Info.plist @@ -0,0 +1,49 @@ + + + + + + CFBundleName + checktool + CFBundleIconFile + + CFBundleVersion + 1 + NSHumanReadableCopyright + © 2020 Intel Corporation + CFBundleGetInfoString + Intel® HAXM Check Tool 1.0.0 + CFBundleLongVersionString + 1.0.0.0 + CFBundleShortVersionString + 1.0.0 + + diff --git a/CheckTool/README.md b/CheckTool/README.md new file mode 100644 index 00000000..ff4ac2bb --- /dev/null +++ b/CheckTool/README.md @@ -0,0 +1,136 @@ +# Check Tool for Intel Hardware Accelerated Execution Manager + +It is required that the host operating system to meet the environmental +requirements to install HAXM. These requirements include Intel CPU verdor, +enabling VMX, disabling Hyper-V, etc. Only when all the requirements are met, +HAXM can be installed and executed properly. These wiki pages (installation +instructions on [Windows][install-on-windows] and [macOS][install-on-macos]) +describe the configuration methods of HAXM installation prerequisites. + +This utility is a command line tool for system checking for HAXM. It is used to +help user to check the status of each condition in the current system +environment, so as to determine whether the hardware configuration meets the +requirements or which system settings need to be changed. This software +currently supports running on Windows and macOS. + +## Downloads + +The latest release of HAXM **Check Tool** for Windows and macOS hosts are +available [here][checktool-release]. + +## Windows + +### Usage + +1. `cd X:\path\to\CheckTool` +1. `checktool.exe --verbose` + +The output will be as below. + + CPU vendor * GenuineIntel + Intel64 supported * Yes + VMX supported * Yes + VMX enabled * Yes + EPT supported * Yes + NX supported * Yes + NX enabled * Yes + Hyper-V disabled - No + OS version * Windows 10.0.18363 + OS architecture * x86_64 + Guest unoccupied * Yes. 0 guest(s) + +"*" represents the item is passed, while "-" represents the item is failed. + +### Build + +#### Prerequisites + +[Visual Studio][visualstudio] 2017 or later + +Install the following components: **Desktop development with C++** (**C++ CMake +tools for Windows** is included) + +#### Build steps + +**Option A (Visual Studio)** + +1. Open _CheckTool_ project in Visual Studio. + + **File** > **Open** > **Folder...** > **Select Folder** "CheckTool" + (containing _CMakeLists.txt_) +1. Select proper configuration, e.g., "x86-Debug". +1. Build project. + + **Build** > **Build All** + +The executable program (_checktool.exe_) will be generated in +_X:\path\to\CheckTool\build\x86-Debug\\_. The 32-bit executable can run on both +32-bit and 64-bit Windows, while the 64-bit executable can run on 64-bit Windows +only. + +**Option B (CMake)** + +1. `set PATH=C:\Program Files (x86)\Microsoft Visual ` +`Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin;%PATH%` +1. `cd X:\path\to\CheckTool` +1. `mkdir build && cd build && cmake .. && cmake --build .` + +The executable program (_checktool.exe_) will be generated in +_X:\path\to\CheckTool\build\Debug\\_. It is easy to clean the build just by +removing the _build_ folder manually. + +The full matrix for building 32-bit/64-bit Windows with Debug/Release +configuration can be referred as below. + +| | 32-bit Build | 64-bit Build +----------- | -------------------------------------------- | ------------------------------------------ +| | `cmake -A Win32 -B build\Win32` | `cmake -A x64 -B build\x64` +**Debug** | `cmake --build build\Win32 --config Debug` | `cmake --build build\x64 --config Debug` +**Release** | `cmake --build build\Win32 --config Release` | `cmake --build build\x64 --config Release` + +The path in the first step is the CMake default extension path installed in +Visual Studio 2019. If [CMake][cmake] (3.17 or later) has been installed +independently and added to the system path, the first step of setting path can +be omitted. + +## macOS + +### Usage + +1. `cd /path/to/CheckTool` +1. `./checktool --verbose` + +### Build + +#### Prerequisites + +* [Xcode][xcode] 7.2.1 or later +* [CMake][cmake] 3.17 or later + +#### Build steps + +1. `cd /path/to/CheckTool` +1. `mkdir build && cd build && cmake .. && make` + +The binary (_checktool_) will be generated in _/path/to/CheckTool/build/_. It is +easy to clean the build just by removing the _build_ folder manually. + +The full list for building Debug/Release configuration can be referred as +below. + +| Debug +| :-------------------------------------------------- +| `cmake -DCMAKE_BUILD_TYPE=Debug -B build/Debug` +| `make -C build/Debug` +| **Release** +| `cmake -DCMAKE_BUILD_TYPE=Release -B build/Release` +| `make -C build/Release` + +[checktool-release]: https://github.com/intel/haxm/releases/tag/checktool-v1.0.0 +[cmake]: https://cmake.org/download/ +[install-on-macos]: +https://github.com/intel/haxm/wiki/Installation-Instructions-on-macOS +[install-on-windows]: +https://github.com/intel/haxm/wiki/Installation-Instructions-on-Windows +[visualstudio]: https://www.visualstudio.com/downloads/ +[xcode]: https://developer.apple.com/xcode/ diff --git a/CheckTool/arg_parser.cpp b/CheckTool/arg_parser.cpp new file mode 100644 index 00000000..e4d411fd --- /dev/null +++ b/CheckTool/arg_parser.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "arg_parser.h" + +namespace haxm { +namespace check_util { + +ArgParser::ArgParser(int &argc, char *argv[], + const std::vector &valid_options) { + valid_options_ = valid_options; + + for (int i = 1; i < argc; ++i) { + args_.push_back(std::string(argv[i])); + } +} + +bool ArgParser::Verify() { + for (std::vector::const_iterator it = args_.begin(); + it != args_.end(); ++it) { + if (std::find(valid_options_.begin(), valid_options_.end(), *it) + == valid_options_.end()) { + error_ = *it; + return false; + } + } + return true; +} + +bool ArgParser::Test(const std::string &option) const { + return std::find(args_.begin(), args_.end(), option) != args_.end(); +} + +std::string ArgParser::error() const { + return error_; +} + +} // namespace check_util +} // namespace haxm diff --git a/CheckTool/arg_parser.h b/CheckTool/arg_parser.h new file mode 100644 index 00000000..f23efc9c --- /dev/null +++ b/CheckTool/arg_parser.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HAXM_CHECK_ARG_PARSER_H_ +#define HAXM_CHECK_ARG_PARSER_H_ + +#include +#include + +namespace haxm { +namespace check_util { + +class ArgParser { +public: + ArgParser(int &argc, char *argv[], + const std::vector &valid_options); + bool Verify(); + bool Test(const std::string &option) const; + std::string error() const; + +private: + std::vector valid_options_; + std::vector args_; + std::string error_; +}; + +} // namespace check_util +} // namespace haxm + +#endif // HAXM_CHECK_ARG_PARSER_H_ diff --git a/CheckTool/common.cpp b/CheckTool/common.cpp new file mode 100644 index 00000000..1c80dd22 --- /dev/null +++ b/CheckTool/common.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "arg_parser.h" +#include "common.h" +#include "feature_detector.h" + +namespace haxm { +namespace check_util { + +CheckResult ParseArguments(int &argc, char* argv[], bool &is_verbose) { + haxm::check_util::ArgParser arg_parser(argc, argv, {"-h", "--help", "-v", + "--verbose"}); + + if (!arg_parser.Verify()) { + std::cout << "checktool unknown option: " << arg_parser.error() + << std::endl; + std::cout << "Usage: checktool [-h | --help] [-v | --verbose]" + << std::endl; + return haxm::check_util::kError; + } + + if (arg_parser.Test("-h") || arg_parser.Test("--help")) { + std::cout << "CheckTool version " << APP_VERSION << std::endl; + std::cout << "-v, --verbose Show detailed system information" + << std::endl; + return haxm::check_util::kFail; + } + + if (arg_parser.Test("-v") || arg_parser.Test("--verbose")) { + is_verbose = true; + } + + return haxm::check_util::kPass; +} + +int Check(bool is_verbose) { + int ret = 0; + + haxm::check_util::FeatureDetector fd; + haxm::check_util::CheckResult detect_res = fd.Detect(); + + if (detect_res == haxm::check_util::kError) { + ret = -1; + } else if (detect_res == haxm::check_util::kFail) { + ret = 1; + } + + if (is_verbose) { + fd.Print(); + } + + return ret; +} + +} // namespace check_util +} // namespace haxm diff --git a/CheckTool/common.h b/CheckTool/common.h new file mode 100644 index 00000000..5b21c1ce --- /dev/null +++ b/CheckTool/common.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HAXM_CHECK_COMMON_H_ +#define HAXM_CHECK_COMMON_H_ + +#include + +namespace haxm { +namespace check_util { + +#define APP_VERSION "1.0.0" + +enum CheckResult { + kUnknown = 0, + kPass, + kFail, + kNotApplicable, // e.g., CheckHypervDisabled() on macOS + kError, +}; + +// Source: +// https://github.com/google/cpu_features/blob/master/include/internal/bit_utils.h +inline static bool IsBitSet(uint32_t reg, int bit) { + return (reg >> bit) & 0x1; +} + +CheckResult ParseArguments(int &argc, char* argv[], bool &is_verbose); +int Check(bool is_verbose); + +} // namespace check_util +} // namespace haxm + +#endif // HAXM_CHECK_COMMON_H_ diff --git a/CheckTool/cpuid.cpp b/CheckTool/cpuid.cpp new file mode 100644 index 00000000..2585eace --- /dev/null +++ b/CheckTool/cpuid.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "cpuid.h" + +// To check the current compilers +// https://github.com/google/cpu_features/blob/7806502271dfe79b417f636839dd9de41a0be16f/include/cpu_features_macros.h#L83 +#if defined(__GNUC__) || defined(__clang__) // GCC or Clang +#include +#elif defined(_MSC_VER) // MSVC +#include +#else // !defined(__GNUC__) && !defined(__clang__) && !defined(_MSC_VER_) +#error "Unsupported compiler, only support either GCC, Clang or MSVC." +#endif // defined(__GNUC__) || defined(__clang__) + +#include "common.h" + +namespace haxm { +namespace check_util { + +Cpuid::Cpuid() { + max_leaf0_ = Run(0).eax; + max_leaf8_ = Run(0x80000000).eax; +} + +// To wrap the CPUID instruction +CpuidResult Cpuid::Run(uint32_t eax) { + CpuidResult leaf; +#if defined(__GNUC__) || defined(__clang__) // GCC or Clang + __cpuid(eax, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx); + +#elif defined(_MSC_VER) // MSVC + int data[4]; + __cpuid(data, eax); + leaf.eax = data[0]; + leaf.ebx = data[1]; + leaf.ecx = data[2]; + leaf.edx = data[3]; +#else // !defined(__GNUC__) && !defined(__clang__) && !defined(_MSC_VER) +#error "Unsupported compiler, only support either GCC, Clang or MSVC." +#endif // defined(__GNUC__) || defined(__clang__) + return leaf; +} + +std::string Cpuid::GetCpuVendor() const { + CpuidResult leaf = Run(0); + + char vendor_temp[13] = {0}; + *reinterpret_cast(vendor_temp) = leaf.ebx; + *reinterpret_cast(vendor_temp + 4) = leaf.edx; + *reinterpret_cast(vendor_temp + 8) = leaf.ecx; + vendor_temp[12] = '\0'; + + std::string vendor = vendor_temp; + + return vendor; +} + +bool Cpuid::IsVmxSupported() const { + if (max_leaf0_ < 1) { + return false; + } + CpuidResult leaf = Run(1); + + return IsBitSet(leaf.ecx, 5); +} + +bool Cpuid::IsNxSupported() const { + if (max_leaf8_ < 0x80000001) { + return false; + } + CpuidResult leaf = Run(0x80000001); + + return IsBitSet(leaf.edx, 20); +} + +bool Cpuid::IsLongModeSupported() const { + if (max_leaf8_ < 0x80000001) { + return false; + } + CpuidResult leaf = Run(0x80000001); + + return IsBitSet(leaf.edx, 29); +} + +bool Cpuid::IsHypervisorPresent() const { + if (max_leaf0_ < 1) { + return false; + } + CpuidResult leaf = Run(1); + + return IsBitSet(leaf.ecx, 31); +} + +} // namespace check_util +} // namespace haxm diff --git a/CheckTool/cpuid.h b/CheckTool/cpuid.h new file mode 100644 index 00000000..1555b3f0 --- /dev/null +++ b/CheckTool/cpuid.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HAXM_CHECK_CPUID_H_ +#define HAXM_CHECK_CPUID_H_ + +#include +#include + +namespace haxm { +namespace check_util { + +struct CpuidResult { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; +}; + +class Cpuid { +public: + Cpuid(); + static CpuidResult Run(uint32_t eax); + std::string GetCpuVendor() const; + bool IsVmxSupported() const; + bool IsNxSupported() const; + bool IsLongModeSupported() const; + bool IsHypervisorPresent() const; + +private: + uint32_t max_leaf0_; // highest basic information leaf + uint32_t max_leaf8_; // highest extended information leaf +}; + +} // namespace check_util +} // namespace haxm + +#endif // HAXM_CHECK_CPUID_H_ diff --git a/CheckTool/feature_detector.cpp b/CheckTool/feature_detector.cpp new file mode 100644 index 00000000..daeabf72 --- /dev/null +++ b/CheckTool/feature_detector.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "common.h" +#include "cpuid.h" +#include "feature_detector.h" +#if defined(_WIN32) || defined(_WIN64) +#include "os_windows.h" +#elif defined(__APPLE__) +#include "os_darwin.h" +#endif + +namespace haxm { +namespace check_util { + +FeatureDetector::FeatureDetector() { + os_ = new OsImpl(); +} + +FeatureDetector::~FeatureDetector() { + delete os_; +} + +CheckResult FeatureDetector::CheckCpuVendor(std::string* vendor) const { + std::string temp; + temp = cpuid_.GetCpuVendor(); + + if (vendor != nullptr) { + *vendor = temp; + } + + return temp == "GenuineIntel" ? kPass : kFail; +} + +CheckResult FeatureDetector::CheckLongModeSupported() const { + return cpuid_.IsLongModeSupported() ? kPass : kFail; +} + +CheckResult FeatureDetector::CheckVmxSupported() const { + return cpuid_.IsVmxSupported() ? kPass : kFail; +} + +CheckResult FeatureDetector::CheckVmxEnabled() const { + return os_->CheckVmxEnabled(); +} + +CheckResult FeatureDetector::CheckEptSupported() const { + return os_->CheckEptSupported(); +} + +CheckResult FeatureDetector::CheckNxSupported() const { + return cpuid_.IsNxSupported() ? kPass : kFail; +} + +CheckResult FeatureDetector::CheckNxEnabled() const { + return os_->CheckNxEnabled(); +} + +CheckResult FeatureDetector::CheckHyperVDisabled() const { + return os_->CheckHyperVDisabled(); +} + +CheckResult FeatureDetector::CheckOsVersion(OsVersion* os_ver) const { + return os_->CheckVersion(os_ver); +} + +CheckResult FeatureDetector::CheckOsArchitecture( + OsArchitecture* os_arch) const { + return os_->CheckArchitecture(os_arch); +} + +CheckResult FeatureDetector::CheckGuestOccupied(uint32_t* occupied_count) + const { + return os_->CheckGuestOccupied(occupied_count); +} + +std::string FeatureDetector::ToString(CheckResult res) { + switch (res) { + case kUnknown: + return "Unknown"; + case kPass: + return "Yes"; + case kFail: + return "No"; + case kNotApplicable: + return "Not Applicable"; + case kError: + return "An error occurred"; + default: + assert(false); + return nullptr; + } +} + +std::string FeatureDetector::ToString(OsArchitecture os_arch) { + switch (os_arch) { + case kX86: + return "x86"; + case kX86_64: + return "x86_64"; + default: + return "Unrecognized"; + } +} + +std::string FeatureDetector::ToString(OsType os_type) { + switch (os_type) { + case kWindows: + return "Windows"; + case kDarwin: + return "macOS"; + default: + return "Unrecognized"; + } +} + +CheckResult FeatureDetector::Detect() const { + CheckResult res[11]; + + res[0] = CheckCpuVendor(); + res[1] = CheckLongModeSupported(); + res[2] = CheckNxSupported(); + res[3] = CheckNxEnabled(); + res[4] = CheckOsVersion(); + res[5] = CheckOsArchitecture(); + res[6] = CheckGuestOccupied(); + res[7] = CheckHyperVDisabled(); + res[8] = CheckVmxSupported(); + res[9] = CheckVmxEnabled(); + res[10] = CheckEptSupported(); + + int check_num = 11; + // When Hyper-V is enabled, it will affect the checking results of VMX + // supported, VMX enabled and EPT supported, so only the first 8 items are + // checked. When Hyper-V is disabled, all items are checked. + if (res[7] == kFail) { + check_num = 8; + } + + int detector[5] = {}; + + for (int i = 0; i < check_num; ++i) { + ++detector[static_cast(res[i])]; + } + + if (detector[static_cast(kError)] > 0) { + return kError; + } + + if (detector[static_cast(kUnknown)] > 0) { + return kUnknown; + } + + if (detector[static_cast(kFail)] > 0) { + return kFail; + } + + return kPass; +} + +void FeatureDetector::Print() const { + CheckResult res; + std::string item; + const int kCol = 20; + + std::string vendor; + res = CheckCpuVendor(&vendor); + item = "CPU vendor"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res == kPass ? '*' : '-') << " " << vendor << std::endl; + + res = CheckLongModeSupported(); + item = "Intel64 supported"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res == kPass ? '*' : '-') << " " << ToString(res) + << std::endl; + + res = CheckVmxSupported(); + item = "VMX supported"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res == kPass ? '*' : '-') << " " << ToString(res) + << std::endl; + + res = CheckVmxEnabled(); + item = "VMX enabled"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res == kPass ? '*' : '-') << " " << ToString(res) + << std::endl; + + res = CheckEptSupported(); + item = "EPT supported"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res == kPass ? '*' : '-') << " " << ToString(res) + << std::endl; + + res = CheckNxSupported(); + item = "NX supported"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res == kPass ? '*' : '-') << " " << ToString(res) + << std::endl; + + res = CheckNxEnabled(); + item = "NX enabled"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res == kPass ? '*' : '-') << " " << ToString(res) + << std::endl; + + res = CheckHyperVDisabled(); + item = "Hyper-V disabled"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res != kFail ? '*' : '-') << " " << ToString(res) + << std::endl; + + OsVersion os_ver; + res = CheckOsVersion(&os_ver); + item = "OS version"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res == kPass ? '*' : '-') << " " << ToString(os_ver.type) + << " " << os_ver.major << "." << os_ver.minor << "." + << os_ver.build_number << std::endl; + + OsArchitecture os_arch; + res = CheckOsArchitecture(&os_arch); + item = "OS architecture"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res == kPass ? '*' : '-') << " " << ToString(os_arch) + << std::endl; + + uint32_t occupied_count; + res = CheckGuestOccupied(&occupied_count); + item = "Guest unoccupied"; + std::cout << item << std::string(kCol - item.size(), ' ') + << (res == kPass ? '*' : '-') << " " << ToString(res) << ". " + << occupied_count << " guest(s)" << std::endl; +} + +} // namespace check_util +} // namespace haxm diff --git a/CheckTool/feature_detector.h b/CheckTool/feature_detector.h new file mode 100644 index 00000000..060f35f9 --- /dev/null +++ b/CheckTool/feature_detector.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HAXM_CHECK_FEATURE_DETECTOR_H_ +#define HAXM_CHECK_FEATURE_DETECTOR_H_ + +#include + +#include "common.h" +#include "cpuid.h" +#include "os.h" + +namespace haxm { +namespace check_util { + +class FeatureDetector { +public: + FeatureDetector(); + ~FeatureDetector(); + CheckResult Detect() const; + void Print() const; + +private: + CheckResult CheckCpuVendor(std::string* vendor = nullptr) const; + CheckResult CheckLongModeSupported() const; // Long Mode = Intel64 + CheckResult CheckVmxSupported() const; + CheckResult CheckVmxEnabled() const; + CheckResult CheckEptSupported() const; + CheckResult CheckNxSupported() const; + CheckResult CheckNxEnabled() const; + CheckResult CheckHyperVDisabled() const; + CheckResult CheckOsVersion(OsVersion* os_ver = nullptr) const; + CheckResult CheckOsArchitecture(OsArchitecture* os_arch = nullptr) const; + CheckResult CheckGuestOccupied(uint32_t* occupied_count = nullptr) const; + static std::string ToString(CheckResult res); + static std::string ToString(OsType os_type); + static std::string ToString(OsArchitecture os_arch); + Cpuid cpuid_; + Os* os_; +}; + +} // namespace check_util +} // namespace haxm + +#endif // HAXM_CHECK_FEATURE_DETECTOR_H_ diff --git a/CheckTool/main.cpp b/CheckTool/main.cpp new file mode 100644 index 00000000..7b1849fc --- /dev/null +++ b/CheckTool/main.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "common.h" + +int main(int argc, char* argv[]) { + int ret = 0; + haxm::check_util::CheckResult result; + bool is_verbose = false; + + result = haxm::check_util::ParseArguments(argc, argv, is_verbose); + + switch (result) { + case haxm::check_util::kPass: { + ret = haxm::check_util::Check(is_verbose); + break; + } + case haxm::check_util::kError: { + ret = -1; + break; + } + default: { + ret = 0; + break; + } + } + + return ret; +} diff --git a/CheckTool/os.h b/CheckTool/os.h new file mode 100644 index 00000000..7e63d310 --- /dev/null +++ b/CheckTool/os.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HAXM_CHECK_OS_H_ +#define HAXM_CHECK_OS_H_ + +#include "common.h" + +namespace haxm { +namespace check_util { + +enum OsType { + kWindows = 0, + kDarwin, + kOtherOs, +}; + +struct OsVersion { + OsType type; + int major; + int minor; + int build_number; +}; + +enum OsArchitecture { + kX86 = 0, + kX86_64, + kOtherArch, +}; + +class Os { // abstract class +public: + virtual ~Os() {} + virtual CheckResult CheckVmxEnabled() const = 0; + virtual CheckResult CheckEptSupported() const = 0; + virtual CheckResult CheckNxEnabled() const = 0; + virtual CheckResult CheckHyperVDisabled() const = 0; + virtual CheckResult CheckVersion(OsVersion* os_ver = nullptr) const = 0; + virtual CheckResult CheckArchitecture( + OsArchitecture* os_arch = nullptr) const = 0; + virtual CheckResult CheckGuestOccupied(uint32_t* occupied_count = nullptr) + const = 0; +}; + +} // namespace check_util +} // namespace haxm + +#endif // HAXM_CHECK_OS_H_ diff --git a/CheckTool/os_darwin.cpp b/CheckTool/os_darwin.cpp new file mode 100644 index 00000000..b68a5f5b --- /dev/null +++ b/CheckTool/os_darwin.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "os_darwin.h" + +namespace haxm { +namespace check_util { + +OsImpl::OsImpl() {} + +CheckResult OsImpl::CheckHvfSupported() const { + static CheckResult hvf_supported = kNotApplicable; + + if (hvf_supported != kNotApplicable) { + return hvf_supported; + } + + FILE* hvf_pipe; + char hvf_buffer[256]; + + hvf_pipe = popen("sysctl kern.hv_support", "r"); + + if (hvf_pipe == NULL) { + return kError; + } + + if (fgets(hvf_buffer, sizeof(hvf_buffer), hvf_pipe) == NULL) { + return kError; + } + + pclose(hvf_pipe); + + std::string hvf_status(hvf_buffer); + hvf_status = hvf_status[hvf_status.size() - 2]; + + hvf_supported = hvf_status == "1" ? kPass : kUnknown; + + return hvf_supported; +} + +CheckResult OsImpl::CheckVmxEnabled() const { + return CheckHvfSupported(); +} + +CheckResult OsImpl::CheckEptSupported() const { + return CheckHvfSupported(); +} + +CheckResult OsImpl::CheckNxEnabled() const { + return CheckHvfSupported(); +} + +CheckResult OsImpl::CheckHyperVDisabled() const { + return kNotApplicable; +} + +CheckResult OsImpl::CheckVersion(OsVersion* os_ver) const { + OsVersion temp_os_ver = {kDarwin, 0, 0, 0}; + FILE* os_ver_pipe; + char os_ver_buffer[256]; + + os_ver_pipe = popen("sw_vers -productVersion", "r"); + + if (os_ver_pipe == NULL) { + return kError; + } + + if (fgets(os_ver_buffer, sizeof(os_ver_buffer), os_ver_pipe) == NULL) { + return kError; + } + + const char* os_ver_info = static_cast(os_ver_buffer); + + std::sscanf(os_ver_info, "%d.%d.%d", &temp_os_ver.major, &temp_os_ver.minor, + &temp_os_ver.build_number); + + if (os_ver != nullptr) { + *os_ver = temp_os_ver; + } + + if (temp_os_ver.major < 10) { + return kFail; + } + + if (temp_os_ver.major == 10 && temp_os_ver.minor < 10) { + return kFail; + } + + return kPass; +} + +CheckResult OsImpl::CheckArchitecture(OsArchitecture* os_arch) const { + if (os_arch != nullptr) { + *os_arch = kX86_64; + } + + return kPass; +} + +CheckResult OsImpl::CheckGuestOccupied(uint32_t* occupied_count) const { + if (occupied_count != nullptr) { + *occupied_count = 0; + } + + return kPass; +} + +} // namespace check_util +} // namespace haxm diff --git a/CheckTool/os_darwin.h b/CheckTool/os_darwin.h new file mode 100644 index 00000000..e1ed8cf4 --- /dev/null +++ b/CheckTool/os_darwin.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HAXM_CHECK_OSIMPL_MAC_H_ +#define HAXM_CHECK_OSIMPL_MAC_H_ + +#include "common.h" +#include "os.h" + +namespace haxm { +namespace check_util { + +class OsImpl : public Os { +public: + OsImpl(); + CheckResult CheckVmxEnabled() const override; + CheckResult CheckEptSupported() const override; + CheckResult CheckNxEnabled() const override; + CheckResult CheckHyperVDisabled() const override; + CheckResult CheckVersion(OsVersion* os_ver) const override; + CheckResult CheckArchitecture(OsArchitecture* os_arch) const override; + CheckResult CheckGuestOccupied(uint32_t* occupied_count) const override; + +private: + CheckResult CheckHvfSupported() const; +}; + +} // namespace check_util +} // namespace haxm + +#endif // HAXM_CHECK_OSIMPL_MAC_H_ diff --git a/CheckTool/os_windows.cpp b/CheckTool/os_windows.cpp new file mode 100644 index 00000000..0ccc6278 --- /dev/null +++ b/CheckTool/os_windows.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "cpuid.h" +#include "os_windows.h" + +namespace haxm { +namespace check_util { + +#define HAX_DEVICE_TYPE 0x4000 +#define HAX_IOCTL_CAPABILITY \ + CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// The definition of hax_capability refers to the source code of HAXM project. +// /include/hax_interface.h +struct hax_capabilityinfo { + int16_t wstatus; + uint16_t winfo; + uint32_t win_refcount; + uint64_t mem_quota; +}; + +OsImpl::OsImpl() {} + +CheckResult OsImpl::CheckVmxEnabled() const { + bool vmx_enabled_res = IsVirtFeaturePresent(PF_VIRT_FIRMWARE_ENABLED); + + return vmx_enabled_res ? kPass : kFail; +} + +CheckResult OsImpl::CheckEptSupported() const { + bool ept_supported_res = + IsVirtFeaturePresent(PF_SECOND_LEVEL_ADDRESS_TRANSLATION); + + return ept_supported_res ? kPass : kFail; +} + +CheckResult OsImpl::CheckNxEnabled() const { + bool nx_enabled_res = IsVirtFeaturePresent(PF_NX_ENABLED); + + return nx_enabled_res ? kPass : kFail; +} + +CheckResult OsImpl::CheckHyperVDisabled() const { + // Check whether hypervisor is present or not + if (!cpuid_.IsHypervisorPresent()) { + // Hypervisor is not present + return kPass; + } + + // Hypervisor is present + CpuidResult leaf = cpuid_.Run(0x40000000); + uint32_t max_leaf4_ = leaf.eax; + + // TO check if hypervisor vendor is "MicrosoftHv" + // Leaf = 0x40000000 EBX = "Micr" ECX = "osof" EDX = "t HV" + // According to: Hypervisor Top Level Functional Specification v5.0C page 5 + char vendor_temp[13] = {0}; + *reinterpret_cast(vendor_temp) = leaf.ebx; + *reinterpret_cast(vendor_temp + 4) = leaf.ecx; + *reinterpret_cast(vendor_temp + 8) = leaf.edx; + vendor_temp[12] = '\0'; + + std::string vendor_str = vendor_temp; + + if (vendor_str != "Microsoft Hv") { + return kPass; + } + + if (max_leaf4_ < 0x40000003) { + return kPass; + } + + // CPUID function 0x40000003 will return Hypervisor feature + // identification + leaf = cpuid_.Run(0x40000003); + + // EBX includes information of flags specified at partition creation. + // Partition privileges must be identical for all virtual processors in + // a partition and "CreatePartitions" can make any other hypercall that + // is restricted to operating on children. + // So EBX[0] whose description is CreatePartitions can indicate Hyper-V + // enabled. + // According to: Requirements for Implementing the Microsoft Hypervisor + // Interface + // According to: Hypervisor Top Level Functional Specification v5.0C page + // 34 Also refer to: + // http://jason-x64.itwn.intel.com:8080/sdk/xref/emu-master-dev/external/qemu/android/android-emu/android/emulation/CpuAccelerator.cpp#1054 + return IsBitSet(leaf.ebx, 0) ? kFail : kPass; +} + +typedef NTSTATUS (WINAPI *RtlGetVersionFunc)(PRTL_OSVERSIONINFOW); + +CheckResult OsImpl::CheckVersion(OsVersion* os_ver) const { + CheckResult res; + HMODULE module; + + // Refer to the table: + // https://docs.microsoft.com/en-us/windows/win32/sysinfo/operating-system-version + res = IsWindows7SP1OrGreater() ? kPass : kFail; + if (os_ver == nullptr) + return res; + + module = ::GetModuleHandle(TEXT("ntdll.dll")); + + if (module == NULL) + return kError; + + RtlGetVersionFunc RtlGetVersion = + (RtlGetVersionFunc)::GetProcAddress(module, "RtlGetVersion"); + + if (RtlGetVersion == NULL) + return kError; + + RTL_OSVERSIONINFOW rovi = {0}; + rovi.dwOSVersionInfoSize = sizeof(rovi); + + RtlGetVersion(&rovi); + + os_ver->type = kWindows; + os_ver->major = rovi.dwMajorVersion; + os_ver->minor = rovi.dwMinorVersion; + os_ver->build_number = rovi.dwBuildNumber; + + return res; +} + +CheckResult OsImpl::CheckArchitecture(OsArchitecture* os_arch) const { + SYSTEM_INFO si; + OsArchitecture os_arch_temp; + + GetNativeSystemInfo(&si); + + if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) { + os_arch_temp = kX86_64; + } else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) { + os_arch_temp = kX86; + } else { + os_arch_temp = kOtherArch; + } + + if (os_arch != nullptr) { + *os_arch = os_arch_temp; + } + + return os_arch_temp == kOtherArch ? kFail : kPass; +} + +CheckResult OsImpl::CheckGuestOccupied(uint32_t* occupied_count) const { + int ret; + HANDLE hax_handle; + DWORD size = 0; + hax_capabilityinfo ci = {0, 0, 0, 0}; + + if (occupied_count != nullptr) { + *occupied_count = 0; + } + + hax_handle = CreateFile("\\\\.\\HAX", GENERIC_READ | GENERIC_WRITE, 0, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hax_handle == INVALID_HANDLE_VALUE) { + return kPass; + } + + ret = DeviceIoControl(hax_handle, HAX_IOCTL_CAPABILITY, NULL, 0, &ci, + sizeof(ci), &size, NULL); + + CloseHandle(hax_handle); + + if (!ret) { + return kError; + } + + if (occupied_count != nullptr) { + // Subtracting one here is in order not to count the occupancy of this + // program itself. + *occupied_count = ci.win_refcount - 1; + } + + if (ci.win_refcount > 1) { + return kFail; + } + + return kPass; +} + +bool OsImpl::IsVirtFeaturePresent(uint32_t virt_feature) const { + OsVersion os_ver; + + CheckVersion(&os_ver); + if (os_ver.major == 6 && os_ver.minor == 1) { + // The following processor features of IsProcessorFeaturePresent are + // not supported by Windows 7. + // An alternative command line tool Coreinfo from Microsoft can be + // referred currently. + // https://docs.microsoft.com/en-us/sysinternals/downloads/coreinfo + if (virt_feature == PF_VIRT_FIRMWARE_ENABLED || + virt_feature == PF_SECOND_LEVEL_ADDRESS_TRANSLATION) + return true; + } + + return IsProcessorFeaturePresent(virt_feature); +} + +} // namespace check_util +} // namespace haxm diff --git a/CheckTool/os_windows.h b/CheckTool/os_windows.h new file mode 100644 index 00000000..8df36b57 --- /dev/null +++ b/CheckTool/os_windows.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HAXM_CHECK_OSIMPL_WIN_H_ +#define HAXM_CHECK_OSIMPL_WIN_H_ + +#include "common.h" +#include "cpuid.h" +#include "os.h" + +namespace haxm { +namespace check_util { + +class OsImpl : public Os { +public: + OsImpl(); + CheckResult CheckVmxEnabled() const override; + CheckResult CheckEptSupported() const override; + CheckResult CheckNxEnabled() const override; + CheckResult CheckHyperVDisabled() const override; + CheckResult CheckVersion(OsVersion* os_ver) const override; + CheckResult CheckArchitecture(OsArchitecture* os_arch) const override; + CheckResult CheckGuestOccupied(uint32_t* occupied_count) const override; + +private: + bool IsVirtFeaturePresent(uint32_t virt_feature) const; + Cpuid cpuid_; +}; + +} // namespace check_util +} // namespace haxm + +#endif // HAXM_CHECK_OSIMPL_WIN_H_ diff --git a/CheckTool/version.rc b/CheckTool/version.rc new file mode 100644 index 00000000..1925c849 --- /dev/null +++ b/CheckTool/version.rc @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#define FILE_VERSION 1,0,0,0 +#define FILE_VERSION_STR "1.0.0.0" + +#define PRODUCT_VERSION 7,6,5,0 +#define PRODUCT_VERSION_STR "7.6.5.0" + +#ifdef DEBUG +#define FILE_FLAGS (VS_FF_PRIVATEBUILD | VS_FF_PRERELEASE | VERSION_DEBUG) +#else +#define FILE_FLAGS 0 +#endif + +VS_VERSION_INFO VERSIONINFO +FILEVERSION FILE_VERSION +PRODUCTVERSION PRODUCT_VERSION +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS FILE_FLAGS +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0x0L + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "Intel Corporation" + VALUE "FileDescription", "System check tool for Intel\xAE " + "Hardware Accelerated Execution Manager" + VALUE "FileVersion", FILE_VERSION_STR + VALUE "InternalName", "check_tool" + VALUE "LegalCopyright", "\xA9 2020 Intel Corporation" + VALUE "OriginalFilename", "checktool.exe" + VALUE "ProductName", "Intel\xAE Hardware Accelerated " + "Execution Manager" + VALUE "ProductVersion", PRODUCT_VERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END