| // Copyright 2016 The Fuchsia Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | // This file is based on zircon/kernel/arch/x86/include/arch/x86/feature.h. | 
 | // TODO(dje): As with generic elf, dwarf, et.al, move to application | 
 | // independent library. | 
 |  | 
 | #ifndef GARNET_LIB_DEBUGGER_UTILS_X86_CPUID_H_ | 
 | #define GARNET_LIB_DEBUGGER_UTILS_X86_CPUID_H_ | 
 |  | 
 | #include <lib/syslog/cpp/macros.h> | 
 |  | 
 | #include <cstdint> | 
 | #include <cstdio> | 
 |  | 
 | namespace debugger_utils { | 
 |  | 
 | // cpu vendors | 
 | enum x86_vendor_list { X86_VENDOR_UNKNOWN, X86_VENDOR_INTEL, X86_VENDOR_AMD }; | 
 |  | 
 | struct x86_model_info { | 
 |   uint8_t processor_type; | 
 |   uint8_t family; | 
 |   uint8_t model; | 
 |   uint8_t stepping; | 
 |  | 
 |   uint16_t display_family; | 
 |   uint8_t display_model; | 
 | }; | 
 |  | 
 | const x86_model_info* x86_get_model(); | 
 |  | 
 | #define MAX_SUPPORTED_CPUID (0x17) | 
 | #define MAX_SUPPORTED_CPUID_EXT (0x80000008) | 
 |  | 
 | struct x86_cpuid_leaf { | 
 |   uint32_t a; | 
 |   uint32_t b; | 
 |   uint32_t c; | 
 |   uint32_t d; | 
 | }; | 
 |  | 
 | enum x86_cpuid_leaf_num { | 
 |   X86_CPUID_BASE = 0, | 
 |   X86_CPUID_MODEL_FEATURES = 0x1, | 
 |   X86_CPUID_TOPOLOGY = 0xb, | 
 |   X86_CPUID_XSAVE = 0xd, | 
 |   X86_CPUID_PT = 0x14, | 
 |  | 
 |   X86_CPUID_EXT_BASE = 0x80000000, | 
 |   X86_CPUID_ADDR_WIDTH = 0x80000008, | 
 | }; | 
 |  | 
 | struct x86_cpuid_bit { | 
 |   enum x86_cpuid_leaf_num leaf_num; | 
 |   uint8_t word; | 
 |   uint8_t bit; | 
 | }; | 
 |  | 
 | void x86_feature_init(); | 
 |  | 
 | const x86_cpuid_leaf* x86_get_cpuid_leaf(enum x86_cpuid_leaf_num leaf); | 
 |  | 
 | // Retrieve the specified subleaf.  This function is not cached. | 
 | // Returns false if leaf num is invalid. | 
 | bool x86_get_cpuid_subleaf(enum x86_cpuid_leaf_num, uint32_t, x86_cpuid_leaf*); | 
 |  | 
 | bool x86_feature_test(x86_cpuid_bit bit); | 
 |  | 
 | // TODO(dje): Switch to iostreams later, maybe. | 
 | void x86_feature_debug(FILE* out); | 
 |  | 
 | #define X86_CPUID_BIT(leaf, word, bit) \ | 
 |   (::debugger_utils::x86_cpuid_bit) { (::debugger_utils::x86_cpuid_leaf_num)(leaf), (word), (bit) } | 
 |  | 
 | // add feature bits to test here | 
 | #define X86_FEATURE_SSE3 X86_CPUID_BIT(0x1, 2, 0) | 
 | #define X86_FEATURE_SSSE3 X86_CPUID_BIT(0x1, 2, 9) | 
 | #define X86_FEATURE_SSE4_1 X86_CPUID_BIT(0x1, 2, 19) | 
 | #define X86_FEATURE_SSE4_2 X86_CPUID_BIT(0x1, 2, 20) | 
 | #define X86_FEATURE_TSC_DEADLINE X86_CPUID_BIT(0x1, 2, 24) | 
 | #define X86_FEATURE_AESNI X86_CPUID_BIT(0x1, 2, 25) | 
 | #define X86_FEATURE_XSAVE X86_CPUID_BIT(0x1, 2, 26) | 
 | #define X86_FEATURE_AVX X86_CPUID_BIT(0x1, 2, 28) | 
 | #define X86_FEATURE_RDRAND X86_CPUID_BIT(0x1, 2, 30) | 
 | #define X86_FEATURE_FPU X86_CPUID_BIT(0x1, 3, 0) | 
 | #define X86_FEATURE_MMX X86_CPUID_BIT(0x1, 3, 23) | 
 | #define X86_FEATURE_FXSR X86_CPUID_BIT(0x1, 3, 24) | 
 | #define X86_FEATURE_SSE X86_CPUID_BIT(0x1, 3, 25) | 
 | #define X86_FEATURE_SSE2 X86_CPUID_BIT(0x1, 3, 26) | 
 | #define X86_FEATURE_TSC_ADJUST X86_CPUID_BIT(0x7, 1, 1) | 
 | #define X86_FEATURE_AVX2 X86_CPUID_BIT(0x7, 1, 5) | 
 | #define X86_FEATURE_SMEP X86_CPUID_BIT(0x7, 1, 7) | 
 | #define X86_FEATURE_RDSEED X86_CPUID_BIT(0x7, 1, 18) | 
 | #define X86_FEATURE_SMAP X86_CPUID_BIT(0x7, 1, 20) | 
 | #define X86_FEATURE_PT X86_CPUID_BIT(0x7, 1, 25) | 
 | #define X86_FEATURE_PKU X86_CPUID_BIT(0x7, 2, 3) | 
 | #define X86_FEATURE_SYSCALL X86_CPUID_BIT(0x80000001, 3, 11) | 
 | #define X86_FEATURE_NX X86_CPUID_BIT(0x80000001, 3, 20) | 
 | #define X86_FEATURE_HUGE_PAGE X86_CPUID_BIT(0x80000001, 3, 26) | 
 | #define X86_FEATURE_RDTSCP X86_CPUID_BIT(0x80000001, 3, 27) | 
 | #define X86_FEATURE_INVAR_TSC X86_CPUID_BIT(0x80000007, 3, 8) | 
 |  | 
 | // topology | 
 |  | 
 | #define X86_TOPOLOGY_INVALID 0 | 
 | #define X86_TOPOLOGY_SMT 1 | 
 | #define X86_TOPOLOGY_CORE 2 | 
 |  | 
 | struct x86_topology_level { | 
 |   // The number of bits to right shift to identify the next-higher topological | 
 |   // level. | 
 |   uint8_t right_shift; | 
 |   // The type of relationship this level describes (hyperthread/core/etc). | 
 |   uint8_t type; | 
 | }; | 
 |  | 
 | /** | 
 |  * @brief Fetch the topology information for the given level. | 
 |  * | 
 |  * This interface is uncached. | 
 |  * | 
 |  * @param level The level to retrieve info for.  Should initially be 0 and | 
 |  * incremented with each call. | 
 |  * @param info The structure to populate with the discovered information | 
 |  * | 
 |  * @return true if the requested level existed (and there may be higher levels). | 
 |  * @return false if the requested level does not exist (and no higher ones do). | 
 |  */ | 
 | bool x86_topology_enumerate(uint8_t level, x86_topology_level* info); | 
 |  | 
 | }  // namespace debugger_utils | 
 |  | 
 | #endif  // GARNET_LIB_DEBUGGER_UTILS_X86_CPUID_H_ |