blob: e278085ed0d13364dbc55a4f70da6e6416c6865b [file] [log] [blame]
// 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.
#pragma once
#include <cstdint>
#include <cstdio>
#include "lib/fxl/logging.h"
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