blob: a2db9442ab1a7db7dfd104d63b88975d8755097d [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2011-2014 Google, Inc. All rights reserved.
* Copyright (c) 2000-2010 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name of VMware, Inc. 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 VMWARE, INC. 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.
*/
/* Copyright (c) 2003-2007 Determina Corp. */
/* Copyright (c) 2001-2003 Massachusetts Institute of Technology */
/* Copyright (c) 2000-2001 Hewlett-Packard Company */
/*
* proc.h - processor implementation specific interfaces
*/
#ifndef _PROC_H_
#define _PROC_H_ 1
/* DR_API EXPORT TOFILE dr_proc.h */
/* DR_API EXPORT BEGIN */
/****************************************************************************
* PROCESSOR-SPECIFIC UTILITY ROUTINES AND CONSTANTS
*/
/**
* @file dr_proc.h
* @brief Utility routines for identifying features of the processor.
*/
/* page size is 4K on all DR-supported platforms */
#ifndef PAGE_SIZE /* defined on Mac */
# define PAGE_SIZE (4*1024) /**< Size of a page of memory. */
#endif
/**< Convenience macro to align to the start of a page of memory. */
#define PAGE_START(x) (((ptr_uint_t)(x)) & ~((PAGE_SIZE)-1))
/** Constants returned by proc_get_vendor(). */
enum {
VENDOR_INTEL, /**< proc_get_vendor() processor identification: Intel */
VENDOR_AMD, /**< proc_get_vendor() processor identification: AMD */
VENDOR_UNKNOWN, /**< proc_get_vendor() processor identification: unknown */
};
/* Family and Model
* Intel 486 Family 4
* Intel Pentium Family 5
* Intel Pentium Pro Family 6, Model 0 and 1
* Intel Pentium 2 Family 6, Model 3, 5, and 6
* Intel Celeron Family 6, Model 5 and 6
* Intel Pentium 3 Family 6, Model 7, 8, 10, 11
* Intel Pentium 4 Family 15, Extended 0
* Intel Itanium Family 7
* Intel Itanium 2 Family 15, Extended 1 and 2
* Intel Pentium M Family 6, Model 9 and 13
* Intel Core Family 6, Model 14
* Intel Core 2 Family 6, Model 15
* Intel Nehalem Family 6, Models 26 (0x1a), 30 (0x1e), 31 (0x1f)
* Intel SandyBridge Family 6, Models 37 (0x25), 42 (0x2a), 44 (0x2c),
* 45 (0x2d), 47 (0x2f)
* Intel IvyBridge Family 6, Model 58 (0x3a)
* Intel Atom Family 6, Model 28 (0x1c), 38 (0x26), 54 (0x36)
*/
/* DR_API EXPORT END */
#ifdef IA32_ON_IA64 /* don't export IA64 stuff! */
/* IA-64 */
#define FAMILY_IA64 7
#endif
/* DR_API EXPORT BEGIN */
/* Remember that we add extended family to family as Intel suggests */
#define FAMILY_LLANO 18 /**< proc_get_family() processor family: AMD Llano */
#define FAMILY_ITANIUM_2_DC 17 /**< proc_get_family() processor family: Itanium 2 DC */
#define FAMILY_K8_MOBILE 17 /**< proc_get_family() processor family: AMD K8 Mobile */
#define FAMILY_ITANIUM_2 16 /**< proc_get_family() processor family: Itanium 2 */
#define FAMILY_K8L 16 /**< proc_get_family() processor family: AMD K8L */
#define FAMILY_K8 15 /**< proc_get_family() processor family: AMD K8 */
#define FAMILY_PENTIUM_4 15 /**< proc_get_family() processor family: Pentium 4 */
#define FAMILY_P4 15 /**< proc_get_family() processor family: P4 family */
#define FAMILY_ITANIUM 7 /**< proc_get_family() processor family: Itanium */
/* Pentium Pro, Pentium II, Pentium III, Athlon, Pentium M, Core, Core 2+ */
#define FAMILY_P6 6 /**< proc_get_family() processor family: P6 family */
#define FAMILY_IVYBRIDGE 6 /**< proc_get_family() processor family: IvyBridge */
#define FAMILY_SANDYBRIDGE 6 /**< proc_get_family() processor family: SandyBridge */
#define FAMILY_NEHALEM 6 /**< proc_get_family() processor family: Nehalem */
#define FAMILY_CORE_I7 6 /**< proc_get_family() processor family: Core i7 */
#define FAMILY_CORE_2 6 /**< proc_get_family() processor family: Core 2 */
#define FAMILY_CORE 6 /**< proc_get_family() processor family: Core */
#define FAMILY_PENTIUM_M 6 /**< proc_get_family() processor family: Pentium M */
#define FAMILY_PENTIUM_3 6 /**< proc_get_family() processor family: Pentium 3 */
#define FAMILY_PENTIUM_2 6 /**< proc_get_family() processor family: Pentium 2 */
#define FAMILY_PENTIUM_PRO 6 /**< proc_get_family() processor family: Pentium Pro */
#define FAMILY_ATHLON 6 /**< proc_get_family() processor family: Athlon */
#define FAMILY_K7 6 /**< proc_get_family() processor family: AMD K7 */
/* Pentium (586) */
#define FAMILY_P5 5 /**< proc_get_family() processor family: P5 family */
#define FAMILY_PENTIUM 5 /**< proc_get_family() processor family: Pentium */
#define FAMILY_K6 5 /**< proc_get_family() processor family: K6 */
#define FAMILY_K5 5 /**< proc_get_family() processor family: K5 */
/* 486 */
#define FAMILY_486 4 /**< proc_get_family() processor family: 486 */
/* We do not enumerate all models; just relevant ones needed to distinguish
* major processors in the same family.
*/
#define MODEL_IVYBRIDGE 54 /**< proc_get_model(): Ivybridge */
#define MODEL_I7_WESTMERE_EX 47 /**< proc_get_model(): Nehalem Westmere Ex */
#define MODEL_SANDYBRIDGE_E 45 /**< proc_get_model(): Sandybridge-E, -EN, -EP */
#define MODEL_I7_WESTMERE 44 /**< proc_get_model(): Westmere */
#define MODEL_SANDYBRIDGE 42 /**< proc_get_model(): Sandybridge */
#define MODEL_I7_CLARKDALE 37 /**< proc_get_model(): Westmere Clarkdale/Arrandale */
#define MODEL_I7_HAVENDALE 31 /**< proc_get_model(): Core i7 Havendale/Auburndale */
#define MODEL_I7_CLARKSFIELD 30 /**< proc_get_model(): Core i7 Clarksfield/Lynnfield */
#define MODEL_ATOM_CEDARVIEW 54 /**< proc_get_model(): Atom Cedarview */
#define MODEL_ATOM_LINCROFT 38 /**< proc_get_model(): Atom Lincroft */
#define MODEL_ATOM 28 /**< proc_get_model(): Atom */
#define MODEL_I7_GAINESTOWN 26 /**< proc_get_model(): Core i7 Gainestown */
#define MODEL_CORE_PENRYN 23 /**< proc_get_model(): Core 2 Penryn */
#define MODEL_CORE_2 15 /**< proc_get_model(): Core 2 Merom/Conroe */
#define MODEL_CORE 14 /**< proc_get_model(): Core Yonah */
#define MODEL_PENTIUM_M 13 /**< proc_get_model(): Pentium M 2MB L2 */
#define MODEL_PENTIUM_M_1MB 9 /**< proc_get_model(): Pentium M 1MB L2 */
/**
* Struct to hold all 4 32-bit feature values returned by cpuid.
* Used by proc_get_all_feature_bits().
*/
typedef struct {
uint flags_edx; /**< feature flags stored in edx */
uint flags_ecx; /**< feature flags stored in ecx */
uint ext_flags_edx; /**< extended feature flags stored in edx */
uint ext_flags_ecx; /**< extended feature flags stored in ecx */
} features_t;
/**
* Feature bits returned by cpuid. Pass one of these values to proc_has_feature() to
* determine whether the underlying processor has the feature.
*/
typedef enum {
/* features returned in edx */
FEATURE_FPU = 0, /**< Floating-point unit on chip */
FEATURE_VME = 1, /**< Virtual Mode Extension */
FEATURE_DE = 2, /**< Debugging Extension */
FEATURE_PSE = 3, /**< Page Size Extension */
FEATURE_TSC = 4, /**< Time-Stamp Counter */
FEATURE_MSR = 5, /**< Model Specific Registers */
FEATURE_PAE = 6, /**< Physical Address Extension */
FEATURE_MCE = 7, /**< Machine Check Exception */
FEATURE_CX8 = 8, /**< CMPXCHG8 Instruction Supported */
FEATURE_APIC = 9, /**< On-chip APIC Hardware Supported */
FEATURE_SEP = 11, /**< Fast System Call */
FEATURE_MTRR = 12, /**< Memory Type Range Registers */
FEATURE_PGE = 13, /**< Page Global Enable */
FEATURE_MCA = 14, /**< Machine Check Architecture */
FEATURE_CMOV = 15, /**< Conditional Move Instruction */
FEATURE_PAT = 16, /**< Page Attribute Table */
FEATURE_PSE_36 = 17, /**< 36-bit Page Size Extension */
FEATURE_PSN = 18, /**< Processor serial # present & enabled */
FEATURE_CLFSH = 19, /**< CLFLUSH Instruction supported */
FEATURE_DS = 21, /**< Debug Store */
FEATURE_ACPI = 22, /**< Thermal monitor & SCC supported */
FEATURE_MMX = 23, /**< MMX technology supported */
FEATURE_FXSR = 24, /**< Fast FP save and restore */
FEATURE_SSE = 25, /**< SSE Extensions supported */
FEATURE_SSE2 = 26, /**< SSE2 Extensions supported */
FEATURE_SS = 27, /**< Self-snoop */
FEATURE_HTT = 28, /**< Hyper-threading Technology */
FEATURE_TM = 29, /**< Thermal Monitor supported */
FEATURE_IA64 = 30, /**< IA64 Capabilities */
FEATURE_PBE = 31, /**< Pending Break Enable */
/* features returned in ecx */
FEATURE_SSE3 = 0 + 32, /**< SSE3 Extensions supported */
FEATURE_PCLMULQDQ = 1 + 32, /**< OP_pclmulqdq supported */
FEATURE_MONITOR = 3 + 32, /**< MONITOR/MWAIT instructions supported */
FEATURE_DS_CPL = 4 + 32, /**< CPL Qualified Debug Store */
FEATURE_VMX = 5 + 32, /**< Virtual Machine Extensions */
FEATURE_EST = 7 + 32, /**< Enhanced Speedstep Technology */
FEATURE_TM2 = 8 + 32, /**< Thermal Monitor 2 */
FEATURE_SSSE3 = 9 + 32, /**< SSSE3 Extensions supported */
FEATURE_CID = 10 + 32, /**< Context ID */
FEATURE_FMA = 12 + 32, /**< FMA instructions supported */
FEATURE_CX16 = 13 + 32, /**< CMPXCHG16B instruction supported */
FEATURE_xPTR = 14 + 32, /**< Send Task Priority Messages */
FEATURE_SSE41 = 19 + 32, /**< SSE4.1 Extensions supported */
FEATURE_SSE42 = 20 + 32, /**< SSE4.2 Extensions supported */
FEATURE_MOVBE = 22 + 32, /**< OP_movbe supported */
FEATURE_POPCNT = 23 + 32, /**< OP_popcnt supported */
FEATURE_AES = 25 + 32, /**< AES instructions supported */
FEATURE_XSAVE = 26 + 32, /**< OP_xsave* supported */
FEATURE_OSXSAVE = 27 + 32, /**< OP_xgetbv supported in user mode */
FEATURE_AVX = 28 + 32, /**< AVX instructions supported */
/* extended features returned in edx */
FEATURE_SYSCALL = 11 + 64, /**< SYSCALL/SYSRET instructions supported */
FEATURE_XD_Bit = 20 + 64, /**< Execution Disable bit */
FEATURE_EM64T = 29 + 64, /**< Extended Memory 64 Technology */
/* extended features returned in ecx */
FEATURE_LAHF = 0 + 96 /**< LAHF/SAHF available in 64-bit mode */
} feature_bit_t;
/**
* L1 and L2 cache sizes, used by proc_get_L1_icache_size(),
* proc_get_L1_dcache_size(), proc_get_L2_cache_size(), and
* proc_get_cache_size_str().
*/
#ifdef AVOID_API_EXPORT
/* Make sure to keep this in sync with proc_get_cache_size_str() in proc.c */
#endif
typedef enum {
CACHE_SIZE_8_KB, /**< L1 or L2 cache size of 8 KB. */
CACHE_SIZE_16_KB, /**< L1 or L2 cache size of 16 KB. */
CACHE_SIZE_32_KB, /**< L1 or L2 cache size of 32 KB. */
CACHE_SIZE_64_KB, /**< L1 or L2 cache size of 64 KB. */
CACHE_SIZE_128_KB, /**< L1 or L2 cache size of 128 KB. */
CACHE_SIZE_256_KB, /**< L1 or L2 cache size of 256 KB. */
CACHE_SIZE_512_KB, /**< L1 or L2 cache size of 512 KB. */
CACHE_SIZE_1_MB, /**< L1 or L2 cache size of 1 MB. */
CACHE_SIZE_2_MB, /**< L1 or L2 cache size of 2 MB. */
CACHE_SIZE_UNKNOWN /**< Unknown L1 or L2 cache size. */
} cache_size_t;
/* DR_API EXPORT END */
/* exported for efficient access */
extern size_t cache_line_size;
#define CACHE_LINE_SIZE() cache_line_size
/* xcr0 and xstate_bv feature bits */
enum {
XCR0_AVX = 4,
XCR0_SSE = 2,
XCR0_FP = 1,
};
void proc_init(void);
DR_API
/** Returns the cache line size in bytes of the processor. */
size_t
proc_get_cache_line_size(void);
DR_API
/** Returns true only if \p addr is cache-line-aligned. */
bool
proc_is_cache_aligned(void *addr);
void
machine_cache_sync(void *pc_start, void *pc_end, bool flush_icache);
DR_API
/** Returns n >= \p sz such that n is a multiple of the cache line size. */
ptr_uint_t
proc_bump_to_end_of_cache_line(ptr_uint_t sz);
DR_API
/** Returns n <= \p addr such that n is a multiple of the page size. */
void *
proc_get_containing_page(void *addr);
DR_API
/** Returns one of the VENDOR_ constants. */
uint
proc_get_vendor(void);
DR_API
/**
* Sets the vendor to the given VENDOR_ constant.
* This function is supplied to support decoding or encoding with respect to
* other than the current processor being executed on. The change in vendor
* will be seen by the decoder and encoder, as well as the rest of the
* system.
* \return the prior vendor, or -1 on an invalid argument.
*/
int
proc_set_vendor(uint new_vendor);
DR_API
/**
* Returns the processor family as given by the cpuid instruction,
* adjusted by the extended family as described in the Intel documentation.
* The FAMILY_ constants identify important family values.
*/
uint
proc_get_family(void);
DR_API
/** Returns the processor type as given by the cpuid instruction. */
uint
proc_get_type(void);
DR_API
/**
* Returns the processor model as given by the cpuid instruction,
* adjusted by the extended model as described in the Intel documentation.
* The MODEL_ constants identify important model values.
*/
uint
proc_get_model(void);
DR_API
/** Returns the processor stepping ID. */
uint
proc_get_stepping(void);
DR_API
/** Tests if processor has selected feature. */
bool
proc_has_feature(feature_bit_t feature);
DR_API
/**
* Returns all 4 32-bit feature values. Use proc_has_feature to test
* for specific features.
*/
features_t *
proc_get_all_feature_bits(void);
DR_API
/** Returns the processor brand string as given by the cpuid instruction. */
char*
proc_get_brand_string(void);
DR_API
/** Returns the size of the L1 instruction cache. */
cache_size_t
proc_get_L1_icache_size(void);
DR_API
/** Returns the size of the L1 data cache. */
cache_size_t
proc_get_L1_dcache_size(void);
DR_API
/** Returns the size of the L2 cache. */
cache_size_t
proc_get_L2_cache_size(void);
DR_API
/** Converts a cache_size_t type to a string. */
const char*
proc_get_cache_size_str(cache_size_t size);
DR_API
/**
* Returns the size in bytes needed for a buffer for saving the floating point state.
*/
size_t
proc_fpstate_save_size(void);
DR_API
/**
* Saves the floating point state into the 16-byte-aligned buffer \p buf,
* which must be 512 bytes for processors with the FXSR feature, and
* 108 bytes for those without (where this routine does not support
* 16-bit operand sizing). \note proc_fpstate_save_size() can be used
* to determine the particular size needed.
*
* When the FXSR feature is present, the fxsave format matches the bitwidth
* of the ISA mode of the current thread (see dr_get_isa_mode()).
*
* The last floating-point instruction address is left in an
* untranslated state (i.e., it may point into the code cache).
*
* DR does NOT save the application's floating-point, MMX, or SSE state
* on context switches! Thus if a client performs any floating-point
* operations in its main routines called by DR, the client must save
* and restore the floating-point/MMX/SSE state.
* If the client needs to do so inside the code cache the client should implement
* that itself.
* Returns number of bytes written.
*/
size_t
proc_save_fpstate(byte *buf);
DR_API
/**
* Restores the floating point state from the 16-byte-aligned buffer
* \p buf, which must be 512 bytes for processors with the FXSR feature,
* and 108 bytes for those without (where this routine does not
* support 16-bit operand sizing). \note proc_fpstate_save_size() can
* be used to determine the particular size needed.
*
* When the FXSR feature is present, the fxsave format matches the bitwidth
* of the ISA mode of the current thread (see dr_get_isa_mode()).
*/
void
proc_restore_fpstate(byte *buf);
DR_API
/** Returns whether AVX is enabled by both the processor and the operating system.
* Even if the processor supports AVX, if the operating system does not enable
* AVX state saving, then AVX instructions will fault.
*/
bool
proc_avx_enabled(void);
#endif /* _PROC_H_ */