diff --git a/contrib/libcpuid/include/libcpuid/amd_code_t.h b/contrib/libcpuid/include/libcpuid/amd_code_t.h
new file mode 100644
index 00000000000..2472a3d61d5
--- /dev/null
+++ b/contrib/libcpuid/include/libcpuid/amd_code_t.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016 Veselin Georgiev,
+ * anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * This file contains a list of internal codes we use in detection. It is
+ * of no external use and isn't a complete list of AMD products.
+ */
+ CODE2(OPTERON_GENERIC, 1000),
+ CODE(OPTERON_800),
+ CODE(ATHLON_XP),
+ CODE(ATHLON_XP_M),
+ CODE(ATHLON_XP_M_LV),
+ CODE(ATHLON),
+ CODE(ATHLON_MP),
+ CODE(MOBILE_ATHLON64),
+ CODE(ATHLON_FX),
+ CODE(DURON),
+ CODE(DURON_MP),
+ CODE(MOBILE_DURON),
+ CODE(MOBILE_SEMPRON),
+ CODE(OPTERON_SINGLE),
+ CODE(OPTERON_DUALCORE),
+ CODE(OPTERON_800_DUALCORE),
+ CODE(MOBILE_TURION),
+ CODE(ATHLON_64),
+ CODE(ATHLON_64_FX),
+ CODE(TURION_64),
+ CODE(TURION_X2),
+ CODE(SEMPRON),
+ CODE(M_SEMPRON),
+ CODE(SEMPRON_DUALCORE),
+ CODE(PHENOM),
+ CODE(PHENOM2),
+ CODE(ATHLON_64_X2),
+ CODE(ATHLON_64_X3),
+ CODE(ATHLON_64_X4),
+ CODE(FUSION_C),
+ CODE(FUSION_E),
+ CODE(FUSION_EA),
+ CODE(FUSION_Z),
+ CODE(FUSION_A),
+
diff --git a/contrib/libcpuid/include/libcpuid/asm-bits.c b/contrib/libcpuid/include/libcpuid/asm-bits.c
index ca936f2abf5..b8e32284f57 100644
--- a/contrib/libcpuid/include/libcpuid/asm-bits.c
+++ b/contrib/libcpuid/include/libcpuid/asm-bits.c
@@ -75,13 +75,13 @@ int cpuid_exists_by_eflags(void)
#endif /* PLATFORM_X86 */
}
+#ifdef INLINE_ASM_SUPPORTED
/*
* with MSVC/AMD64, the exec_cpuid() and cpu_rdtsc() functions
* are implemented in separate .asm files. Otherwise, use inline assembly
*/
void exec_cpuid(uint32_t *regs)
{
-#ifdef INLINE_ASM_SUPPORTED
#ifdef COMPILER_GCC
# ifdef PLATFORM_X64
__asm __volatile(
@@ -166,8 +166,8 @@ void exec_cpuid(uint32_t *regs)
# error "Unsupported compiler"
# endif /* COMPILER_MICROSOFT */
#endif
-#endif /* INLINE_ASSEMBLY_SUPPORTED */
}
+#endif /* INLINE_ASSEMBLY_SUPPORTED */
#ifdef INLINE_ASM_SUPPORTED
void cpu_rdtsc(uint64_t* result)
@@ -214,7 +214,8 @@ void busy_sse_loop(int cycles)
" xorps %%xmm6, %%xmm6\n"
" xorps %%xmm7, %%xmm7\n"
XALIGN
- ".bsLoop:\n"
+ /* ".bsLoop:\n" */
+ "1:\n"
// 0:
" addps %%xmm1, %%xmm0\n"
" addps %%xmm2, %%xmm1\n"
@@ -505,7 +506,8 @@ void busy_sse_loop(int cycles)
" addps %%xmm0, %%xmm7\n"
" dec %%eax\n"
- " jnz .bsLoop\n"
+ /* "jnz .bsLoop\n" */
+ " jnz 1b\n"
::"a"(cycles)
);
#else
diff --git a/contrib/libcpuid/include/libcpuid/config.h b/contrib/libcpuid/include/libcpuid/config.h
index 29b513c4ac1..2326cfeede5 100644
--- a/contrib/libcpuid/include/libcpuid/config.h
+++ b/contrib/libcpuid/include/libcpuid/config.h
@@ -1,2 +1,2 @@
/* Version number of package */
-#define VERSION "0.2.1"
+#define VERSION "0.4.0"
diff --git a/contrib/libcpuid/include/libcpuid/cpuid_main.c b/contrib/libcpuid/include/libcpuid/cpuid_main.c
index 737aa706a37..02a7cb7ad50 100644
--- a/contrib/libcpuid/include/libcpuid/cpuid_main.c
+++ b/contrib/libcpuid/include/libcpuid/cpuid_main.c
@@ -24,11 +24,14 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libcpuid.h"
+#include "libcpuid_internal.h"
#include "recog_intel.h"
#include "recog_amd.h"
#include "asm-bits.h"
#include "libcpuid_util.h"
+//#ifdef HAVE_CONFIG_H // CLICKHOUSE PATCH
#include "config.h"
+//#endif // CLICKHOUSE PATCH
#include
#include
#include
@@ -51,9 +54,9 @@ static void raw_data_t_constructor(struct cpu_raw_data_t* raw)
static void cpu_id_t_constructor(struct cpu_id_t* id)
{
memset(id, 0, sizeof(struct cpu_id_t));
- id->l1_data_cache = id->l1_instruction_cache = id->l2_cache = id->l3_cache = -1;
- id->l1_assoc = id->l2_assoc = id->l3_assoc = -1;
- id->l1_cacheline = id->l2_cacheline = id->l3_cacheline = -1;
+ id->l1_data_cache = id->l1_instruction_cache = id->l2_cache = id->l3_cache = id->l4_cache = -1;
+ id->l1_assoc = id->l2_assoc = id->l3_assoc = id->l4_assoc = -1;
+ id->l1_cacheline = id->l2_cacheline = id->l3_cacheline = id->l4_cacheline = -1;
id->sse_size = -1;
}
@@ -181,14 +184,26 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
};
const struct feature_map_t matchtable_ecx1[] = {
{ 0, CPU_FEATURE_PNI },
+ { 1, CPU_FEATURE_PCLMUL },
{ 3, CPU_FEATURE_MONITOR },
{ 9, CPU_FEATURE_SSSE3 },
{ 12, CPU_FEATURE_FMA3 },
{ 13, CPU_FEATURE_CX16 },
{ 19, CPU_FEATURE_SSE4_1 },
- { 21, CPU_FEATURE_X2APIC },
+ { 20, CPU_FEATURE_SSE4_2 },
+ { 22, CPU_FEATURE_MOVBE },
{ 23, CPU_FEATURE_POPCNT },
+ { 25, CPU_FEATURE_AES },
+ { 26, CPU_FEATURE_XSAVE },
+ { 27, CPU_FEATURE_OSXSAVE },
+ { 28, CPU_FEATURE_AVX },
{ 29, CPU_FEATURE_F16C },
+ { 30, CPU_FEATURE_RDRAND },
+ };
+ const struct feature_map_t matchtable_ebx7[] = {
+ { 3, CPU_FEATURE_BMI1 },
+ { 5, CPU_FEATURE_AVX2 },
+ { 8, CPU_FEATURE_BMI2 },
};
const struct feature_map_t matchtable_edx81[] = {
{ 11, CPU_FEATURE_SYSCALL },
@@ -205,6 +220,9 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
match_features(matchtable_edx1, COUNT_OF(matchtable_edx1), raw->basic_cpuid[1][3], data);
match_features(matchtable_ecx1, COUNT_OF(matchtable_ecx1), raw->basic_cpuid[1][2], data);
}
+ if (raw->basic_cpuid[0][0] >= 7) {
+ match_features(matchtable_ebx7, COUNT_OF(matchtable_ebx7), raw->basic_cpuid[7][1], data);
+ }
if (raw->ext_cpuid[0][0] >= 0x80000001) {
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
@@ -229,10 +247,10 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
}
}
-static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
+static cpu_vendor_t cpuid_vendor_identify(const uint32_t *raw_vendor, char *vendor_str)
{
- int i, j, basic, xmodel, xfamily, ext;
- char brandstr[64] = {0};
+ int i;
+ cpu_vendor_t vendor = VENDOR_UNKNOWN;
const struct { cpu_vendor_t vendor; char match[16]; }
matchtable[NUM_CPU_VENDORS] = {
/* source: http://www.sandpile.org/ia32/cpuid.htm */
@@ -247,18 +265,27 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
{ VENDOR_SIS , "SiS SiS SiS " },
{ VENDOR_NSC , "Geode by NSC" },
};
-
- memcpy(data->vendor_str + 0, &raw->basic_cpuid[0][1], 4);
- memcpy(data->vendor_str + 4, &raw->basic_cpuid[0][3], 4);
- memcpy(data->vendor_str + 8, &raw->basic_cpuid[0][2], 4);
- data->vendor_str[12] = 0;
+
+ memcpy(vendor_str + 0, &raw_vendor[1], 4);
+ memcpy(vendor_str + 4, &raw_vendor[3], 4);
+ memcpy(vendor_str + 8, &raw_vendor[2], 4);
+ vendor_str[12] = 0;
+
/* Determine vendor: */
- data->vendor = VENDOR_UNKNOWN;
for (i = 0; i < NUM_CPU_VENDORS; i++)
- if (!strcmp(data->vendor_str, matchtable[i].match)) {
- data->vendor = matchtable[i].vendor;
+ if (!strcmp(vendor_str, matchtable[i].match)) {
+ vendor = matchtable[i].vendor;
break;
}
+ return vendor;
+}
+
+static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
+{
+ int i, j, basic, xmodel, xfamily, ext;
+ char brandstr[64] = {0};
+ data->vendor = cpuid_vendor_identify(raw->basic_cpuid[0], data->vendor_str);
+
if (data->vendor == VENDOR_UNKNOWN)
return set_error(ERR_CPU_UNKN);
basic = raw->basic_cpuid[0][0];
@@ -347,7 +374,7 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data)
cpu_exec_cpuid(i, data->basic_cpuid[i]);
for (i = 0; i < 32; i++)
cpu_exec_cpuid(0x80000000 + i, data->ext_cpuid[i]);
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < MAX_INTELFN4_LEVEL; i++) {
memset(data->intel_fn4[i], 0, sizeof(data->intel_fn4[i]));
data->intel_fn4[i][0] = 4;
data->intel_fn4[i][2] = i;
@@ -359,6 +386,18 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data)
data->intel_fn11[i][2] = i;
cpu_exec_cpuid_ext(data->intel_fn11[i]);
}
+ for (i = 0; i < MAX_INTELFN12H_LEVEL; i++) {
+ memset(data->intel_fn12h[i], 0, sizeof(data->intel_fn12h[i]));
+ data->intel_fn12h[i][0] = 0x12;
+ data->intel_fn12h[i][2] = i;
+ cpu_exec_cpuid_ext(data->intel_fn12h[i]);
+ }
+ for (i = 0; i < MAX_INTELFN14H_LEVEL; i++) {
+ memset(data->intel_fn14h[i], 0, sizeof(data->intel_fn14h[i]));
+ data->intel_fn14h[i][0] = 0x14;
+ data->intel_fn14h[i][2] = i;
+ cpu_exec_cpuid_ext(data->intel_fn14h[i]);
+ }
return set_error(ERR_OK);
}
@@ -390,6 +429,14 @@ int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
fprintf(f, "intel_fn11[%d]=%08x %08x %08x %08x\n", i,
data->intel_fn11[i][0], data->intel_fn11[i][1],
data->intel_fn11[i][2], data->intel_fn11[i][3]);
+ for (i = 0; i < MAX_INTELFN12H_LEVEL; i++)
+ fprintf(f, "intel_fn12h[%d]=%08x %08x %08x %08x\n", i,
+ data->intel_fn12h[i][0], data->intel_fn12h[i][1],
+ data->intel_fn12h[i][2], data->intel_fn12h[i][3]);
+ for (i = 0; i < MAX_INTELFN14H_LEVEL; i++)
+ fprintf(f, "intel_fn14h[%d]=%08x %08x %08x %08x\n", i,
+ data->intel_fn14h[i][0], data->intel_fn14h[i][1],
+ data->intel_fn14h[i][2], data->intel_fn14h[i][3]);
if (strcmp(filename, ""))
fclose(f);
@@ -434,10 +481,12 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
recognized = 1;
}
syntax = 1;
- syntax = syntax && parse_token("basic_cpuid", token, value, data->basic_cpuid, 32, &recognized);
- syntax = syntax && parse_token("ext_cpuid", token, value, data->ext_cpuid, 32, &recognized);
- syntax = syntax && parse_token("intel_fn4", token, value, data->intel_fn4, 4, &recognized);
- syntax = syntax && parse_token("intel_fn11", token, value, data->intel_fn11, 4, &recognized);
+ syntax = syntax && parse_token("basic_cpuid", token, value, data->basic_cpuid, MAX_CPUID_LEVEL, &recognized);
+ syntax = syntax && parse_token("ext_cpuid", token, value, data->ext_cpuid, MAX_EXT_CPUID_LEVEL, &recognized);
+ syntax = syntax && parse_token("intel_fn4", token, value, data->intel_fn4, MAX_INTELFN4_LEVEL, &recognized);
+ syntax = syntax && parse_token("intel_fn11", token, value, data->intel_fn11, MAX_INTELFN11_LEVEL, &recognized);
+ syntax = syntax && parse_token("intel_fn12h", token, value, data->intel_fn12h, MAX_INTELFN12H_LEVEL, &recognized);
+ syntax = syntax && parse_token("intel_fn14h", token, value, data->intel_fn14h, MAX_INTELFN14H_LEVEL, &recognized);
if (!syntax) {
warnf("Error: %s:%d: Syntax error\n", filename, cur_line);
fclose(f);
@@ -453,7 +502,7 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
return set_error(ERR_OK);
}
-int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
+int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
{
int r;
struct cpu_raw_data_t myraw;
@@ -467,10 +516,10 @@ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
return set_error(r);
switch (data->vendor) {
case VENDOR_INTEL:
- r = cpuid_identify_intel(raw, data);
+ r = cpuid_identify_intel(raw, data, internal);
break;
case VENDOR_AMD:
- r = cpuid_identify_amd(raw, data);
+ r = cpuid_identify_amd(raw, data, internal);
break;
default:
break;
@@ -478,6 +527,12 @@ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
return set_error(r);
}
+int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
+{
+ struct internal_id_info_t throwaway;
+ return cpu_ident_internal(raw, data, &throwaway);
+}
+
const char* cpu_feature_str(cpu_feature_t feature)
{
const struct { cpu_feature_t feature; const char* name; }
@@ -577,6 +632,21 @@ const char* cpu_feature_str(cpu_feature_t feature)
{ CPU_FEATURE_PFI, "pfi" },
{ CPU_FEATURE_PA, "pa" },
{ CPU_FEATURE_AVX2, "avx2" },
+ { CPU_FEATURE_BMI1, "bmi1" },
+ { CPU_FEATURE_BMI2, "bmi2" },
+ { CPU_FEATURE_HLE, "hle" },
+ { CPU_FEATURE_RTM, "rtm" },
+ { CPU_FEATURE_AVX512F, "avx512f" },
+ { CPU_FEATURE_AVX512DQ, "avx512dq" },
+ { CPU_FEATURE_AVX512PF, "avx512pf" },
+ { CPU_FEATURE_AVX512ER, "avx512er" },
+ { CPU_FEATURE_AVX512CD, "avx512cd" },
+ { CPU_FEATURE_SHA_NI, "sha_ni" },
+ { CPU_FEATURE_AVX512BW, "avx512bw" },
+ { CPU_FEATURE_AVX512VL, "avx512vl" },
+ { CPU_FEATURE_SGX, "sgx" },
+ { CPU_FEATURE_RDSEED, "rdseed" },
+ { CPU_FEATURE_ADX, "adx" },
};
unsigned i, n = COUNT_OF(matchtable);
if (n != NUM_CPU_FEATURES) {
@@ -600,6 +670,15 @@ const char* cpuid_error(void)
{ ERR_BADFMT , "Bad file format"},
{ ERR_NOT_IMP , "Not implemented"},
{ ERR_CPU_UNKN , "Unsupported processor"},
+ { ERR_NO_RDMSR , "RDMSR instruction is not supported"},
+ { ERR_NO_DRIVER, "RDMSR driver error (generic)"},
+ { ERR_NO_PERMS , "No permissions to install RDMSR driver"},
+ { ERR_EXTRACT , "Cannot extract RDMSR driver (read only media?)"},
+ { ERR_HANDLE , "Bad handle"},
+ { ERR_INVMSR , "Invalid MSR"},
+ { ERR_INVCNB , "Invalid core number"},
+ { ERR_HANDLE_R , "Error on handle read"},
+ { ERR_INVRANGE , "Invalid given range"},
};
unsigned i;
for (i = 0; i < COUNT_OF(matchtable); i++)
@@ -626,6 +705,23 @@ void cpuid_set_verbosiness_level(int level)
_current_verboselevel = level;
}
+cpu_vendor_t cpuid_get_vendor(void)
+{
+ static cpu_vendor_t vendor = VENDOR_UNKNOWN;
+ uint32_t raw_vendor[4];
+ char vendor_str[VENDOR_STR_MAX];
+
+ if(vendor == VENDOR_UNKNOWN) {
+ if (!cpuid_present())
+ set_error(ERR_NO_CPUID);
+ else {
+ cpu_exec_cpuid(0, raw_vendor);
+ vendor = cpuid_vendor_identify(raw_vendor, vendor_str);
+ }
+ }
+ return vendor;
+}
+
void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list)
{
switch (vendor) {
diff --git a/contrib/libcpuid/include/libcpuid/intel_code_t.h b/contrib/libcpuid/include/libcpuid/intel_code_t.h
new file mode 100644
index 00000000000..c50ec9c5a83
--- /dev/null
+++ b/contrib/libcpuid/include/libcpuid/intel_code_t.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2016 Veselin Georgiev,
+ * anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * This file contains a list of internal codes we use in detection. It is
+ * of no external use and isn't a complete list of intel products.
+ */
+ CODE2(PENTIUM, 2000),
+ CODE(MOBILE_PENTIUM),
+
+ CODE(XEON),
+ CODE(XEON_IRWIN),
+ CODE(XEONMP),
+ CODE(XEON_POTOMAC),
+ CODE(XEON_I7),
+ CODE(XEON_GAINESTOWN),
+ CODE(XEON_WESTMERE),
+
+ CODE(MOBILE_PENTIUM_M),
+ CODE(CELERON),
+ CODE(MOBILE_CELERON),
+ CODE(NOT_CELERON),
+
+
+ CODE(CORE_SOLO),
+ CODE(MOBILE_CORE_SOLO),
+ CODE(CORE_DUO),
+ CODE(MOBILE_CORE_DUO),
+
+ CODE(WOLFDALE),
+ CODE(MEROM),
+ CODE(PENRYN),
+ CODE(QUAD_CORE),
+ CODE(DUAL_CORE_HT),
+ CODE(QUAD_CORE_HT),
+ CODE(MORE_THAN_QUADCORE),
+ CODE(PENTIUM_D),
+
+ CODE(ATOM_UNKNOWN),
+ CODE(ATOM_SILVERTHORNE),
+ CODE(ATOM_DIAMONDVILLE),
+ CODE(ATOM_PINEVIEW),
+ CODE(ATOM_CEDARVIEW),
+
+ CODE(CORE_I3),
+ CODE(CORE_I5),
+ CODE(CORE_I7),
+ CODE(CORE_IVY3), /* 22nm Core-iX */
+ CODE(CORE_IVY5),
+ CODE(CORE_IVY7),
+ CODE(CORE_HASWELL3), /* 22nm Core-iX, Haswell */
+ CODE(CORE_HASWELL5),
+ CODE(CORE_HASWELL7),
+ CODE(CORE_BROADWELL3), /* 14nm Core-iX, Broadwell */
+ CODE(CORE_BROADWELL5),
+ CODE(CORE_BROADWELL7),
+ CODE(CORE_SKYLAKE3), /* 14nm Core-iX, Skylake */
+ CODE(CORE_SKYLAKE5),
+ CODE(CORE_SKYLAKE7),
+
diff --git a/contrib/libcpuid/include/libcpuid/libcpuid.h b/contrib/libcpuid/include/libcpuid/libcpuid.h
index b78b0d6f514..866c0e8441d 100644
--- a/contrib/libcpuid/include/libcpuid/libcpuid.h
+++ b/contrib/libcpuid/include/libcpuid/libcpuid.h
@@ -26,25 +26,37 @@
#ifndef __LIBCPUID_H__
#define __LIBCPUID_H__
/**
- * @File libcpuid.h
- * @Author Veselin Georgiev
- * @Date Oct 2008
- * @Version 0.2.1
+ * \file libcpuid.h
+ * \author Veselin Georgiev
+ * \date Oct 2008
+ * \version 0.4.0
*
* Version history:
*
- * 0.1.0 (2008-10-15): initial adaptation from wxfractgui sources
- * 0.1.1 (2009-07-06): Added intel_fn11 fields to cpu_raw_data_t to handle
- * new processor topology enumeration required on Core i7
- * 0.1.2 (2009-09-26): Added support for MSR reading through self-extracting
- * kernel driver on Win32.
- * 0.1.3 (2010-04-20): Added support for greater more accurate CPU clock
- * measurements with cpu_clock_by_ic()
- * 0.2.0 (2011-10-11): Support for AMD Bulldozer CPUs, 128-bit SSE unit size
- * checking. A backwards-incompatible change, since the
- * sizeof cpu_id_t is now different.
- * 0.2.1 (2012-05-26): Support for Ivy Bridge, and detecting the presence of
- * the RdRand instruction.
+ * * 0.1.0 (2008-10-15): initial adaptation from wxfractgui sources
+ * * 0.1.1 (2009-07-06): Added intel_fn11 fields to cpu_raw_data_t to handle
+ * new processor topology enumeration required on Core i7
+ * * 0.1.2 (2009-09-26): Added support for MSR reading through self-extracting
+ * kernel driver on Win32.
+ * * 0.1.3 (2010-04-20): Added support for greater more accurate CPU clock
+ * measurements with cpu_clock_by_ic()
+ * * 0.2.0 (2011-10-11): Support for AMD Bulldozer CPUs, 128-bit SSE unit size
+ * checking. A backwards-incompatible change, since the
+ * sizeof cpu_id_t is now different.
+ * * 0.2.1 (2012-05-26): Support for Ivy Bridge, and detecting the presence of
+ * the RdRand instruction.
+ * * 0.2.2 (2015-11-04): Support for newer processors up to Haswell and Vishera.
+ * Fix clock detection in cpu_clock_by_ic() for Bulldozer.
+ * More entries supported in cpu_msrinfo().
+ * *BSD and Solaris support (unofficial).
+ * * 0.3.0 (2016-07-09): Support for Skylake; MSR ops in FreeBSD; INFO_VOLTAGE
+ * for AMD CPUs. Level 4 cache support for Crystalwell
+ * (a backwards-incompatible change since the sizeof
+ * cpu_raw_data_t is now different).
+ * * 0.4.0 (2016-09-30): Better detection of AMD clock multiplier with msrinfo.
+ * Support for Intel SGX detection
+ * (a backwards-incompatible change since the sizeof
+ * cpu_raw_data_t and cpu_id_t is now different).
*/
/** @mainpage A simple libcpuid introduction
@@ -57,6 +69,15 @@
* To fetch the CPUID info needed for CPU identification, use
* \ref cpuid_get_raw_data
* To make sense of that data (decode, extract features), use \ref cpu_identify
+ * To detect the CPU speed, use either \ref cpu_clock, \ref cpu_clock_by_os,
+ * \ref cpu_tsc_mark + \ref cpu_tsc_unmark + \ref cpu_clock_by_mark,
+ * \ref cpu_clock_measure or \ref cpu_clock_by_ic.
+ * Read carefully for pros/cons of each method.
+ *
+ * To read MSRs, use \ref cpu_msr_driver_open to get a handle, and then
+ * \ref cpu_rdmsr for querying abilities. Some MSR decoding is available on recent
+ * CPUs, and can be queried through \ref cpu_msrinfo; the various types of queries
+ * are described in \ref cpu_msrinfo_request_t.
*
*/
@@ -116,6 +137,81 @@ struct cpu_raw_data_t {
enumeration leaf), this stores the result of CPUID with
eax = 11 and ecx = 0, 1, 2... */
uint32_t intel_fn11[MAX_INTELFN11_LEVEL][4];
+
+ /** when the CPU is intel and supports leaf 12h (SGX enumeration leaf),
+ * this stores the result of CPUID with eax = 0x12 and
+ * ecx = 0, 1, 2... */
+ uint32_t intel_fn12h[MAX_INTELFN12H_LEVEL][4];
+
+ /** when the CPU is intel and supports leaf 14h (Intel Processor Trace
+ * capabilities leaf).
+ * this stores the result of CPUID with eax = 0x12 and
+ * ecx = 0, 1, 2... */
+ uint32_t intel_fn14h[MAX_INTELFN14H_LEVEL][4];
+};
+
+/**
+ * @brief This contains information about SGX features of the processor
+ * Example usage:
+ * @code
+ * ...
+ * struct cpu_raw_data_t raw;
+ * struct cpu_id_t id;
+ *
+ * if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0 && id.sgx.present) {
+ * printf("SGX is present.\n");
+ * printf("SGX1 instructions: %s.\n", id.sgx.flags[INTEL_SGX1] ? "present" : "absent");
+ * printf("SGX2 instructions: %s.\n", id.sgx.flags[INTEL_SGX2] ? "present" : "absent");
+ * printf("Max 32-bit enclave size: 2^%d bytes.\n", id.sgx.max_enclave_32bit);
+ * printf("Max 64-bit enclave size: 2^%d bytes.\n", id.sgx.max_enclave_64bit);
+ * for (int i = 0; i < id.sgx.num_epc_sections; i++) {
+ * struct cpu_epc_t epc = cpuid_get_epc(i, NULL);
+ * printf("EPC section #%d: address = %x, size = %d bytes.\n", epc.address, epc.size);
+ * }
+ * } else {
+ * printf("SGX is not present.\n");
+ * }
+ * @endcode
+ */
+struct cpu_sgx_t {
+ /** Whether SGX is present (boolean) */
+ uint32_t present;
+
+ /** Max enclave size in 32-bit mode. This is a power-of-two value:
+ * if it is "31", then the max enclave size is 2^31 bytes (2 GiB).
+ */
+ uint8_t max_enclave_32bit;
+
+ /** Max enclave size in 64-bit mode. This is a power-of-two value:
+ * if it is "36", then the max enclave size is 2^36 bytes (64 GiB).
+ */
+ uint8_t max_enclave_64bit;
+
+ /**
+ * contains SGX feature flags. See the \ref cpu_sgx_feature_t
+ * "INTEL_SGX*" macros below.
+ */
+ uint8_t flags[SGX_FLAGS_MAX];
+
+ /** number of Enclave Page Cache (EPC) sections. Info for each
+ * section is available through the \ref cpuid_get_epc() function
+ */
+ int num_epc_sections;
+
+ /** bit vector of the supported extended features that can be written
+ * to the MISC region of the SSA (Save State Area)
+ */
+ uint32_t misc_select;
+
+ /** a bit vector of the attributes that can be set to SECS.ATTRIBUTES
+ * via ECREATE. Corresponds to bits 0-63 (incl.) of SECS.ATTRIBUTES.
+ */
+ uint64_t secs_attributes;
+
+ /** a bit vector of the bits that can be set in the XSAVE feature
+ * request mask; Corresponds to bits 64-127 of SECS.ATTRIBUTES.
+ */
+ uint64_t secs_xfrm;
};
/**
@@ -133,7 +229,8 @@ struct cpu_id_t {
/**
* contain CPU flags. Used to test for features. See
- * the CPU_FEATURE_* macros below. @see Features
+ * the \ref cpu_feature_t "CPU_FEATURE_*" macros below.
+ * @see Features
*/
uint8_t flags[CPU_FLAGS_MAX];
@@ -164,11 +261,17 @@ struct cpu_id_t {
/**
* The total number of logical processors.
+ * The same value is availabe through \ref cpuid_get_total_cpus.
*
* This is num_logical_cpus * {total physical processors in the system}
+ * (but only on a real system, under a VM this number may be lower).
*
* If you're writing a multithreaded program and you want to run it on
* all CPUs, this is the number of threads you need.
+ *
+ * @note in a VM, this will exactly match the number of CPUs set in
+ * the VM's configuration.
+ *
*/
int32_t total_logical_cpus;
@@ -194,6 +297,9 @@ struct cpu_id_t {
/** L3 cache size in KB. Zero on most systems */
int32_t l3_cache;
+
+ /** L4 cache size in KB. Zero on most systems */
+ int32_t l4_cache;
/** Cache associativity for the L1 data cache. -1 if undetermined */
int32_t l1_assoc;
@@ -203,6 +309,9 @@ struct cpu_id_t {
/** Cache associativity for the L3 cache. -1 if undetermined */
int32_t l3_assoc;
+
+ /** Cache associativity for the L4 cache. -1 if undetermined */
+ int32_t l4_assoc;
/** Cache-line size for L1 data cache. -1 if undetermined */
int32_t l1_cacheline;
@@ -213,6 +322,9 @@ struct cpu_id_t {
/** Cache-line size for L3 cache. -1 if undetermined */
int32_t l3_cacheline;
+ /** Cache-line size for L4 cache. -1 if undetermined */
+ int32_t l4_cacheline;
+
/**
* The brief and human-friendly CPU codename, which was recognized.
* Examples:
@@ -234,9 +346,13 @@ struct cpu_id_t {
/**
* contain miscellaneous detection information. Used to test about specifics of
- * certain detected features. See CPU_HINT_* macros below. @see Hints
+ * certain detected features. See \ref cpu_hint_t "CPU_HINT_*" macros below.
+ * @see Hints
*/
uint8_t detection_hints[CPU_HINTS_MAX];
+
+ /** contains information about SGX features if the processor, if present */
+ struct cpu_sgx_t sgx;
};
/**
@@ -355,6 +471,21 @@ typedef enum {
CPU_FEATURE_PFI, /*!< Processor Feedback Interface support */
CPU_FEATURE_PA, /*!< Processor accumulator */
CPU_FEATURE_AVX2, /*!< AVX2 instructions */
+ CPU_FEATURE_BMI1, /*!< BMI1 instructions */
+ CPU_FEATURE_BMI2, /*!< BMI2 instructions */
+ CPU_FEATURE_HLE, /*!< Hardware Lock Elision prefixes */
+ CPU_FEATURE_RTM, /*!< Restricted Transactional Memory instructions */
+ CPU_FEATURE_AVX512F, /*!< AVX-512 Foundation */
+ CPU_FEATURE_AVX512DQ, /*!< AVX-512 Double/Quad granular insns */
+ CPU_FEATURE_AVX512PF, /*!< AVX-512 Prefetch */
+ CPU_FEATURE_AVX512ER, /*!< AVX-512 Exponential/Reciprocal */
+ CPU_FEATURE_AVX512CD, /*!< AVX-512 Conflict detection */
+ CPU_FEATURE_SHA_NI, /*!< SHA-1/SHA-256 instructions */
+ CPU_FEATURE_AVX512BW, /*!< AVX-512 Byte/Word granular insns */
+ CPU_FEATURE_AVX512VL, /*!< AVX-512 128/256 vector length extensions */
+ CPU_FEATURE_SGX, /*!< SGX extensions. Non-autoritative, check cpu_id_t::sgx::present to verify presence */
+ CPU_FEATURE_RDSEED, /*!< RDSEED instruction */
+ CPU_FEATURE_ADX, /*!< ADX extensions (arbitrary precision) */
/* termination: */
NUM_CPU_FEATURES,
} cpu_feature_t;
@@ -370,6 +501,36 @@ typedef enum {
NUM_CPU_HINTS,
} cpu_hint_t;
+/**
+ * @brief SGX features flags
+ * \see cpu_sgx_t
+ *
+ * Usage:
+ * @code
+ * ...
+ * struct cpu_raw_data_t raw;
+ * struct cpu_id_t id;
+ * if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0 && id.sgx.present) {
+ * if (id.sgx.flags[INTEL_SGX1])
+ * // The CPU has SGX1 instructions support...
+ * ...
+ * } else {
+ * // no SGX
+ * }
+ * } else {
+ * // processor cannot be determined.
+ * }
+ * @endcode
+ */
+
+typedef enum {
+ INTEL_SGX1, /*!< SGX1 instructions support */
+ INTEL_SGX2, /*!< SGX2 instructions support */
+
+ /* termination: */
+ NUM_SGX_FEATURES,
+} cpu_sgx_feature_t;
+
/**
* @brief Describes common library error codes
*/
@@ -387,7 +548,10 @@ typedef enum {
ERR_NO_PERMS = -10, /*!< "No permissions to install RDMSR driver" */
ERR_EXTRACT = -11, /*!< "Cannot extract RDMSR driver (read only media?)" */
ERR_HANDLE = -12, /*!< "Bad handle" */
- ERR_INVMSR = -13, /*!< "Invalid MSR" */
+ ERR_INVMSR = -13, /*!< "Invalid MSR" */
+ ERR_INVCNB = -14, /*!< "Invalid core number" */
+ ERR_HANDLE_R = -15, /*!< "Error on handle read" */
+ ERR_INVRANGE = -16, /*!< "Invalid given range" */
} cpu_error_t;
/**
@@ -400,8 +564,14 @@ struct cpu_mark_t {
};
/**
- * @brief Returns the total number of CPUs even if CPUID is not present
- * @retval Number of CPUs available
+ * @brief Returns the total number of logical CPU threads (even if CPUID is not present).
+ *
+ * Under VM, this number (and total_logical_cpus, since they are fetched with the same code)
+ * may be nonsensical, i.e. might not equal NumPhysicalCPUs*NumCoresPerCPU*HyperThreading.
+ * This is because no matter how many logical threads the host machine has, you may limit them
+ * in the VM to any number you like. **This** is the number returned by cpuid_get_total_cpus().
+ *
+ * @returns Number of logical CPU threads available. Equals the \ref cpu_id_t::total_logical_cpus.
*/
int cpuid_get_total_cpus(void);
@@ -713,6 +883,32 @@ int cpu_clock_by_ic(int millis, int runs);
*/
int cpu_clock(void);
+
+/**
+ * @brief The return value of cpuid_get_epc().
+ * @details
+ * Describes an EPC (Enclave Page Cache) layout (physical address and size).
+ * A CPU may have one or more EPC areas, and information about each is
+ * fetched via \ref cpuid_get_epc.
+ */
+struct cpu_epc_t {
+ uint64_t start_addr;
+ uint64_t length;
+};
+
+/**
+ * @brief Fetches information about an EPC (Enclave Page Cache) area.
+ * @param index - zero-based index, valid range [0..cpu_id_t.egx.num_epc_sections)
+ * @param raw - a pointer to fetched raw CPUID data. Needed only for testing,
+ * you can safely pass NULL here (if you pass a real structure,
+ * it will be used for fetching the leaf 12h data if index < 2;
+ * otherwise the real CPUID instruction will be used).
+ * @returns the requested data. If the CPU doesn't support SGX, or if
+ * index >= cpu_id_t.egx.num_epc_sections, both fields of the returned
+ * structure will be zeros.
+ */
+struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw);
+
/**
* @brief Returns the libcpuid version
*
@@ -750,6 +946,14 @@ libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t warn_fun);
void cpuid_set_verbosiness_level(int level);
+/**
+ * @brief Obtains the CPU vendor from CPUID from the current CPU
+ * @note The result is cached.
+ * @returns VENDOR_UNKNOWN if failed, otherwise the CPU vendor type.
+ * @see cpu_vendor_t
+ */
+cpu_vendor_t cpuid_get_vendor(void);
+
/**
* @brief a structure that holds a list of processor names
*/
@@ -788,6 +992,7 @@ void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list);
*/
void cpuid_free_cpu_list(struct cpu_list_t* list);
+struct msr_driver_t;
/**
* @brief Starts/opens a driver, needed to read MSRs (Model Specific Registers)
*
@@ -799,9 +1004,23 @@ void cpuid_free_cpu_list(struct cpu_list_t* list);
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
-struct msr_driver_t;
struct msr_driver_t* cpu_msr_driver_open(void);
+/**
+ * @brief Similar to \ref cpu_msr_driver_open, but accept one parameter
+ *
+ * This function works on certain operating systems (GNU/Linux, FreeBSD)
+ *
+ * @param core_num specify the core number for MSR.
+ * The first core number is 0.
+ * The last core number is \ref cpuid_get_total_cpus - 1.
+ *
+ * @returns a handle to the driver on success, and NULL on error.
+ * The error message can be obtained by calling \ref cpuid_error.
+ * @see cpu_error_t
+ */
+struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num);
+
/**
* @brief Reads a Model-Specific Register (MSR)
*
@@ -826,26 +1045,51 @@ struct msr_driver_t* cpu_msr_driver_open(void);
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
-int cpu_rdmsr(struct msr_driver_t* handle, int msr_index, uint64_t* result);
+int cpu_rdmsr(struct msr_driver_t* handle, uint32_t msr_index, uint64_t* result);
typedef enum {
INFO_MPERF, /*!< Maximum performance frequency clock. This
is a counter, which increments as a
- proportion of the actual processor speed */
+ proportion of the actual processor speed. */
INFO_APERF, /*!< Actual performance frequency clock. This
accumulates the core clock counts when the
core is active. */
+ INFO_MIN_MULTIPLIER, /*!< Minimum CPU:FSB ratio for this CPU,
+ multiplied by 100. */
INFO_CUR_MULTIPLIER, /*!< Current CPU:FSB ratio, multiplied by 100.
e.g., a CPU:FSB value of 18.5 reads as
- 1850. */
- INFO_MAX_MULTIPLIER, /*!< Maxumum CPU:FSB ratio for this CPU,
- multiplied by 100 */
- INFO_TEMPERATURE, /*!< The current core temperature in Celsius */
+ "1850". */
+ INFO_MAX_MULTIPLIER, /*!< Maximum CPU:FSB ratio for this CPU,
+ multiplied by 100. */
+ INFO_TEMPERATURE, /*!< The current core temperature in Celsius. */
INFO_THROTTLING, /*!< 1 if the current logical processor is
throttling. 0 if it is running normally. */
+ INFO_VOLTAGE, /*!< The current core voltage in Volt,
+ multiplied by 100. */
+ INFO_BCLK, /*!< See \ref INFO_BUS_CLOCK. */
+ INFO_BUS_CLOCK, /*!< The main bus clock in MHz,
+ e.g., FSB/QPI/DMI/HT base clock,
+ multiplied by 100. */
} cpu_msrinfo_request_t;
+/**
+ * @brief Similar to \ref cpu_rdmsr, but extract a range of bits
+ *
+ * @param handle - a handle to the MSR reader driver, as created by
+ * cpu_msr_driver_open
+ * @param msr_index - the numeric ID of the MSR you want to read
+ * @param highbit - the high bit in range, must be inferior to 64
+ * @param lowbit - the low bit in range, must be equal or superior to 0
+ * @param result - a pointer to a 64-bit integer, where the MSR value is stored
+ *
+ * @returns zero if successful, and some negative number on error.
+ * The error message can be obtained by calling \ref cpuid_error.
+ * @see cpu_error_t
+ */
+int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit,
+ uint8_t lowbit, uint64_t* result);
+
/**
* @brief Reads extended CPU information from Model-Specific Registers.
* @param handle - a handle to an open MSR driver, @see cpu_msr_driver_open
diff --git a/contrib/libcpuid/include/libcpuid/libcpuid_constants.h b/contrib/libcpuid/include/libcpuid/libcpuid_constants.h
index 8af4718c906..3ddb6d5e14e 100644
--- a/contrib/libcpuid/include/libcpuid/libcpuid_constants.h
+++ b/contrib/libcpuid/include/libcpuid/libcpuid_constants.h
@@ -37,8 +37,11 @@
#define CPU_FLAGS_MAX 128
#define MAX_CPUID_LEVEL 32
#define MAX_EXT_CPUID_LEVEL 32
-#define MAX_INTELFN4_LEVEL 4
+#define MAX_INTELFN4_LEVEL 8
#define MAX_INTELFN11_LEVEL 4
+#define MAX_INTELFN12H_LEVEL 4
+#define MAX_INTELFN14H_LEVEL 4
#define CPU_HINTS_MAX 16
+#define SGX_FLAGS_MAX 14
#endif /* __LIBCPUID_CONSTANTS_H__ */
diff --git a/contrib/libcpuid/include/libcpuid/libcpuid_internal.h b/contrib/libcpuid/include/libcpuid/libcpuid_internal.h
new file mode 100644
index 00000000000..95528896219
--- /dev/null
+++ b/contrib/libcpuid/include/libcpuid/libcpuid_internal.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016 Veselin Georgiev,
+ * anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __LIBCPUID_INTERNAL_H__
+#define __LIBCPUID_INTERNAL_H__
+/*
+ * This file contains internal undocumented declarations and function prototypes
+ * for the workings of the internal library infrastructure.
+ */
+
+enum _common_codes_t {
+ NA = 0,
+ NO_CODE,
+};
+
+#define CODE(x) x
+#define CODE2(x, y) x = y
+enum _amd_code_t {
+ #include "amd_code_t.h"
+};
+typedef enum _amd_code_t amd_code_t;
+
+enum _intel_code_t {
+ #include "intel_code_t.h"
+};
+typedef enum _intel_code_t intel_code_t;
+#undef CODE
+#undef CODE2
+
+struct internal_id_info_t {
+ union {
+ amd_code_t amd;
+ intel_code_t intel;
+ } code;
+ int score; // detection (matchtable) score
+};
+
+int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data,
+ struct internal_id_info_t* internal);
+
+#endif /* __LIBCPUID_INTERNAL_H__ */
diff --git a/contrib/libcpuid/include/libcpuid/libcpuid_types.h b/contrib/libcpuid/include/libcpuid/libcpuid_types.h
index 6dd18a97724..f1181edf2ee 100644
--- a/contrib/libcpuid/include/libcpuid/libcpuid_types.h
+++ b/contrib/libcpuid/include/libcpuid/libcpuid_types.h
@@ -32,6 +32,37 @@
#ifndef __LIBCPUID_TYPES_H__
#define __LIBCPUID_TYPES_H__
+//#ifdef HAVE_CONFIG_H // CLICKHOUSE PATCH
+# include "config.h"
+//#endif // CLICKHOUSE PATCH
+
+#if 1 // CLICKHOUSE PATCH
+//#if defined(HAVE_STDINT_H) // CLICKHOUSE PATCH
# include
+#else
+/* we have to provide our own: */
+# if !defined(HAVE_INT32_T) && !defined(__int32_t_defined)
+typedef int int32_t;
+# endif
+
+# if !defined(HAVE_UINT32_T) && !defined(__uint32_t_defined)
+typedef unsigned uint32_t;
+# endif
+
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+#if (defined _MSC_VER) && (_MSC_VER <= 1300)
+ /* MSVC 6.0: no long longs ... */
+ typedef signed __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+#else
+ /* all other sane compilers: */
+ typedef signed long long int64_t;
+ typedef unsigned long long uint64_t;
+#endif
+
+#endif
#endif /* __LIBCPUID_TYPES_H__ */
diff --git a/contrib/libcpuid/include/libcpuid/libcpuid_util.c b/contrib/libcpuid/include/libcpuid/libcpuid_util.c
index 36e83c84b4a..ea6b1b8dfb4 100644
--- a/contrib/libcpuid/include/libcpuid/libcpuid_util.c
+++ b/contrib/libcpuid/include/libcpuid/libcpuid_util.c
@@ -38,7 +38,7 @@ void match_features(const struct feature_map_t* matchtable, int count, uint32_t
{
int i;
for (i = 0; i < count; i++)
- if (reg & (1U << matchtable[i].bit))
+ if (reg & (1u << matchtable[i].bit))
data->flags[matchtable[i].feature] = 1;
}
@@ -78,20 +78,20 @@ static int score(const struct match_entry_t* entry, const struct cpu_id_t* data,
int brand_code, int model_code)
{
int res = 0;
- if (entry->family == data->family ) res++;
- if (entry->model == data->model ) res++;
- if (entry->stepping == data->stepping ) res++;
- if (entry->ext_family == data->ext_family) res++;
- if (entry->ext_model == data->ext_model ) res++;
- if (entry->ncores == data->num_cores ) res++;
- if (entry->l2cache == data->l2_cache ) res++;
- if (entry->l3cache == data->l3_cache ) res++;
- if (entry->brand_code == brand_code ) res++;
- if (entry->model_code == model_code ) res++;
+ if (entry->family == data->family ) res += 2;
+ if (entry->model == data->model ) res += 2;
+ if (entry->stepping == data->stepping ) res += 2;
+ if (entry->ext_family == data->ext_family) res += 2;
+ if (entry->ext_model == data->ext_model ) res += 2;
+ if (entry->ncores == data->num_cores ) res += 2;
+ if (entry->l2cache == data->l2_cache ) res += 1;
+ if (entry->l3cache == data->l3_cache ) res += 1;
+ if (entry->brand_code == brand_code ) res += 2;
+ if (entry->model_code == model_code ) res += 2;
return res;
}
-void match_cpu_codename(const struct match_entry_t* matchtable, int count,
+int match_cpu_codename(const struct match_entry_t* matchtable, int count,
struct cpu_id_t* data, int brand_code, int model_code)
{
int bestscore = -1;
@@ -112,6 +112,7 @@ void match_cpu_codename(const struct match_entry_t* matchtable, int count,
}
}
strcpy(data->cpu_codename, matchtable[bestindex].name);
+ return bestscore;
}
void generic_get_cpu_list(const struct match_entry_t* matchtable, int count,
@@ -129,7 +130,11 @@ void generic_get_cpu_list(const struct match_entry_t* matchtable, int count,
break;
}
if (!good) continue;
+#if defined(_MSC_VER)
+ list->names[n++] = _strdup(matchtable[i].name);
+#else
list->names[n++] = strdup(matchtable[i].name);
+#endif
}
list->num_entries = n;
}
diff --git a/contrib/libcpuid/include/libcpuid/libcpuid_util.h b/contrib/libcpuid/include/libcpuid/libcpuid_util.h
index 34e1efe960a..22becea26f6 100644
--- a/contrib/libcpuid/include/libcpuid/libcpuid_util.h
+++ b/contrib/libcpuid/include/libcpuid/libcpuid_util.h
@@ -42,7 +42,8 @@ struct match_entry_t {
char name[32];
};
-void match_cpu_codename(const struct match_entry_t* matchtable, int count,
+// returns the match score:
+int match_cpu_codename(const struct match_entry_t* matchtable, int count,
struct cpu_id_t* data, int brand_code, int model_code);
void warnf(const char* format, ...)
diff --git a/contrib/libcpuid/include/libcpuid/msrdriver.c b/contrib/libcpuid/include/libcpuid/msrdriver.c
new file mode 100644
index 00000000000..8f9d7ed0ca8
--- /dev/null
+++ b/contrib/libcpuid/include/libcpuid/msrdriver.c
@@ -0,0 +1,593 @@
+/*
+ * Copyright 2009 Veselin Georgiev,
+ * anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/**
+ * @File msrdriver.c
+ * @Brief Contains the binary images of the x86 and x64 MSR drivers for Windows
+ * @Date 2009-09-29
+ *
+ * The driver is courtesy of Nick 'Bombera' Gabareff, and its source is actually
+ * available, see the contrib/ dir.
+ *
+ * However, for simplicity, here we just include the images of the compiled .SYS
+ * files.
+ * They are extracted to the filesystem on demand and loaded in the kernel
+ * by the cpu_msr_driver_open() function
+ */
+#ifdef _WIN32
+#include "asm-bits.h"
+//begin {
+int cc_x86driver_code_size = 4608;
+uint8_t cc_x86driver_code[4608] = {
+ 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xb8,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
+ 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,
+ 0x20,0x63,0x61,0x6e,0x6e,0x6f,0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,0x20,0x69,0x6e,0x20,
+ 0x44,0x4f,0x53,0x20,0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,0x24,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x9f,0x99,0x48,0xdf,0xdb,0xf8,0x26,0x8c,0xdb,0xf8,0x26,0x8c,0xdb,0xf8,0x26,0x8c,
+ 0xdb,0xf8,0x27,0x8c,0xdd,0xf8,0x26,0x8c,0x21,0xdb,0x3f,0x8c,0xd8,0xf8,0x26,0x8c,0xfc,0x3e,
+ 0x57,0x8c,0xda,0xf8,0x26,0x8c,0xfc,0x3e,0x5a,0x8c,0xda,0xf8,0x26,0x8c,0xfc,0x3e,0x5e,0x8c,
+ 0xda,0xf8,0x26,0x8c,0x52,0x69,0x63,0x68,0xdb,0xf8,0x26,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x50,0x45,0x00,0x00,0x4c,0x01,0x07,0x00,0x12,0x9b,0x9b,0x4a,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xe0,0x00,0x02,0x21,0x0b,0x01,0x08,0x00,0x00,0x06,0x00,0x00,0x00,0x0a,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x00,
+ 0xa9,0xd1,0x00,0x00,0x01,0x00,0x00,0x04,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,
+ 0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0xc0,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x70,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x20,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0x74,
+ 0x65,0x78,0x74,0x00,0x00,0x00,0xa3,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0x68,0x2e,0x72,0x64,0x61,0x74,0x61,0x00,0x00,0x62,0x00,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x48,0x2e,0x64,0x61,0x74,0x61,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
+ 0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0xc8,0x50,0x41,0x47,0x45,0x30,0x44,0x45,0x46,
+ 0x8c,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x60,0x49,0x4e,0x49,0x54,
+ 0x00,0x00,0x00,0x00,0xd4,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0a,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0xe2,
+ 0x2e,0x72,0x73,0x72,0x63,0x00,0x00,0x00,0xc0,0x03,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x04,
+ 0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x42,0x2e,0x72,0x65,0x6c,0x6f,0x63,0x00,0x00,0x68,0x00,0x00,0x00,0x00,0x70,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8b,0x4c,
+ 0x24,0x08,0x83,0x61,0x18,0x00,0x83,0x61,0x1c,0x00,0x32,0xd2,0xff,0x15,0x08,0x20,0x01,0x00,
+ 0x33,0xc0,0xc2,0x08,0x00,0x56,0x8b,0x74,0x24,0x0c,0x8b,0x46,0x60,0x81,0x78,0x0c,0x0c,0xe0,
+ 0x22,0x00,0x57,0x75,0x3c,0x83,0x78,0x04,0x08,0x72,0x36,0x83,0x78,0x08,0x04,0x75,0x07,0x8b,
+ 0x46,0x0c,0x8b,0x08,0xeb,0x05,0xb9,0x9c,0x01,0x00,0x00,0x8b,0x7e,0x0c,0x0f,0x32,0x89,0x07,
+ 0x89,0x57,0x04,0xc7,0x46,0x1c,0x08,0x00,0x00,0x00,0x33,0xff,0x32,0xd2,0x8b,0xce,0xff,0x15,
+ 0x08,0x20,0x01,0x00,0x8b,0xc7,0x5f,0x5e,0xc2,0x08,0x00,0x83,0x66,0x1c,0x00,0xbf,0x01,0x00,
+ 0x00,0xc0,0x89,0x7e,0x18,0xeb,0xe1,0x55,0x8b,0xec,0x51,0x51,0x8b,0x45,0x08,0xff,0x70,0x04,
+ 0xff,0x15,0x04,0x20,0x01,0x00,0x68,0x3c,0x20,0x01,0x00,0x8d,0x45,0xf8,0x50,0xff,0x15,0x00,
+ 0x20,0x01,0x00,0x8d,0x45,0xf8,0x50,0xff,0x15,0x14,0x20,0x01,0x00,0xc9,0xc2,0x04,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x50,0x00,0x00,0x74,0x50,0x00,0x00,0x86,0x50,0x00,0x00,
+ 0x9c,0x50,0x00,0x00,0xb4,0x50,0x00,0x00,0x44,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x00,
+ 0x44,0x00,0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x5c,0x00,0x54,0x00,0x6d,0x00,
+ 0x70,0x00,0x52,0x00,0x64,0x00,0x72,0x00,0x00,0x00,0x00,0x00,0x5c,0x00,0x44,0x00,0x6f,0x00,
+ 0x73,0x00,0x44,0x00,0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x73,0x00,0x5c,0x00,
+ 0x54,0x00,0x6d,0x00,0x70,0x00,0x52,0x00,0x64,0x00,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x8b,0xec,0x83,
+ 0xec,0x14,0x56,0x8b,0x35,0x00,0x20,0x01,0x00,0x57,0x68,0x1c,0x20,0x01,0x00,0x8d,0x45,0xf4,
+ 0x50,0xff,0xd6,0x8b,0x7d,0x08,0x8d,0x45,0xfc,0x50,0x6a,0x00,0x6a,0x00,0x6a,0x22,0x8d,0x45,
+ 0xf4,0x50,0x6a,0x04,0x57,0xff,0x15,0x10,0x20,0x01,0x00,0x85,0xc0,0x75,0x4f,0x68,0x3c,0x20,
+ 0x01,0x00,0x8d,0x45,0xec,0x50,0xff,0xd6,0x8d,0x45,0xf4,0x50,0x8d,0x45,0xec,0x50,0xff,0x15,
+ 0x0c,0x20,0x01,0x00,0x8b,0xf0,0x85,0xf6,0x74,0x0d,0xff,0x75,0xfc,0xff,0x15,0x04,0x20,0x01,
+ 0x00,0x8b,0xc6,0xeb,0x23,0x8b,0x45,0xfc,0xa3,0x00,0x30,0x01,0x00,0xb8,0x00,0x10,0x01,0x00,
+ 0x89,0x47,0x38,0x89,0x47,0x40,0xc7,0x47,0x34,0x75,0x10,0x01,0x00,0xc7,0x47,0x70,0x19,0x10,
+ 0x01,0x00,0x33,0xc0,0x5f,0x5e,0xc9,0xc2,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc6,0x50,
+ 0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x50,0x00,0x00,0x74,0x50,0x00,0x00,0x86,0x50,
+ 0x00,0x00,0x9c,0x50,0x00,0x00,0xb4,0x50,0x00,0x00,0x44,0x50,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x4b,0x01,0x49,0x6f,0x44,0x65,0x6c,0x65,0x74,0x65,0x53,0x79,0x6d,0x62,0x6f,0x6c,0x69,0x63,
+ 0x4c,0x69,0x6e,0x6b,0x00,0x00,0x0b,0x04,0x52,0x74,0x6c,0x49,0x6e,0x69,0x74,0x55,0x6e,0x69,
+ 0x63,0x6f,0x64,0x65,0x53,0x74,0x72,0x69,0x6e,0x67,0x00,0x00,0x49,0x01,0x49,0x6f,0x44,0x65,
+ 0x6c,0x65,0x74,0x65,0x44,0x65,0x76,0x69,0x63,0x65,0x00,0x00,0xda,0x01,0x49,0x6f,0x66,0x43,
+ 0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x00,0x00,0x41,0x01,
+ 0x49,0x6f,0x43,0x72,0x65,0x61,0x74,0x65,0x53,0x79,0x6d,0x62,0x6f,0x6c,0x69,0x63,0x4c,0x69,
+ 0x6e,0x6b,0x00,0x00,0x38,0x01,0x49,0x6f,0x43,0x72,0x65,0x61,0x74,0x65,0x44,0x65,0x76,0x69,
+ 0x63,0x65,0x00,0x00,0x6e,0x74,0x6f,0x73,0x6b,0x72,0x6e,0x6c,0x2e,0x65,0x78,0x65,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x18,0x00,0x00,0x80,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
+ 0x00,0x00,0x30,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x09,0x04,0x00,0x00,0x48,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x5c,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5c,0x03,0x34,0x00,0x00,0x00,0x56,0x00,0x53,0x00,0x5f,0x00,0x56,0x00,0x45,0x00,0x52,0x00,
+ 0x53,0x00,0x49,0x00,0x4f,0x00,0x4e,0x00,0x5f,0x00,0x49,0x00,0x4e,0x00,0x46,0x00,0x4f,0x00,
+ 0x00,0x00,0x00,0x00,0xbd,0x04,0xef,0xfe,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x00,0x04,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xba,0x02,0x00,0x00,0x01,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,
+ 0x67,0x00,0x46,0x00,0x69,0x00,0x6c,0x00,0x65,0x00,0x49,0x00,0x6e,0x00,0x66,0x00,0x6f,0x00,
+ 0x00,0x00,0x96,0x02,0x00,0x00,0x01,0x00,0x30,0x00,0x34,0x00,0x30,0x00,0x39,0x00,0x30,0x00,
+ 0x34,0x00,0x62,0x00,0x30,0x00,0x00,0x00,0x58,0x00,0x20,0x00,0x01,0x00,0x43,0x00,0x6f,0x00,
+ 0x6d,0x00,0x6d,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x73,0x00,0x00,0x00,0x4d,0x00,0x53,0x00,
+ 0x52,0x00,0x20,0x00,0x72,0x00,0x65,0x00,0x61,0x00,0x64,0x00,0x65,0x00,0x72,0x00,0x20,0x00,
+ 0x33,0x00,0x32,0x00,0x2d,0x00,0x62,0x00,0x69,0x00,0x74,0x00,0x20,0x00,0x6b,0x00,0x65,0x00,
+ 0x72,0x00,0x6e,0x00,0x65,0x00,0x6c,0x00,0x20,0x00,0x64,0x00,0x72,0x00,0x69,0x00,0x76,0x00,
+ 0x65,0x00,0x72,0x00,0x00,0x00,0x42,0x00,0x11,0x00,0x01,0x00,0x43,0x00,0x6f,0x00,0x6d,0x00,
+ 0x70,0x00,0x61,0x00,0x6e,0x00,0x79,0x00,0x4e,0x00,0x61,0x00,0x6d,0x00,0x65,0x00,0x00,0x00,
+ 0x00,0x00,0x49,0x00,0x72,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x53,0x00,0x74,0x00,0x65,0x00,
+ 0x65,0x00,0x64,0x00,0x73,0x00,0x20,0x00,0x49,0x00,0x6e,0x00,0x63,0x00,0x2e,0x00,0x00,0x00,
+ 0x00,0x00,0x60,0x00,0x1c,0x00,0x01,0x00,0x46,0x00,0x69,0x00,0x6c,0x00,0x65,0x00,0x44,0x00,
+ 0x65,0x00,0x73,0x00,0x63,0x00,0x72,0x00,0x69,0x00,0x70,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,
+ 0x6e,0x00,0x00,0x00,0x00,0x00,0x54,0x00,0x6d,0x00,0x70,0x00,0x52,0x00,0x64,0x00,0x72,0x00,
+ 0x20,0x00,0x33,0x00,0x32,0x00,0x2d,0x00,0x62,0x00,0x69,0x00,0x74,0x00,0x20,0x00,0x4b,0x00,
+ 0x65,0x00,0x72,0x00,0x6e,0x00,0x65,0x00,0x6c,0x00,0x20,0x00,0x4d,0x00,0x6f,0x00,0x64,0x00,
+ 0x75,0x00,0x6c,0x00,0x65,0x00,0x00,0x00,0x36,0x00,0x0b,0x00,0x01,0x00,0x46,0x00,0x69,0x00,
+ 0x6c,0x00,0x65,0x00,0x56,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,
+ 0x00,0x00,0x00,0x00,0x31,0x00,0x2c,0x00,0x20,0x00,0x30,0x00,0x2c,0x00,0x20,0x00,0x30,0x00,
+ 0x2c,0x00,0x20,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x2e,0x00,0x07,0x00,0x01,0x00,0x49,0x00,
+ 0x6e,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x6e,0x00,0x61,0x00,0x6c,0x00,0x4e,0x00,0x61,0x00,
+ 0x6d,0x00,0x65,0x00,0x00,0x00,0x54,0x00,0x6d,0x00,0x70,0x00,0x52,0x00,0x64,0x00,0x72,0x00,
+ 0x00,0x00,0x00,0x00,0x4a,0x00,0x13,0x00,0x01,0x00,0x4c,0x00,0x65,0x00,0x67,0x00,0x61,0x00,
+ 0x6c,0x00,0x43,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,
+ 0x74,0x00,0x00,0x00,0x4e,0x00,0x69,0x00,0x63,0x00,0x6b,0x00,0x20,0x00,0x47,0x00,0x61,0x00,
+ 0x62,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x76,0x00,0x20,0x00,0x27,0x00,0x32,0x00,0x30,0x00,
+ 0x30,0x00,0x39,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x0b,0x00,0x01,0x00,0x4f,0x00,0x72,0x00,
+ 0x69,0x00,0x67,0x00,0x69,0x00,0x6e,0x00,0x61,0x00,0x6c,0x00,0x46,0x00,0x69,0x00,0x6c,0x00,
+ 0x65,0x00,0x6e,0x00,0x61,0x00,0x6d,0x00,0x65,0x00,0x00,0x00,0x54,0x00,0x6d,0x00,0x70,0x00,
+ 0x52,0x00,0x64,0x00,0x72,0x00,0x2e,0x00,0x73,0x00,0x79,0x00,0x73,0x00,0x00,0x00,0x00,0x00,
+ 0x54,0x00,0x1a,0x00,0x01,0x00,0x50,0x00,0x72,0x00,0x6f,0x00,0x64,0x00,0x75,0x00,0x63,0x00,
+ 0x74,0x00,0x4e,0x00,0x61,0x00,0x6d,0x00,0x65,0x00,0x00,0x00,0x00,0x00,0x43,0x00,0x6f,0x00,
+ 0x72,0x00,0x65,0x00,0x20,0x00,0x32,0x00,0x20,0x00,0x54,0x00,0x65,0x00,0x6d,0x00,0x70,0x00,
+ 0x65,0x00,0x72,0x00,0x61,0x00,0x74,0x00,0x75,0x00,0x72,0x00,0x65,0x00,0x20,0x00,0x52,0x00,
+ 0x65,0x00,0x61,0x00,0x64,0x00,0x65,0x00,0x72,0x00,0x00,0x00,0x3a,0x00,0x0b,0x00,0x01,0x00,
+ 0x50,0x00,0x72,0x00,0x6f,0x00,0x64,0x00,0x75,0x00,0x63,0x00,0x74,0x00,0x56,0x00,0x65,0x00,
+ 0x72,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x00,0x00,0x31,0x00,0x2c,0x00,0x20,0x00,
+ 0x30,0x00,0x2c,0x00,0x20,0x00,0x30,0x00,0x2c,0x00,0x20,0x00,0x31,0x00,0x00,0x00,0x00,0x00,
+ 0x44,0x00,0x00,0x00,0x01,0x00,0x56,0x00,0x61,0x00,0x72,0x00,0x46,0x00,0x69,0x00,0x6c,0x00,
+ 0x65,0x00,0x49,0x00,0x6e,0x00,0x66,0x00,0x6f,0x00,0x00,0x00,0x00,0x00,0x24,0x00,0x04,0x00,
+ 0x00,0x00,0x54,0x00,0x72,0x00,0x61,0x00,0x6e,0x00,0x73,0x00,0x6c,0x00,0x61,0x00,0x74,0x00,
+ 0x69,0x00,0x6f,0x00,0x6e,0x00,0x00,0x00,0x00,0x00,0x09,0x04,0xb0,0x04,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x14,0x00,0x00,0x00,
+ 0x10,0x30,0x5c,0x30,0x82,0x30,0x87,0x30,0x91,0x30,0x9b,0x30,0x00,0x40,0x00,0x00,0x1c,0x00,
+ 0x00,0x00,0x09,0x30,0x0f,0x30,0x2f,0x30,0x38,0x30,0x4c,0x30,0x5b,0x30,0x67,0x30,0x6c,0x30,
+ 0x79,0x30,0x80,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+int cc_x64driver_code_size = 5120;
+uint8_t cc_x64driver_code[5120] = {
+ 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xb8,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
+ 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,
+ 0x20,0x63,0x61,0x6e,0x6e,0x6f,0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,0x20,0x69,0x6e,0x20,
+ 0x44,0x4f,0x53,0x20,0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,0x24,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xb7,0x04,0xa8,0xc2,0xf3,0x65,0xc6,0x91,0xf3,0x65,0xc6,0x91,0xf3,0x65,0xc6,0x91,
+ 0xf3,0x65,0xc7,0x91,0xf4,0x65,0xc6,0x91,0x85,0xf8,0xbd,0x91,0xf0,0x65,0xc6,0x91,0x85,0xf8,
+ 0xab,0x91,0xf0,0x65,0xc6,0x91,0x30,0x6a,0x98,0x91,0xf2,0x65,0xc6,0x91,0x85,0xf8,0xbe,0x91,
+ 0xf2,0x65,0xc6,0x91,0x52,0x69,0x63,0x68,0xf3,0x65,0xc6,0x91,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x45,0x00,0x00,0x64,0x86,0x07,0x00,
+ 0x41,0xc8,0x6d,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x22,0x00,0x0b,0x02,
+ 0x08,0x00,0x00,0x06,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x60,0x00,0x00,
+ 0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x05,0x00,0x02,0x00,0x05,0x00,0x02,0x00,0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x00,0x79,0x44,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x60,0x00,0x00,0x28,0x00,0x00,0x00,
+ 0x00,0x70,0x00,0x00,0xc0,0x03,0x00,0x00,0x00,0x40,0x00,0x00,0x48,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x20,0x00,0x00,
+ 0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x2e,0x74,0x65,0x78,0x74,0x00,0x00,0x00,0x26,0x01,0x00,0x00,0x00,0x10,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x68,0x2e,0x72,0x64,0x61,0x74,0x61,0x00,0x00,0xf0,0x00,
+ 0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x48,0x2e,0x64,0x61,0x74,0x61,0x00,
+ 0x00,0x00,0x18,0x01,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0xc8,0x2e,0x70,
+ 0x64,0x61,0x74,0x61,0x00,0x00,0x48,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,
+ 0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x48,0x50,0x41,0x47,0x45,0x30,0x44,0x45,0x46,0x4e,0x01,0x00,0x00,0x00,0x50,0x00,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x20,0x00,0x00,0x60,0x49,0x4e,0x49,0x54,0x00,0x00,0x00,0x00,0x60,0x01,0x00,0x00,
+ 0x00,0x60,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0xe2,0x2e,0x72,0x73,0x72,0x63,0x00,0x00,0x00,
+ 0xc0,0x03,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x42,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x83,0xec,0x28,
+ 0x33,0xc9,0x48,0x8b,0xc2,0x89,0x4a,0x30,0x48,0x89,0x4a,0x38,0x33,0xd2,0x48,0x8b,0xc8,0xff,
+ 0x15,0xfd,0x0f,0x00,0x00,0x33,0xc0,0x48,0x83,0xc4,0x28,0xc3,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x48,0x83,0xec,0x28,0x48,0x8b,0x82,0xb8,0x00,0x00,
+ 0x00,0x4c,0x8b,0xca,0x81,0x78,0x18,0x0c,0xe0,0x22,0x00,0x75,0x43,0x83,0x78,0x08,0x08,0x72,
+ 0x3d,0x83,0x78,0x10,0x04,0x75,0x08,0x48,0x8b,0x42,0x18,0x8b,0x08,0xeb,0x05,0xb9,0x9c,0x01,
+ 0x00,0x00,0x4c,0x8b,0x42,0x18,0x0f,0x32,0x48,0xc1,0xe2,0x20,0x49,0x8b,0xc9,0x48,0x0b,0xc2,
+ 0x33,0xd2,0x49,0x89,0x00,0x49,0xc7,0x41,0x38,0x08,0x00,0x00,0x00,0xff,0x15,0x95,0x0f,0x00,
+ 0x00,0x33,0xc0,0x48,0x83,0xc4,0x28,0xc3,0xc7,0x42,0x30,0x01,0x00,0x00,0xc0,0x48,0xc7,0x42,
+ 0x38,0x00,0x00,0x00,0x00,0x49,0x8b,0xc9,0x33,0xd2,0xff,0x15,0x74,0x0f,0x00,0x00,0xb8,0x01,
+ 0x00,0x00,0xc0,0x48,0x83,0xc4,0x28,0xc3,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x48,0x83,0xec,0x38,0x48,0x8b,0x49,0x08,0xff,0x15,
+ 0x32,0x0f,0x00,0x00,0x48,0x8d,0x15,0x1b,0x00,0x00,0x00,0x48,0x8d,0x4c,0x24,0x20,0xff,0x15,
+ 0x18,0x0f,0x00,0x00,0x48,0x8d,0x4c,0x24,0x20,0xff,0x15,0x05,0x0f,0x00,0x00,0x48,0x83,0xc4,
+ 0x38,0xc3,0x5c,0x00,0x44,0x00,0x6f,0x00,0x73,0x00,0x44,0x00,0x65,0x00,0x76,0x00,0x69,0x00,
+ 0x63,0x00,0x65,0x00,0x73,0x00,0x5c,0x00,0x54,0x00,0x6d,0x00,0x70,0x00,0x52,0x00,0x64,0x00,
+ 0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x60,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x16,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x61,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x40,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x60,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x41,0xc8,0x6d,0x49,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x49,0x00,0x00,0x00,
+ 0x5c,0x20,0x00,0x00,0x5c,0x06,0x00,0x00,0x52,0x53,0x44,0x53,0xd9,0x5e,0xab,0x47,0xc4,0xf2,
+ 0x4f,0x40,0xaa,0xe9,0x90,0x47,0x67,0x30,0xa5,0xfa,0x03,0x00,0x00,0x00,0x44,0x3a,0x5c,0x74,
+ 0x6d,0x70,0x5c,0x4b,0x65,0x72,0x6e,0x65,0x6c,0x5c,0x6f,0x62,0x6a,0x66,0x72,0x65,0x5f,0x77,
+ 0x6e,0x65,0x74,0x5f,0x41,0x4d,0x44,0x36,0x34,0x5c,0x61,0x6d,0x64,0x36,0x34,0x5c,0x54,0x6d,
+ 0x70,0x52,0x64,0x72,0x2e,0x70,0x64,0x62,0x00,0x00,0x00,0x00,0x01,0x04,0x01,0x00,0x04,0x42,
+ 0x00,0x00,0x01,0x04,0x01,0x00,0x04,0x42,0x00,0x00,0x01,0x04,0x01,0x00,0x04,0x62,0x00,0x00,
+ 0x21,0x00,0x00,0x00,0x10,0x50,0x00,0x00,0x74,0x50,0x00,0x00,0xe4,0x20,0x00,0x00,0x21,0x08,
+ 0x02,0x00,0x08,0x74,0x13,0x00,0x10,0x50,0x00,0x00,0x74,0x50,0x00,0x00,0xe4,0x20,0x00,0x00,
+ 0x01,0x0c,0x03,0x00,0x0c,0x34,0x12,0x00,0x04,0xe2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xcd,0x5d,0x20,0xd2,0x66,0xd4,0xff,0xff,0x32,0xa2,0xdf,0x2d,0x99,0x2b,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x32,0x10,0x00,0x00,0xa8,0x20,0x00,0x00,0x40,0x10,
+ 0x00,0x00,0xbe,0x10,0x00,0x00,0xb0,0x20,0x00,0x00,0xd0,0x10,0x00,0x00,0x00,0x11,0x00,0x00,
+ 0xb8,0x20,0x00,0x00,0x10,0x50,0x00,0x00,0x74,0x50,0x00,0x00,0xe4,0x20,0x00,0x00,0x74,0x50,
+ 0x00,0x00,0xe8,0x50,0x00,0x00,0xd0,0x20,0x00,0x00,0xe8,0x50,0x00,0x00,0xf5,0x50,0x00,0x00,
+ 0xc0,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x83,0xec,0x78,0x48,0x89,0x9c,0x24,
+ 0x90,0x00,0x00,0x00,0x48,0x8b,0xd9,0x48,0x8d,0x15,0x0a,0x01,0x00,0x00,0x48,0x8d,0x4c,0x24,
+ 0x48,0xff,0x15,0xd7,0xcf,0xff,0xff,0x41,0xb9,0x22,0x00,0x00,0x00,0x4c,0x8d,0x5c,0x24,0x40,
+ 0x4c,0x89,0x5c,0x24,0x30,0x4c,0x8d,0x44,0x24,0x48,0x41,0x8d,0x51,0xe6,0x48,0x8b,0xcb,0xc6,
+ 0x44,0x24,0x28,0x00,0xc7,0x44,0x24,0x20,0x00,0x00,0x00,0x00,0xff,0x15,0xc0,0xcf,0xff,0xff,
+ 0x85,0xc0,0x0f,0x85,0x80,0x00,0x00,0x00,0x48,0x8d,0x15,0x91,0x00,0x00,0x00,0x48,0x8d,0x4c,
+ 0x24,0x58,0x48,0x89,0xbc,0x24,0x98,0x00,0x00,0x00,0xff,0x15,0x86,0xcf,0xff,0xff,0x48,0x8d,
+ 0x54,0x24,0x48,0x48,0x8d,0x4c,0x24,0x58,0xff,0x15,0x86,0xcf,0xff,0xff,0x85,0xc0,0x8b,0xf8,
+ 0x74,0x0f,0x48,0x8b,0x4c,0x24,0x40,0xff,0x15,0x6d,0xcf,0xff,0xff,0x8b,0xc7,0xeb,0x39,0x48,
+ 0x8b,0x44,0x24,0x40,0x48,0x89,0x05,0x5d,0xe0,0xff,0xff,0x48,0x8d,0x05,0x16,0xc0,0xff,0xff,
+ 0x48,0x89,0x43,0x68,0x48,0x8d,0x05,0x4b,0xbf,0xff,0xff,0x48,0x89,0x43,0x70,0x48,0x89,0x83,
+ 0x80,0x00,0x00,0x00,0x48,0x8d,0x05,0x69,0xbf,0xff,0xff,0x48,0x89,0x83,0xe0,0x00,0x00,0x00,
+ 0x33,0xc0,0x48,0x8b,0xbc,0x24,0x98,0x00,0x00,0x00,0x48,0x8b,0x9c,0x24,0x90,0x00,0x00,0x00,
+ 0x48,0x83,0xc4,0x78,0xc3,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x5c,0x00,
+ 0x44,0x00,0x6f,0x00,0x73,0x00,0x44,0x00,0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65,0x00,
+ 0x73,0x00,0x5c,0x00,0x54,0x00,0x6d,0x00,0x70,0x00,0x52,0x00,0x64,0x00,0x72,0x00,0x00,0x00,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x5c,0x00,0x44,0x00,0x65,0x00,0x76,0x00,
+ 0x69,0x00,0x63,0x00,0x65,0x00,0x5c,0x00,0x54,0x00,0x6d,0x00,0x70,0x00,0x52,0x00,0x64,0x00,
+ 0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x48,0x8b,0x05,0xf1,0xd0,0xff,0xff,0x49,0xb9,0x32,0xa2,0xdf,0x2d,0x99,0x2b,0x00,0x00,0x48,
+ 0x85,0xc0,0x74,0x05,0x49,0x3b,0xc1,0x75,0x2f,0x4c,0x8d,0x05,0xd6,0xd0,0xff,0xff,0x48,0xb8,
+ 0x20,0x03,0x00,0x00,0x80,0xf7,0xff,0xff,0x48,0x8b,0x00,0x49,0x33,0xc0,0x49,0xb8,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x49,0x23,0xc0,0x49,0x0f,0x44,0xc1,0x48,0x89,0x05,0xae,0xd0,
+ 0xff,0xff,0x48,0xf7,0xd0,0x48,0x89,0x05,0x9c,0xd0,0xff,0xff,0xe9,0xa7,0xef,0xff,0xff,0xcc,
+ 0xcc,0xcc,0x98,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x61,0x00,0x00,
+ 0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0x60,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x61,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x60,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf6,0x01,0x49,0x6f,0x66,0x43,
+ 0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x00,0x00,0x61,0x01,
+ 0x49,0x6f,0x44,0x65,0x6c,0x65,0x74,0x65,0x53,0x79,0x6d,0x62,0x6f,0x6c,0x69,0x63,0x4c,0x69,
+ 0x6e,0x6b,0x00,0x00,0x3e,0x04,0x52,0x74,0x6c,0x49,0x6e,0x69,0x74,0x55,0x6e,0x69,0x63,0x6f,
+ 0x64,0x65,0x53,0x74,0x72,0x69,0x6e,0x67,0x00,0x00,0x5f,0x01,0x49,0x6f,0x44,0x65,0x6c,0x65,
+ 0x74,0x65,0x44,0x65,0x76,0x69,0x63,0x65,0x00,0x00,0x55,0x01,0x49,0x6f,0x43,0x72,0x65,0x61,
+ 0x74,0x65,0x53,0x79,0x6d,0x62,0x6f,0x6c,0x69,0x63,0x4c,0x69,0x6e,0x6b,0x00,0x00,0x4c,0x01,
+ 0x49,0x6f,0x43,0x72,0x65,0x61,0x74,0x65,0x44,0x65,0x76,0x69,0x63,0x65,0x00,0x00,0x6e,0x74,
+ 0x6f,0x73,0x6b,0x72,0x6e,0x6c,0x2e,0x65,0x78,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x18,0x00,0x00,0x80,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
+ 0x30,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x09,0x04,0x00,0x00,0x48,0x00,0x00,0x00,0x60,0x70,0x00,0x00,0x60,0x03,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x03,
+ 0x34,0x00,0x00,0x00,0x56,0x00,0x53,0x00,0x5f,0x00,0x56,0x00,0x45,0x00,0x52,0x00,0x53,0x00,
+ 0x49,0x00,0x4f,0x00,0x4e,0x00,0x5f,0x00,0x49,0x00,0x4e,0x00,0x46,0x00,0x4f,0x00,0x00,0x00,
+ 0x00,0x00,0xbd,0x04,0xef,0xfe,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,
+ 0x04,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xbe,0x02,0x00,0x00,0x01,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,
+ 0x46,0x00,0x69,0x00,0x6c,0x00,0x65,0x00,0x49,0x00,0x6e,0x00,0x66,0x00,0x6f,0x00,0x00,0x00,
+ 0x9a,0x02,0x00,0x00,0x01,0x00,0x30,0x00,0x34,0x00,0x30,0x00,0x39,0x00,0x30,0x00,0x34,0x00,
+ 0x62,0x00,0x30,0x00,0x00,0x00,0x58,0x00,0x20,0x00,0x01,0x00,0x43,0x00,0x6f,0x00,0x6d,0x00,
+ 0x6d,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x73,0x00,0x00,0x00,0x4d,0x00,0x53,0x00,0x52,0x00,
+ 0x20,0x00,0x72,0x00,0x65,0x00,0x61,0x00,0x64,0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x36,0x00,
+ 0x34,0x00,0x2d,0x00,0x62,0x00,0x69,0x00,0x74,0x00,0x20,0x00,0x6b,0x00,0x65,0x00,0x72,0x00,
+ 0x6e,0x00,0x65,0x00,0x6c,0x00,0x20,0x00,0x64,0x00,0x72,0x00,0x69,0x00,0x76,0x00,0x65,0x00,
+ 0x72,0x00,0x00,0x00,0x42,0x00,0x11,0x00,0x01,0x00,0x43,0x00,0x6f,0x00,0x6d,0x00,0x70,0x00,
+ 0x61,0x00,0x6e,0x00,0x79,0x00,0x4e,0x00,0x61,0x00,0x6d,0x00,0x65,0x00,0x00,0x00,0x00,0x00,
+ 0x49,0x00,0x72,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x53,0x00,0x74,0x00,0x65,0x00,0x65,0x00,
+ 0x64,0x00,0x73,0x00,0x20,0x00,0x49,0x00,0x6e,0x00,0x63,0x00,0x2e,0x00,0x00,0x00,0x00,0x00,
+ 0x60,0x00,0x1c,0x00,0x01,0x00,0x46,0x00,0x69,0x00,0x6c,0x00,0x65,0x00,0x44,0x00,0x65,0x00,
+ 0x73,0x00,0x63,0x00,0x72,0x00,0x69,0x00,0x70,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,
+ 0x00,0x00,0x00,0x00,0x54,0x00,0x6d,0x00,0x70,0x00,0x52,0x00,0x64,0x00,0x72,0x00,0x20,0x00,
+ 0x36,0x00,0x34,0x00,0x2d,0x00,0x62,0x00,0x69,0x00,0x74,0x00,0x20,0x00,0x4b,0x00,0x65,0x00,
+ 0x72,0x00,0x6e,0x00,0x65,0x00,0x6c,0x00,0x20,0x00,0x4d,0x00,0x6f,0x00,0x64,0x00,0x75,0x00,
+ 0x6c,0x00,0x65,0x00,0x00,0x00,0x36,0x00,0x0b,0x00,0x01,0x00,0x46,0x00,0x69,0x00,0x6c,0x00,
+ 0x65,0x00,0x56,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x00,0x00,
+ 0x00,0x00,0x31,0x00,0x2c,0x00,0x20,0x00,0x30,0x00,0x2c,0x00,0x20,0x00,0x30,0x00,0x2c,0x00,
+ 0x20,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x2e,0x00,0x07,0x00,0x01,0x00,0x49,0x00,0x6e,0x00,
+ 0x74,0x00,0x65,0x00,0x72,0x00,0x6e,0x00,0x61,0x00,0x6c,0x00,0x4e,0x00,0x61,0x00,0x6d,0x00,
+ 0x65,0x00,0x00,0x00,0x54,0x00,0x6d,0x00,0x70,0x00,0x52,0x00,0x64,0x00,0x72,0x00,0x00,0x00,
+ 0x00,0x00,0x4a,0x00,0x13,0x00,0x01,0x00,0x4c,0x00,0x65,0x00,0x67,0x00,0x61,0x00,0x6c,0x00,
+ 0x43,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,
+ 0x00,0x00,0x4e,0x00,0x69,0x00,0x63,0x00,0x6b,0x00,0x20,0x00,0x47,0x00,0x61,0x00,0x62,0x00,
+ 0x61,0x00,0x72,0x00,0x65,0x00,0x76,0x00,0x20,0x00,0x27,0x00,0x32,0x00,0x30,0x00,0x30,0x00,
+ 0x39,0x00,0x00,0x00,0x00,0x00,0x42,0x00,0x0d,0x00,0x01,0x00,0x4f,0x00,0x72,0x00,0x69,0x00,
+ 0x67,0x00,0x69,0x00,0x6e,0x00,0x61,0x00,0x6c,0x00,0x46,0x00,0x69,0x00,0x6c,0x00,0x65,0x00,
+ 0x6e,0x00,0x61,0x00,0x6d,0x00,0x65,0x00,0x00,0x00,0x54,0x00,0x6d,0x00,0x70,0x00,0x52,0x00,
+ 0x64,0x00,0x72,0x00,0x36,0x00,0x34,0x00,0x2e,0x00,0x73,0x00,0x79,0x00,0x73,0x00,0x00,0x00,
+ 0x00,0x00,0x54,0x00,0x1a,0x00,0x01,0x00,0x50,0x00,0x72,0x00,0x6f,0x00,0x64,0x00,0x75,0x00,
+ 0x63,0x00,0x74,0x00,0x4e,0x00,0x61,0x00,0x6d,0x00,0x65,0x00,0x00,0x00,0x00,0x00,0x43,0x00,
+ 0x6f,0x00,0x72,0x00,0x65,0x00,0x20,0x00,0x32,0x00,0x20,0x00,0x54,0x00,0x65,0x00,0x6d,0x00,
+ 0x70,0x00,0x65,0x00,0x72,0x00,0x61,0x00,0x74,0x00,0x75,0x00,0x72,0x00,0x65,0x00,0x20,0x00,
+ 0x52,0x00,0x65,0x00,0x61,0x00,0x64,0x00,0x65,0x00,0x72,0x00,0x00,0x00,0x3a,0x00,0x0b,0x00,
+ 0x01,0x00,0x50,0x00,0x72,0x00,0x6f,0x00,0x64,0x00,0x75,0x00,0x63,0x00,0x74,0x00,0x56,0x00,
+ 0x65,0x00,0x72,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x00,0x00,0x31,0x00,0x2c,0x00,
+ 0x20,0x00,0x30,0x00,0x2c,0x00,0x20,0x00,0x30,0x00,0x2c,0x00,0x20,0x00,0x31,0x00,0x00,0x00,
+ 0x00,0x00,0x44,0x00,0x00,0x00,0x01,0x00,0x56,0x00,0x61,0x00,0x72,0x00,0x46,0x00,0x69,0x00,
+ 0x6c,0x00,0x65,0x00,0x49,0x00,0x6e,0x00,0x66,0x00,0x6f,0x00,0x00,0x00,0x00,0x00,0x24,0x00,
+ 0x04,0x00,0x00,0x00,0x54,0x00,0x72,0x00,0x61,0x00,0x6e,0x00,0x73,0x00,0x6c,0x00,0x61,0x00,
+ 0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x00,0x00,0x00,0x00,0x09,0x04,0xb0,0x04,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+//} end
+#endif // _WIN32
+
+int msrdriver_dummy; // a dummy to avoid a linker warning on OS X.
diff --git a/contrib/libcpuid/include/libcpuid/rdmsr.c b/contrib/libcpuid/include/libcpuid/rdmsr.c
new file mode 100644
index 00000000000..a27e939bba0
--- /dev/null
+++ b/contrib/libcpuid/include/libcpuid/rdmsr.c
@@ -0,0 +1,922 @@
+/*
+ * Copyright 2009 Veselin Georgiev,
+ * anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+#define _XOPEN_SOURCE 500
+#include
+#include
+#include "libcpuid.h"
+#include "asm-bits.h"
+#include "libcpuid_util.h"
+#include "libcpuid_internal.h"
+#include "rdtsc.h"
+
+#if defined (__linux__) || defined (__gnu_linux__)
+/* Assuming linux with /dev/cpu/x/msr: */
+#include
+#include
+#include
+#include
+#include
+#include
+struct msr_driver_t { int fd; };
+static int rdmsr_supported(void);
+static int load_driver(char *msr_path)
+{
+ const int file_exists = !access(msr_path, F_OK);
+ const int file_readable = !access(msr_path, R_OK);
+
+ if (file_exists && file_readable)
+ return 1;
+ else if (file_exists && !file_readable)
+ return 0;
+ else if (getuid() != 0)
+ return 0;
+ else
+ return !system("modprobe msr 2> /dev/null");
+}
+
+struct msr_driver_t* cpu_msr_driver_open(void)
+{
+ return cpu_msr_driver_open_core(0);
+}
+
+struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num)
+{
+ char msr[32];
+ struct msr_driver_t* handle;
+ if (core_num >= cpuid_get_total_cpus()) {
+ set_error(ERR_INVCNB);
+ return NULL;
+ }
+ if (!rdmsr_supported()) {
+ set_error(ERR_NO_RDMSR);
+ return NULL;
+ }
+ sprintf(msr, "/dev/cpu/%u/msr", core_num);
+ if(!load_driver(msr)) {
+ set_error(ERR_NO_DRIVER);
+ return NULL;
+ }
+ int fd = open(msr, O_RDONLY);
+ if (fd < 0) {
+ if (errno == EIO) {
+ set_error(ERR_NO_RDMSR);
+ return NULL;
+ }
+ set_error(ERR_NO_DRIVER);
+ return NULL;
+ }
+ handle = (struct msr_driver_t*) malloc(sizeof(struct msr_driver_t));
+ handle->fd = fd;
+ return handle;
+}
+
+int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result)
+{
+ ssize_t ret;
+
+ if (!driver || driver->fd < 0)
+ return set_error(ERR_HANDLE);
+ ret = pread(driver->fd, result, 8, msr_index);
+ if (ret != 8)
+ return set_error(ERR_INVMSR);
+ return 0;
+}
+
+int cpu_msr_driver_close(struct msr_driver_t* drv)
+{
+ if (drv && drv->fd >= 0) {
+ close(drv->fd);
+ free(drv);
+ }
+ return 0;
+}
+
+/* #endif defined (__linux__) || defined (__gnu_linux__) */
+
+#elif defined (__FreeBSD__) || defined (__DragonFly__)
+/* Assuming FreeBSD with /dev/cpuctlX */
+#include
+#include
+#include
+#include
+#include
+
+struct msr_driver_t { int fd; };
+static int rdmsr_supported(void);
+static int load_driver(char *msr_path)
+{
+ const int file_exists = !access(msr_path, F_OK);
+ const int file_readable = !access(msr_path, R_OK);
+
+ if (file_exists && file_readable)
+ return 1;
+ else if (file_exists && !file_readable)
+ return 0;
+ else if (getuid() != 0)
+ return 0;
+ else
+ return !system("kldload -n cpuctl 2> /dev/null");
+}
+
+struct msr_driver_t* cpu_msr_driver_open(void)
+{
+ return cpu_msr_driver_open_core(0);
+}
+
+struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num)
+{
+ char msr[32];
+ struct msr_driver_t* handle;
+ if (core_num >= cpuid_get_total_cpus()) {
+ set_error(ERR_INVCNB);
+ return NULL;
+ }
+ if (!rdmsr_supported()) {
+ set_error(ERR_NO_RDMSR);
+ return NULL;
+ }
+ sprintf(msr, "/dev/cpuctl%u", core_num);
+ if(!load_driver(msr)) {
+ set_error(ERR_NO_DRIVER);
+ return NULL;
+ }
+ int fd = open(msr, O_RDONLY);
+ if (fd < 0) {
+ if (errno == EIO) {
+ set_error(ERR_NO_RDMSR);
+ return NULL;
+ }
+ set_error(ERR_NO_DRIVER);
+ return NULL;
+ }
+ handle = (struct msr_driver_t*) malloc(sizeof(struct msr_driver_t));
+ handle->fd = fd;
+ return handle;
+}
+
+int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result)
+{
+ cpuctl_msr_args_t args;
+ args.msr = msr_index;
+
+ if (!driver || driver->fd < 0)
+ return set_error(ERR_HANDLE);
+
+ if(ioctl(driver->fd, CPUCTL_RDMSR, &args))
+ return set_error(ERR_INVMSR);
+
+ *result = args.data;
+ return 0;
+}
+
+int cpu_msr_driver_close(struct msr_driver_t* drv)
+{
+ if (drv && drv->fd >= 0) {
+ close(drv->fd);
+ free(drv);
+ }
+ return 0;
+}
+
+/* #endif defined (__FreeBSD__) || defined (__DragonFly__) */
+
+#elif defined (_WIN32)
+#include
+#include
+#include
+
+extern uint8_t cc_x86driver_code[];
+extern int cc_x86driver_code_size;
+extern uint8_t cc_x64driver_code[];
+extern int cc_x64driver_code_size;
+
+struct msr_driver_t {
+ char driver_path[MAX_PATH + 1];
+ SC_HANDLE scManager;
+ volatile SC_HANDLE scDriver;
+ HANDLE hhDriver;
+ OVERLAPPED ovl;
+ int errorcode;
+};
+
+static int rdmsr_supported(void);
+static int extract_driver(struct msr_driver_t* driver);
+static int load_driver(struct msr_driver_t* driver);
+
+struct msr_driver_t* cpu_msr_driver_open(void)
+{
+ struct msr_driver_t* drv;
+ int status;
+ if (!rdmsr_supported()) {
+ set_error(ERR_NO_RDMSR);
+ return NULL;
+ }
+
+ drv = (struct msr_driver_t*) malloc(sizeof(struct msr_driver_t));
+ if (!drv) {
+ set_error(ERR_NO_MEM);
+ return NULL;
+ }
+ memset(drv, 0, sizeof(struct msr_driver_t));
+
+ if (!extract_driver(drv)) {
+ free(drv);
+ set_error(ERR_EXTRACT);
+ return NULL;
+ }
+
+ status = load_driver(drv);
+ if (!DeleteFile(drv->driver_path))
+ debugf(1, "Deleting temporary driver file failed.\n");
+ if (!status) {
+ set_error(drv->errorcode ? drv->errorcode : ERR_NO_DRIVER);
+ free(drv);
+ return NULL;
+ }
+ return drv;
+}
+
+struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num)
+{
+ warnf("cpu_msr_driver_open_core(): parameter ignored (function is the same as cpu_msr_driver_open)\n");
+ return cpu_msr_driver_open();
+}
+
+typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+static BOOL is_running_x64(void)
+{
+ BOOL bIsWow64 = FALSE;
+
+ LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(__TEXT("kernel32")), "IsWow64Process");
+ if(NULL != fnIsWow64Process)
+ fnIsWow64Process(GetCurrentProcess(), &bIsWow64);
+ return bIsWow64;
+}
+
+
+static int extract_driver(struct msr_driver_t* driver)
+{
+ FILE *f;
+ if (!GetTempPath(sizeof(driver->driver_path), driver->driver_path)) return 0;
+ strcat(driver->driver_path, "TmpRdr.sys");
+
+ f = fopen(driver->driver_path, "wb");
+ if (!f) return 0;
+ if (is_running_x64())
+ fwrite(cc_x64driver_code, 1, cc_x64driver_code_size, f);
+ else
+ fwrite(cc_x86driver_code, 1, cc_x86driver_code_size, f);
+ fclose(f);
+ return 1;
+}
+
+static BOOL wait_for_service_state(SC_HANDLE hService, DWORD dwDesiredState, SERVICE_STATUS *lpsrvStatus){
+ BOOL fOK = FALSE;
+ DWORD dwWaitHint;
+
+ if(hService != NULL){
+ while(TRUE){
+ fOK = QueryServiceStatus(hService, lpsrvStatus);
+ if(!fOK)
+ break;
+ if(lpsrvStatus->dwCurrentState == dwDesiredState)
+ break;
+
+ dwWaitHint = lpsrvStatus->dwWaitHint / 10; // Poll 1/10 of the wait hint
+ if (dwWaitHint < 1000)
+ dwWaitHint = 1000; // At most once per second
+ if (dwWaitHint > 10000)
+ dwWaitHint = 10000; // At least every 10 seconds
+ Sleep(dwWaitHint);
+ }
+ }
+
+ return fOK;
+}
+
+static int load_driver(struct msr_driver_t* drv)
+{
+ LPTSTR lpszInfo = __TEXT("RDMSR Executor Driver");
+ USHORT uLen = 0;
+ SERVICE_STATUS srvStatus = {0};
+ BOOL fRunning = FALSE;
+ DWORD dwLastError;
+ LPTSTR lpszDriverServiceName = __TEXT("TmpRdr");
+ TCHAR lpszDriverName[] = __TEXT("\\\\.\\Global\\TmpRdr");
+
+ if((LPVOID)(drv->scManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) != NULL) {
+ drv->scDriver = CreateService(drv->scManager, lpszDriverServiceName, lpszInfo, SERVICE_ALL_ACCESS,
+ SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
+ drv->driver_path, NULL, NULL, NULL, NULL, NULL);
+ if(drv->scDriver == NULL){
+ switch(dwLastError = GetLastError()){
+ case ERROR_SERVICE_EXISTS:
+ case ERROR_SERVICE_MARKED_FOR_DELETE:{
+ LPQUERY_SERVICE_CONFIG lpqsc;
+ DWORD dwBytesNeeded;
+
+ drv->scDriver = OpenService(drv->scManager, lpszDriverServiceName, SERVICE_ALL_ACCESS);
+ if(drv->scDriver == NULL){
+ debugf(1, "Error opening service: %d\n", GetLastError());
+ break;
+ }
+
+ QueryServiceConfig(drv->scDriver, NULL, 0, &dwBytesNeeded);
+ if((dwLastError = GetLastError()) == ERROR_INSUFFICIENT_BUFFER){
+ lpqsc = calloc(1, dwBytesNeeded);
+ if(!QueryServiceConfig(drv->scDriver, lpqsc, dwBytesNeeded, &dwBytesNeeded)){
+ free(lpqsc);
+ debugf(1, "Error query service config(adjusted buffer): %d\n", GetLastError());
+ goto clean_up;
+ }
+ else{
+ free(lpqsc);
+ }
+ }
+ else{
+ debugf(1, "Error query service config: %d\n", dwLastError);
+ goto clean_up;
+ }
+
+ break;
+ }
+ case ERROR_ACCESS_DENIED:
+ drv->errorcode = ERR_NO_PERMS;
+ break;
+ default:
+ debugf(1, "Create driver service failed: %d\n", dwLastError);
+ break;
+ }
+ }
+ if(drv->scDriver != NULL){
+ if(StartService(drv->scDriver, 0, NULL)){
+ if(!wait_for_service_state(drv->scDriver, SERVICE_RUNNING, &srvStatus)){
+ debugf(1, "Driver load failed.\n");
+ DeleteService(drv->scDriver);
+ CloseServiceHandle(drv->scManager);
+ drv->scDriver = NULL;
+ goto clean_up;
+ } else {
+ fRunning = TRUE;
+ }
+ } else{
+ if((dwLastError = GetLastError()) == ERROR_SERVICE_ALREADY_RUNNING)
+ fRunning = TRUE;
+ else{
+ debugf(1, "Driver start failed.\n");
+ DeleteService(drv->scDriver);
+ CloseServiceHandle(drv->scManager);
+ drv->scDriver = NULL;
+ goto clean_up;
+ }
+
+ }
+ if(fRunning)
+ debugf(1, "Driver already running.\n");
+ else
+ debugf(1, "Driver loaded.\n");
+ CloseServiceHandle(drv->scManager);
+ drv->hhDriver = CreateFile(lpszDriverName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+ drv->ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ return 1;
+ }
+ } else {
+ debugf(1, "Open SCM failed: %d\n", GetLastError());
+ }
+
+clean_up:
+ if(drv->scManager != NULL){
+ CloseServiceHandle(drv->scManager);
+ drv->scManager = 0; // pointless
+ }
+ if(drv->scDriver != NULL){
+ if(!DeleteService(drv->scDriver))
+ debugf(1, "Delete driver service failed: %d\n", GetLastError());
+ CloseServiceHandle(drv->scDriver);
+ drv->scDriver = 0;
+ }
+
+ return 0;
+}
+
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define IOCTL_UNKNOWN_BASE FILE_DEVICE_UNKNOWN
+#define IOCTL_PROCVIEW_RDMSR CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result)
+{
+ DWORD dwBytesReturned;
+ __int64 msrdata;
+ SERVICE_STATUS srvStatus = {0};
+
+ if (!driver)
+ return set_error(ERR_HANDLE);
+ DeviceIoControl(driver->hhDriver, IOCTL_PROCVIEW_RDMSR, &msr_index, sizeof(int), &msrdata, sizeof(__int64), &dwBytesReturned, &driver->ovl);
+ GetOverlappedResult(driver->hhDriver, &driver->ovl, &dwBytesReturned, TRUE);
+ *result = msrdata;
+ return 0;
+}
+
+int cpu_msr_driver_close(struct msr_driver_t* drv)
+{
+ SERVICE_STATUS srvStatus = {0};
+ if (drv == NULL) return 0;
+ if(drv->scDriver != NULL){
+ if (drv->hhDriver) CancelIo(drv->hhDriver);
+ if(drv->ovl.hEvent != NULL)
+ CloseHandle(drv->ovl.hEvent);
+ if (drv->hhDriver) CloseHandle(drv->hhDriver);
+ drv->hhDriver = NULL;
+ drv->ovl.hEvent = NULL;
+ if (ControlService(drv->scDriver, SERVICE_CONTROL_STOP, &srvStatus)){
+ if (wait_for_service_state(drv->scDriver, SERVICE_STOPPED, &srvStatus)){
+ DeleteService(drv->scDriver);
+ }
+ }
+ }
+ return 0;
+}
+
+/* endif defined (_WIN32) */
+
+#else /* Unsupported OS */
+/* On others OS (i.e., Darwin), we still do not support RDMSR, so supply dummy struct
+ and functions */
+
+#define RDMSR_UNSUPPORTED_OS
+
+struct msr_driver_t { int dummy; };
+struct msr_driver_t* cpu_msr_driver_open(void)
+{
+ set_error(ERR_NOT_IMP);
+ return NULL;
+}
+
+struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num)
+{
+ set_error(ERR_NOT_IMP);
+ return NULL;
+}
+
+int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result)
+{
+ return set_error(ERR_NOT_IMP);
+}
+
+int cpu_msr_driver_close(struct msr_driver_t* driver)
+{
+ return set_error(ERR_NOT_IMP);
+}
+
+int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit,
+ uint8_t lowbit, uint64_t* result)
+{
+ return set_error(ERR_NOT_IMP);
+}
+
+int cpu_msrinfo(struct msr_driver_t* driver, cpu_msrinfo_request_t which)
+{
+ return set_error(ERR_NOT_IMP);
+}
+
+#endif /* Unsupported OS */
+
+#ifndef RDMSR_UNSUPPORTED_OS
+
+/* Useful links for hackers:
+- AMD MSRs:
+ AMD BIOS and Kernel Developer’s Guide (BKDG)
+ * AMD Family 10h Processors
+ http://support.amd.com/TechDocs/31116.pdf
+ * AMD Family 11h Processors
+ http://support.amd.com/TechDocs/41256.pdf
+ * AMD Family 12h Processors
+ http://support.amd.com/TechDocs/41131.pdf
+ * AMD Family 14h Processors
+ http://support.amd.com/TechDocs/43170_14h_Mod_00h-0Fh_BKDG.pdf
+ * AMD Family 15h Processors
+ http://support.amd.com/TechDocs/42301_15h_Mod_00h-0Fh_BKDG.pdf
+ http://support.amd.com/TechDocs/42300_15h_Mod_10h-1Fh_BKDG.pdf
+ http://support.amd.com/TechDocs/49125_15h_Models_30h-3Fh_BKDG.pdf
+ http://support.amd.com/TechDocs/50742_15h_Models_60h-6Fh_BKDG.pdf
+ http://support.amd.com/TechDocs/49125_15h_Models_30h-3Fh_BKDG.pdf
+ * AMD Family 16h Processors
+ http://support.amd.com/TechDocs/48751_16h_bkdg.pdf
+ http://support.amd.com/TechDocs/52740_16h_Models_30h-3Fh_BKDG.pdf
+
+- Intel MSRs:
+ Intel® 64 and IA-32 Architectures Software Developer’s Manual
+ * Volume 3 (3A, 3B, 3C & 3D): System Programming Guide
+ http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-system-programming-manual-325384.pdf
+*/
+
+/* AMD MSRs addresses */
+#define MSR_PSTATE_L 0xC0010061
+#define MSR_PSTATE_S 0xC0010063
+#define MSR_PSTATE_0 0xC0010064
+#define MSR_PSTATE_7 0xC001006B
+
+/* Intel MSRs addresses */
+#define IA32_MPERF 0xE7
+#define IA32_APERF 0xE8
+#define IA32_PERF_STATUS 0x198
+#define IA32_THERM_STATUS 0x19C
+#define MSR_EBL_CR_POWERON 0x2A
+#define MSR_TURBO_RATIO_LIMIT 0x1AD
+#define MSR_TEMPERATURE_TARGET 0x1A2
+#define MSR_PERF_STATUS 0x198
+#define MSR_PLATFORM_INFO 0xCE
+
+
+static int rdmsr_supported(void)
+{
+ struct cpu_id_t* id = get_cached_cpuid();
+ return id->flags[CPU_FEATURE_MSR];
+}
+
+static int perfmsr_measure(struct msr_driver_t* handle, int msr)
+{
+ int err;
+ uint64_t a, b;
+ uint64_t x, y;
+ err = cpu_rdmsr(handle, msr, &x);
+ if (err) return CPU_INVALID_VALUE;
+ sys_precise_clock(&a);
+ busy_loop_delay(10);
+ cpu_rdmsr(handle, msr, &y);
+ sys_precise_clock(&b);
+ if (a >= b || x > y) return CPU_INVALID_VALUE;
+ return (int) ((y - x) / (b - a));
+}
+
+static int get_amd_multipliers(struct msr_driver_t* handle, struct cpu_id_t *id,
+ struct internal_id_info_t *internal,
+ uint32_t pstate, uint64_t *multiplier)
+{
+ int err;
+ static int clock = 0;
+ uint64_t CpuFid, CpuDid, CpuDidLSD;
+ double divisor;
+
+ if (pstate < MSR_PSTATE_0 || MSR_PSTATE_7 < pstate)
+ return 1;
+
+ switch (id->ext_family) {
+ case 0x11:
+ /* BKDG 11h, page 236
+ MSRC001_00[6B:64][8:6] is CpuDid
+ MSRC001_00[6B:64][5:0] is CpuFid
+ CPU COF is ((100 MHz * (CpuFid + 08h)) / (2^CpuDid)) */
+ err = cpu_rdmsr_range(handle, pstate, 8, 6, &CpuDid);
+ err += cpu_rdmsr_range(handle, pstate, 5, 0, &CpuFid);
+ *multiplier = (uint64_t) ((CpuFid + 0x8) / (1ull << CpuDid));
+ break;
+ case 0x12:
+ /* BKDG 12h, page 469
+ MSRC001_00[6B:64][8:4] is CpuFid
+ MSRC001_00[6B:64][3:0] is CpuDid
+ CPU COF is (100MHz * (CpuFid + 10h) / (divisor specified by CpuDid)) */
+ err = cpu_rdmsr_range(handle, pstate, 8, 4, &CpuFid);
+ err += cpu_rdmsr_range(handle, pstate, 3, 0, &CpuDid);
+ if (CpuDid == 0x0)
+ divisor = 1;
+ else if (CpuDid == 0x1)
+ divisor = 1.5;
+ else if (CpuDid == 0x2)
+ divisor = 2;
+ else if (CpuDid == 0x3)
+ divisor = 3;
+ else if (CpuDid == 0x4)
+ divisor = 4;
+ else if (CpuDid == 0x5)
+ divisor = 6;
+ else if (CpuDid == 0x6)
+ divisor = 8;
+ else if (CpuDid == 0x7)
+ divisor = 12;
+ else if (CpuDid == 0x8)
+ divisor = 16;
+ else
+ divisor = 0;
+
+ if (divisor > 0)
+ *multiplier = (uint64_t) ((CpuFid + 0x10) / divisor);
+ else
+ err++;
+ break;
+ case 0x14:
+ /* BKDG 14h, page 430
+ MSRC001_00[6B:64][8:4] is CpuDidMSD
+ MSRC001_00[6B:64][3:0] is CpuDidLSD
+ PLL COF is (100 MHz * (D18F3xD4[MainPllOpFreqId] + 10h))
+ Divisor is (CpuDidMSD + (CpuDidLSD * 0.25) + 1)
+ CPU COF is (main PLL frequency specified by D18F3xD4[MainPllOpFreqId]) / (core clock divisor specified by CpuDidMSD and CpuDidLSD) */
+ err = cpu_rdmsr_range(handle, pstate, 8, 4, &CpuDid);
+ err += cpu_rdmsr_range(handle, pstate, 3, 0, &CpuDidLSD);
+ if (clock == 0)
+ clock = cpu_clock_measure(100, 1) + 5; // Fake round
+ *multiplier = (uint64_t) ((clock / 100 + 0x10) / (CpuDid + CpuDidLSD * 0.25 + 1));
+ break;
+ case 0x10:
+ /* BKDG 10h, page 429
+ MSRC001_00[6B:64][8:6] is CpuDid
+ MSRC001_00[6B:64][5:0] is CpuFid
+ CPU COF is (100 MHz * (CpuFid + 10h) / (2^CpuDid)) */
+ case 0x15:
+ /* BKDG 15h, page 570/580/635/692 (00h-0Fh/10h-1Fh/30h-3Fh/60h-6Fh)
+ MSRC001_00[6B:64][8:6] is CpuDid
+ MSRC001_00[6B:64][5:0] is CpuFid
+ CoreCOF is (100 * (MSRC001_00[6B:64][CpuFid] + 10h) / (2^MSRC001_00[6B:64][CpuDid])) */
+ case 0x16:
+ /* BKDG 16h, page 549/611 (00h-0Fh/30h-3Fh)
+ MSRC001_00[6B:64][8:6] is CpuDid
+ MSRC001_00[6B:64][5:0] is CpuFid
+ CoreCOF is (100 * (MSRC001_00[6B:64][CpuFid] + 10h) / (2^MSRC001_00[6B:64][CpuDid])) */
+ err = cpu_rdmsr_range(handle, pstate, 8, 6, &CpuDid);
+ err += cpu_rdmsr_range(handle, pstate, 5, 0, &CpuFid);
+ *multiplier = (uint64_t) ((CpuFid + 0x10) / (1ull << CpuDid));
+ break;
+ default:
+ err = 1;
+ break;
+ }
+
+ return err;
+}
+
+static double get_info_min_multiplier(struct msr_driver_t* handle, struct cpu_id_t *id,
+ struct internal_id_info_t *internal)
+{
+ int err;
+ uint64_t reg;
+
+ if(id->vendor == VENDOR_INTEL) {
+ /* Refer links above
+ Table 35-12. MSRs in Next Generation Intel Atom Processors Based on the Goldmont Microarchitecture
+ Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem
+ Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.)
+ Table 35-23. Additional MSRs Supported by 3rd Generation Intel® Core™ Processors (based on Intel® microarchitecture code name Ivy Bridge)
+ Table 35-24. MSRs Supported by Intel® Xeon® Processors E5 v2 Product Family (based on Ivy Bridge-E microarchitecture)
+ Table 35-27. Additional MSRs Supported by Processors based on the Haswell or Haswell-E microarchitectures
+ Table 35-34. Additional MSRs Common to Intel® Xeon® Processor D and Intel Xeon Processors E5 v4 Family Based on the Broadwell Microarchitecture
+ Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phi™ Processors with DisplayFamily_DisplayModel Signature 06_57H
+ MSR_PLATFORM_INFO[47:40] is Maximum Efficiency Ratio
+ Maximum Efficiency Ratio is the minimum ratio that the processor can operates */
+ err = cpu_rdmsr_range(handle, MSR_PLATFORM_INFO, 47, 40, ®);
+ if (!err) return (double) reg;
+ }
+ else if(id->vendor == VENDOR_AMD) {
+ /* Refer links above
+ MSRC001_0061[6:4] is PstateMaxVal
+ PstateMaxVal is the lowest-performance non-boosted P-state */
+ err = cpu_rdmsr_range(handle, MSR_PSTATE_L, 6, 4, ®);
+ err += get_amd_multipliers(handle, id, internal, MSR_PSTATE_0 + (uint32_t) reg, ®);
+ if (!err) return (double) reg;
+ }
+
+ return (double) CPU_INVALID_VALUE / 100;
+}
+
+static double get_info_cur_multiplier(struct msr_driver_t* handle, struct cpu_id_t *id,
+ struct internal_id_info_t *internal)
+{
+ int err;
+ uint64_t reg;
+
+ if(id->vendor == VENDOR_INTEL && internal->code.intel == PENTIUM) {
+ err = cpu_rdmsr(handle, MSR_EBL_CR_POWERON, ®);
+ if (!err) return (double) ((reg>>22) & 0x1f);
+ }
+ else if(id->vendor == VENDOR_INTEL && internal->code.intel != PENTIUM) {
+ /* Refer links above
+ Table 35-2. IA-32 Architectural MSRs (Contd.)
+ IA32_PERF_STATUS[15:0] is Current performance State Value
+ [7:0] is 0x0, [15:8] looks like current ratio */
+ err = cpu_rdmsr_range(handle, IA32_PERF_STATUS, 15, 8, ®);
+ if (!err) return (double) reg;
+ }
+ else if(id->vendor == VENDOR_AMD) {
+ /* Refer links above
+ MSRC001_0063[2:0] is CurPstate */
+ err = cpu_rdmsr_range(handle, MSR_PSTATE_S, 2, 0, ®);
+ err += get_amd_multipliers(handle, id, internal, MSR_PSTATE_0 + (uint32_t) reg, ®);
+ if (!err) return (double) reg;
+ }
+
+ return (double) CPU_INVALID_VALUE / 100;
+}
+
+static double get_info_max_multiplier(struct msr_driver_t* handle, struct cpu_id_t *id,
+ struct internal_id_info_t *internal)
+{
+ int err;
+ uint64_t reg;
+
+ if(id->vendor == VENDOR_INTEL && internal->code.intel == PENTIUM) {
+ err = cpu_rdmsr(handle, IA32_PERF_STATUS, ®);
+ if (!err) return (double) ((reg >> 40) & 0x1f);
+ }
+ else if(id->vendor == VENDOR_INTEL && internal->code.intel != PENTIUM) {
+ /* Refer links above
+ Table 35-10. Specific MSRs Supported by Intel® Atom™ Processor C2000 Series with CPUID Signature 06_4DH
+ Table 35-12. MSRs in Next Generation Intel Atom Processors Based on the Goldmont Microarchitecture (Contd.)
+ Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem (Contd.)
+ Table 35-14. Additional MSRs in Intel® Xeon® Processor 5500 and 3400 Series
+ Table 35-16. Additional MSRs Supported by Intel Processors (Based on Intel® Microarchitecture Code Name Westmere)
+ Table 35-19. MSRs Supported by 2nd Generation Intel® Core™ Processors (Intel® microarchitecture code name Sandy Bridge)
+ Table 35-21. Selected MSRs Supported by Intel® Xeon® Processors E5 Family (based on Sandy Bridge microarchitecture)
+ Table 35-28. MSRs Supported by 4th Generation Intel® Core™ Processors (Haswell microarchitecture) (Contd.)
+ Table 35-30. Additional MSRs Supported by Intel® Xeon® Processor E5 v3 Family
+ Table 35-33. Additional MSRs Supported by Intel® Core™ M Processors and 5th Generation Intel® Core™ Processors
+ Table 35-34. Additional MSRs Common to Intel® Xeon® Processor D and Intel Xeon Processors E5 v4 Family Based on the Broadwell Microarchitecture
+ Table 35-37. Additional MSRs Supported by 6th Generation Intel® Core™ Processors Based on Skylake Microarchitecture
+ Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phi™ Processors with DisplayFamily_DisplayModel Signature 06_57H
+ MSR_TURBO_RATIO_LIMIT[7:0] is Maximum Ratio Limit for 1C */
+ err = cpu_rdmsr_range(handle, MSR_TURBO_RATIO_LIMIT, 7, 0, ®);
+ if (!err) return (double) reg;
+ }
+ else if(id->vendor == VENDOR_AMD) {
+ /* Refer links above
+ MSRC001_0064 is Pb0
+ Pb0 is the highest-performance boosted P-state */
+ err = get_amd_multipliers(handle, id, internal, MSR_PSTATE_0, ®);
+ if (!err) return (double) reg;
+ }
+
+ return (double) CPU_INVALID_VALUE / 100;
+}
+
+static int get_info_temperature(struct msr_driver_t* handle, struct cpu_id_t *id,
+ struct internal_id_info_t *internal)
+{
+ int err;
+ uint64_t DigitalReadout, ReadingValid, TemperatureTarget;
+
+ if(id->vendor == VENDOR_INTEL) {
+ /* Refer links above
+ Table 35-2. IA-32 Architectural MSRs
+ IA32_THERM_STATUS[22:16] is Digital Readout
+ IA32_THERM_STATUS[31] is Reading Valid
+
+ Table 35-6. MSRs Common to the Silvermont Microarchitecture and Newer Microarchitectures for Intel® Atom
+ Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem (Contd.)
+ Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.)
+ Table 35-24. MSRs Supported by Intel® Xeon® Processors E5 v2 Product Family (based on Ivy Bridge-E microarchitecture) (Contd.)
+ Table 35-34. Additional MSRs Common to Intel® Xeon® Processor D and Intel Xeon Processors E5 v4 Family Based on the Broadwell Microarchitecture
+ Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phi™ Processors with DisplayFamily_DisplayModel Signature 06_57H
+ MSR_TEMPERATURE_TARGET[23:16] is Temperature Target */
+ err = cpu_rdmsr_range(handle, IA32_THERM_STATUS, 22, 16, &DigitalReadout);
+ err += cpu_rdmsr_range(handle, IA32_THERM_STATUS, 31, 31, &ReadingValid);
+ err += cpu_rdmsr_range(handle, MSR_TEMPERATURE_TARGET, 23, 16, &TemperatureTarget);
+ if(!err && ReadingValid) return (int) (TemperatureTarget - DigitalReadout);
+ }
+
+ return CPU_INVALID_VALUE;
+}
+
+static double get_info_voltage(struct msr_driver_t* handle, struct cpu_id_t *id,
+ struct internal_id_info_t *internal)
+{
+ int err;
+ uint64_t reg, CpuVid;
+
+ if(id->vendor == VENDOR_INTEL) {
+ /* Refer links above
+ Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.)
+ MSR_PERF_STATUS[47:32] is Core Voltage
+ P-state core voltage can be computed by MSR_PERF_STATUS[37:32] * (float) 1/(2^13). */
+ err = cpu_rdmsr_range(handle, MSR_PERF_STATUS, 47, 32, ®);
+ if (!err) return (double) reg / (1 << 13);
+ }
+ else if(id->vendor == VENDOR_AMD) {
+ /* Refer links above
+ MSRC001_00[6B:64][15:9] is CpuVid
+ MSRC001_0063[2:0] is P-state Status
+ 2.4.1.6.3 Serial VID (SVI) Encodings: voltage = 1.550V - 0.0125V * SviVid[6:0] */
+ err = cpu_rdmsr_range(handle, MSR_PSTATE_S, 2, 0, ®);
+ err += cpu_rdmsr_range(handle, MSR_PSTATE_0 + (uint32_t) reg, 15, 9, &CpuVid);
+ if (!err && MSR_PSTATE_0 + (uint32_t) reg <= MSR_PSTATE_7) return 1.550 - 0.0125 * CpuVid;
+ }
+
+ return (double) CPU_INVALID_VALUE / 100;
+}
+
+static double get_info_bus_clock(struct msr_driver_t* handle, struct cpu_id_t *id,
+ struct internal_id_info_t *internal)
+{
+ int err;
+ static int clock = 0;
+ uint64_t reg;
+
+ if(clock == 0)
+ clock = cpu_clock_measure(100, 1);
+
+ if(id->vendor == VENDOR_INTEL) {
+ /* Refer links above
+ Table 35-12. MSRs in Next Generation Intel Atom Processors Based on the Goldmont Microarchitecture
+ Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem
+ Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.)
+ Table 35-23. Additional MSRs Supported by 3rd Generation Intel® Core™ Processors (based on Intel® microarchitecture code name Ivy Bridge)
+ Table 35-24. MSRs Supported by Intel® Xeon® Processors E5 v2 Product Family (based on Ivy Bridge-E microarchitecture)
+ Table 35-27. Additional MSRs Supported by Processors based on the Haswell or Haswell-E microarchitectures
+ Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phi™ Processors with DisplayFamily_DisplayModel Signature 06_57H
+ MSR_PLATFORM_INFO[15:8] is Maximum Non-Turbo Ratio */
+ err = cpu_rdmsr_range(handle, MSR_PLATFORM_INFO, 15, 8, ®);
+ if (!err) return (double) clock / reg;
+ }
+ else if(id->vendor == VENDOR_AMD) {
+ /* Refer links above
+ MSRC001_0061[2:0] is CurPstateLimit
+ CurPstateLimit is the highest-performance non-boosted P-state */
+ err = cpu_rdmsr_range(handle, MSR_PSTATE_L, 2, 0, ®);
+ err += get_amd_multipliers(handle, id, internal, MSR_PSTATE_0 + (uint32_t) reg, ®);
+ if (!err) return (double) clock / reg;
+ }
+
+ return (double) CPU_INVALID_VALUE / 100;
+}
+
+int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit,
+ uint8_t lowbit, uint64_t* result)
+{
+ int err;
+ const uint8_t bits = highbit - lowbit + 1;
+
+ if(highbit > 63 || lowbit > highbit)
+ return set_error(ERR_INVRANGE);
+
+ err = cpu_rdmsr(handle, msr_index, result);
+
+ if(!err && bits < 64) {
+ /* Show only part of register */
+ *result >>= lowbit;
+ *result &= (1ULL << bits) - 1;
+ }
+
+ return err;
+}
+
+int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which)
+{
+ struct cpu_raw_data_t raw;
+ static struct cpu_id_t id;
+ static struct internal_id_info_t internal;
+ internal.score = -1;
+
+ if (handle == NULL)
+ return set_error(ERR_HANDLE);
+
+ if (internal.score == -1) {
+ cpuid_get_raw_data(&raw);
+ cpu_ident_internal(&raw, &id, &internal);
+ }
+
+ switch (which) {
+ case INFO_MPERF:
+ return perfmsr_measure(handle, IA32_MPERF);
+ case INFO_APERF:
+ return perfmsr_measure(handle, IA32_APERF);
+ case INFO_MIN_MULTIPLIER:
+ return (int) (get_info_min_multiplier(handle, &id, &internal) * 100);
+ case INFO_CUR_MULTIPLIER:
+ return (int) (get_info_cur_multiplier(handle, &id, &internal) * 100);
+ case INFO_MAX_MULTIPLIER:
+ return (int) (get_info_max_multiplier(handle, &id, &internal) * 100);
+ case INFO_TEMPERATURE:
+ return get_info_temperature(handle, &id, &internal);
+ case INFO_THROTTLING:
+ return CPU_INVALID_VALUE;
+ case INFO_VOLTAGE:
+ return (int) (get_info_voltage(handle, &id, &internal) * 100);
+ case INFO_BCLK:
+ case INFO_BUS_CLOCK:
+ return (int) (get_info_bus_clock(handle, &id, &internal) * 100);
+ default:
+ return CPU_INVALID_VALUE;
+ }
+}
+
+#endif // RDMSR_UNSUPPORTED_OS
diff --git a/contrib/libcpuid/include/libcpuid/rdtsc.c b/contrib/libcpuid/include/libcpuid/rdtsc.c
index 5930681561a..df4543946f5 100644
--- a/contrib/libcpuid/include/libcpuid/rdtsc.c
+++ b/contrib/libcpuid/include/libcpuid/rdtsc.c
@@ -226,6 +226,45 @@ int cpu_clock_measure(int millis, int quad_check)
return (results[bi] + results[bj] + _zero) / 2;
}
+
+static void adjust_march_ic_multiplier(const struct cpu_id_t* id, int* numerator, int* denom)
+{
+ /*
+ * for cpu_clock_by_ic: we need to know how many clocks does a typical ADDPS instruction
+ * take, when issued in rapid succesion without dependencies. The whole idea of
+ * cpu_clock_by_ic was that this is easy to determine, at least it was back in 2010. Now
+ * it's getting progressively more hairy, but here are the current measurements:
+ *
+ * 1. For CPUs with 64-bit SSE units, ADDPS issue rate is 0.5 IPC (one insn in 2 clocks)
+ * 2. For CPUs with 128-bit SSE units, issue rate is exactly 1.0 IPC
+ * 3. For Bulldozer and later, it is 1.4 IPC (we multiply by 5/7)
+ * 4. For Skylake and later, it is 1.6 IPC (we multiply by 5/8)
+ */
+ //
+ if (id->sse_size < 128) {
+ debugf(1, "SSE execution path is 64-bit\n");
+ // on a CPU with half SSE unit length, SSE instructions execute at 0.5 IPC;
+ // the resulting value must be multiplied by 2:
+ *numerator = 2;
+ } else {
+ debugf(1, "SSE execution path is 128-bit\n");
+ }
+ //
+ // Bulldozer or later: assume 1.4 IPC
+ if (id->vendor == VENDOR_AMD && id->ext_family >= 21) {
+ debugf(1, "cpu_clock_by_ic: Bulldozer (or later) detected, dividing result by 1.4\n");
+ *numerator = 5;
+ *denom = 7; // multiply by 5/7, to divide by 1.4
+ }
+ //
+ // Skylake or later: assume 1.6 IPC
+ if (id->vendor == VENDOR_INTEL && id->ext_model >= 94) {
+ debugf(1, "cpu_clock_by_ic: Skylake (or later) detected, dividing result by 1.6\n");
+ *numerator = 5;
+ *denom = 8; // to divide by 1.6, multiply by 5/8
+ }
+}
+
int cpu_clock_by_ic(int millis, int runs)
{
int max_value = 0, cur_value, i, ri, cycles_inner, cycles_outer, c;
@@ -237,21 +276,7 @@ int cpu_clock_by_ic(int millis, int runs)
// if there aren't SSE instructions - we can't run the test at all
if (!id || !id->flags[CPU_FEATURE_SSE]) return -1;
//
- if (id->sse_size < 128) {
- debugf(1, "SSE execution path is 64-bit\n");
- // on a CPU with half SSE unit length, SSE instructions execute at 0.5 IPC;
- // the resulting value must be multiplied by 2:
- multiplier_numerator = 2;
- } else {
- debugf(1, "SSE execution path is 128-bit\n");
- }
- //
- // on a Bulldozer or later CPU, SSE instructions execute at 1.4 IPC, handle that as well:
- if (id->vendor == VENDOR_AMD && id->ext_family >= 21) {
- debugf(1, "cpu_clock_by_ic: Bulldozer (or later) detected, dividing result by 1.4\n");
- multiplier_numerator = 5;
- multiplier_denom = 7; // multiply by 5/7, to divide by 1.4
- }
+ adjust_march_ic_multiplier(id, &multiplier_numerator, &multiplier_denom);
//
tl = millis * 125; // (*1000 / 8)
cycles_inner = 128;
diff --git a/contrib/libcpuid/include/libcpuid/recog_amd.c b/contrib/libcpuid/include/libcpuid/recog_amd.c
index c5390b9fd24..2e6c8a9ead8 100644
--- a/contrib/libcpuid/include/libcpuid/recog_amd.c
+++ b/contrib/libcpuid/include/libcpuid/recog_amd.c
@@ -28,47 +28,16 @@
#include
#include
#include "libcpuid.h"
-#include "recog_amd.h"
#include "libcpuid_util.h"
+#include "libcpuid_internal.h"
+#include "recog_amd.h"
-enum _amd_code_t {
- NA,
- NO_CODE,
- OPTERON_GENERIC,
- OPTERON_800,
- ATHLON_XP,
- ATHLON_XP_M,
- ATHLON_XP_M_LV,
- ATHLON,
- ATHLON_MP,
- MOBILE_ATHLON64,
- ATHLON_FX,
- DURON,
- DURON_MP,
- MOBILE_DURON,
- MOBILE_SEMPRON,
- OPTERON_SINGLE,
- OPTERON_DUALCORE,
- OPTERON_800_DUALCORE,
- MOBILE_TURION,
- ATHLON_64,
- ATHLON_64_FX,
- TURION_64,
- TURION_X2,
- SEMPRON,
- M_SEMPRON,
- SEMPRON_DUALCORE,
- PHENOM,
- PHENOM2,
- ATHLON_64_X2,
- ATHLON_64_X3,
- ATHLON_64_X4,
- FUSION_C,
- FUSION_E,
- FUSION_EA,
- FUSION_Z,
+const struct amd_code_str { amd_code_t code; char *str; } amd_code_str[] = {
+ #define CODE(x) { x, #x }
+ #define CODE2(x, y) CODE(x)
+ #include "amd_code_t.h"
+ #undef CODE
};
-typedef enum _amd_code_t amd_code_t;
const struct match_entry_t cpudb_amd[] = {
{ -1, -1, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Unknown AMD CPU" },
@@ -146,6 +115,7 @@ const struct match_entry_t cpudb_amd[] = {
{ 15, -1, -1, 15, -1, 1, 1024, -1, ATHLON_64 , 0, "Athlon 64 (1024K)" },
{ 15, -1, -1, 15, -1, 1, -1, -1, ATHLON_FX , 0, "Athlon FX" },
{ 15, -1, -1, 15, -1, 1, -1, -1, ATHLON_64_FX , 0, "Athlon 64 FX" },
+ { 15, 3, -1, 15, 35, 2, -1, -1, ATHLON_64_FX , 0, "Athlon 64 FX X2 (Toledo)" },
{ 15, -1, -1, 15, -1, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (512K)" },
{ 15, -1, -1, 15, -1, 2, 1024, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (1024K)" },
{ 15, -1, -1, 15, -1, 1, 512, -1, TURION_64 , 0, "Turion 64 (512K)" },
@@ -237,31 +207,65 @@ const struct match_entry_t cpudb_amd[] = {
{ 15, 4, -1, 16, 10, 4, 512, -1, PHENOM2 , 0, "Phenom II X4 (Zosma)" },
{ 15, 4, -1, 16, 10, 6, 512, -1, PHENOM2 , 0, "Phenom II X6 (Thuban)" },
- { 15, 4, -1, 16, -1, 2, 1024, -1, ATHLON_64_X2 , 0, "Athlon II X2 (Regor)" },
- { 15, 4, -1, 16, -1, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon II X2 (Regor)" },
+ { 15, 6, -1, 16, 6, 2, 512, -1, ATHLON , 0, "Athlon II (Champlain)" },
+ { 15, 6, -1, 16, 6, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon II X2 (Regor)" },
+ { 15, 6, -1, 16, 6, 2, 1024, -1, ATHLON_64_X2 , 0, "Athlon II X2 (Regor)" },
{ 15, 5, -1, 16, 5, 3, 512, -1, ATHLON_64_X3 , 0, "Athlon II X3 (Rana)" },
{ 15, 5, -1, 16, 5, 4, 512, -1, ATHLON_64_X4 , 0, "Athlon II X4 (Propus)" },
- /* 2011 CPUs with AMD fusion: */
- { 15, -1, -1, 20, 1, 1, 512, -1, FUSION_C , 0, "Brazos Ontario" },
- { 15, -1, -1, 20, 1, 2, 512, -1, FUSION_C , 0, "Brazos Ontario (Dual-core)" },
- { 15, -1, -1, 20, 1, 1, 512, -1, FUSION_E , 0, "Brazos Zacate" },
- { 15, -1, -1, 20, 1, 2, 512, -1, FUSION_E , 0, "Brazos Zacate (Dual-core)" },
- { 15, -1, -1, 20, 1, 1, 512, -1, FUSION_Z , 0, "Brazos Desna" },
- { 15, -1, -1, 18, 1, 2, 512, -1, FUSION_EA , 0, "Llano X2" },
- { 15, -1, -1, 18, 1, 2, 1024, -1, FUSION_EA , 0, "Llano X2" },
- { 15, -1, -1, 18, 1, 3, 1024, -1, FUSION_EA , 0, "Llano X3" },
- { 15, -1, -1, 18, 1, 4, 1024, -1, FUSION_EA , 0, "Llano X4" },
+
+ /* 2011 CPUs: K10 architecture: Llano */
+ { 15, 1, -1, 18, 1, 2, 512, -1, FUSION_EA , 0, "Llano X2" },
+ { 15, 1, -1, 18, 1, 2, 1024, -1, FUSION_EA , 0, "Llano X2" },
+ { 15, 1, -1, 18, 1, 3, 1024, -1, FUSION_EA , 0, "Llano X3" },
+ { 15, 1, -1, 18, 1, 4, 1024, -1, FUSION_EA , 0, "Llano X4" },
+ /* 2011 CPUs: Bobcat architecture: Ontario, Zacate, Desna, Hondo */
+ { 15, 2, -1, 20, -1, 1, 512, -1, FUSION_C , 0, "Brazos Ontario" },
+ { 15, 2, -1, 20, -1, 2, 512, -1, FUSION_C , 0, "Brazos Ontario (Dual-core)" },
+ { 15, 1, -1, 20, -1, 1, 512, -1, FUSION_E , 0, "Brazos Zacate" },
+ { 15, 1, -1, 20, -1, 2, 512, -1, FUSION_E , 0, "Brazos Zacate (Dual-core)" },
+ { 15, 2, -1, 20, -1, 2, 512, -1, FUSION_Z , 0, "Brazos Desna (Dual-core)" },
+ /* 2012 CPUs: Piledriver architecture: Trinity and Richland */
+ { 15, 0, -1, 21, 10, 2, 1024, -1, FUSION_A , 0, "Trinity X2" },
+ { 15, 0, -1, 21, 16, 2, 1024, -1, FUSION_A , 0, "Trinity X2" },
+ { 15, 0, -1, 21, 10, 4, 1024, -1, FUSION_A , 0, "Trinity X4" },
+ { 15, 0, -1, 21, 16, 4, 1024, -1, FUSION_A , 0, "Trinity X4" },
+ { 15, 3, -1, 21, 13, 2, 1024, -1, FUSION_A , 0, "Richland X2" },
+ { 15, 3, -1, 21, 13, 4, 1024, -1, FUSION_A , 0, "Richland X4" },
+ /* 2013 CPUs: Jaguar architecture: Kabini and Temash */
+ { 15, 0, -1, 22, 0, 2, 1024, -1, FUSION_A , 0, "Kabini X2" },
+ { 15, 0, -1, 22, 0, 4, 1024, -1, FUSION_A , 0, "Kabini X4" },
+ /* 2014 CPUs: Steamroller architecture: Kaveri */
+ { 15, 0, -1, 21, 30, 2, 1024, -1, FUSION_A , 0, "Kaveri X2" },
+ { 15, 0, -1, 21, 30, 4, 1024, -1, FUSION_A , 0, "Kaveri X4" },
+ /* 2014 CPUs: Puma architecture: Beema and Mullins */
+ { 15, 0, -1, 22, 30, 2, 1024, -1, FUSION_E , 0, "Mullins X2" },
+ { 15, 0, -1, 22, 30, 4, 1024, -1, FUSION_A , 0, "Mullins X4" },
+ /* 2015 CPUs: Excavator architecture: Carrizo */
+ { 15, 1, -1, 21, 60, 2, 1024, -1, FUSION_A , 0, "Carrizo X2" },
+ { 15, 1, -1, 21, 60, 4, 1024, -1, FUSION_A , 0, "Carrizo X4" },
+ /* 2015 CPUs: Steamroller architecture: Godavari */
+ //TODO
+ /* 2016 CPUs: Excavator architecture: Bristol Ridge */
+ //TODO
/* Newer Opterons: */
- { 15, 9, -1, 16, 9, 8, -1, -1, OPTERON_GENERIC , 0, "Magny-Cours Opteron" },
+ { 15, 9, -1, 22, 9, 8, -1, -1, OPTERON_GENERIC , 0, "Magny-Cours Opteron" },
/* Bulldozer CPUs: */
+ { 15, -1, -1, 21, 0, 4, 2048, -1, NO_CODE , 0, "Bulldozer X2" },
{ 15, -1, -1, 21, 1, 4, 2048, -1, NO_CODE , 0, "Bulldozer X2" },
{ 15, -1, -1, 21, 1, 6, 2048, -1, NO_CODE , 0, "Bulldozer X3" },
{ 15, -1, -1, 21, 1, 8, 2048, -1, NO_CODE , 0, "Bulldozer X4" },
+ /* Piledriver CPUs: */
{ 15, -1, -1, 21, 2, 4, 2048, -1, NO_CODE , 0, "Vishera X2" },
{ 15, -1, -1, 21, 2, 6, 2048, -1, NO_CODE , 0, "Vishera X3" },
{ 15, -1, -1, 21, 2, 8, 2048, -1, NO_CODE , 0, "Vishera X4" },
+ /* Steamroller CPUs: */
+ //TODO
+ /* Excavator CPUs: */
+ //TODO
+ /* Zen CPUs: */
+ //TODO
};
@@ -287,6 +291,7 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
{ 12, CPU_FEATURE_SKINIT },
{ 13, CPU_FEATURE_WDT },
{ 16, CPU_FEATURE_FMA4 },
+ { 21, CPU_FEATURE_TBM },
};
const struct feature_map_t matchtable_edx87[] = {
{ 0, CPU_FEATURE_TS },
@@ -307,7 +312,7 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
}
- if (raw->ext_cpuid[0][0] >= 0x80000001)
+ if (raw->ext_cpuid[0][0] >= 0x80000007)
match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
if (raw->ext_cpuid[0][0] >= 0x8000001a) {
/* We have the extended info about SSE unit size */
@@ -320,7 +325,7 @@ static void decode_amd_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* d
{
int l3_result;
const int assoc_table[16] = {
- 0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 92, 128, 255
+ 0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, 255
};
unsigned n = raw->ext_cpuid[0][0];
@@ -442,24 +447,36 @@ static amd_code_t decode_amd_codename_part1(const char *bs)
if (match_pattern(bs, "Z-##")) return FUSION_Z;
if (match_pattern(bs, "E#-####") || match_pattern(bs, "A#-####")) return FUSION_EA;
- return NO_CODE;
+ return (amd_code_t) NO_CODE;
}
-static void decode_amd_codename(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
+static void decode_amd_codename(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
{
amd_code_t code = decode_amd_codename_part1(data->brand_str);
-
+ int i = 0;
+ char* code_str = NULL;
+ for (i = 0; i < COUNT_OF(amd_code_str); i++) {
+ if (code == amd_code_str[i].code) {
+ code_str = amd_code_str[i].str;
+ break;
+ }
+ }
if (code == ATHLON_64_X2 && data->l2_cache < 512)
code = SEMPRON_DUALCORE;
- match_cpu_codename(cpudb_amd, COUNT_OF(cpudb_amd), data, code, 0);
+ if (code_str)
+ debugf(2, "Detected AMD brand code: %d (%s)\n", code, code_str);
+ else
+ debugf(2, "Detected AMD brand code: %d\n", code);
+ internal->code.amd = code;
+ internal->score = match_cpu_codename(cpudb_amd, COUNT_OF(cpudb_amd), data, code, 0);
}
-int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
+int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
{
load_amd_features(raw, data);
decode_amd_cache_info(raw, data);
decode_amd_number_of_cores(raw, data);
- decode_amd_codename(raw, data);
+ decode_amd_codename(raw, data, internal);
return 0;
}
diff --git a/contrib/libcpuid/include/libcpuid/recog_amd.h b/contrib/libcpuid/include/libcpuid/recog_amd.h
index e0f3b61f727..34e89598397 100644
--- a/contrib/libcpuid/include/libcpuid/recog_amd.h
+++ b/contrib/libcpuid/include/libcpuid/recog_amd.h
@@ -26,7 +26,7 @@
#ifndef __RECOG_AMD_H__
#define __RECOG_AMD_H__
-int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
+int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal);
void cpuid_get_list_amd(struct cpu_list_t* list);
#endif /* __RECOG_AMD_H__ */
diff --git a/contrib/libcpuid/include/libcpuid/recog_intel.c b/contrib/libcpuid/include/libcpuid/recog_intel.c
index 625b2777f51..2ffc41c8a15 100644
--- a/contrib/libcpuid/include/libcpuid/recog_intel.c
+++ b/contrib/libcpuid/include/libcpuid/recog_intel.c
@@ -26,61 +26,16 @@
#include
#include
#include "libcpuid.h"
-#include "recog_intel.h"
#include "libcpuid_util.h"
+#include "libcpuid_internal.h"
+#include "recog_intel.h"
-
-enum _intel_code_t {
- NA,
- NO_CODE,
- PENTIUM = 10,
- MOBILE_PENTIUM,
-
- XEON = 20,
- XEON_IRWIN,
- XEONMP,
- XEON_POTOMAC,
- XEON_I7,
- XEON_GAINESTOWN,
- XEON_WESTMERE,
-
- MOBILE_PENTIUM_M = 30,
- CELERON,
- MOBILE_CELERON,
- NOT_CELERON,
-
-
- CORE_SOLO = 40,
- MOBILE_CORE_SOLO,
- CORE_DUO,
- MOBILE_CORE_DUO,
-
- WOLFDALE = 50,
- MEROM,
- PENRYN,
- QUAD_CORE,
- DUAL_CORE_HT,
- QUAD_CORE_HT,
- MORE_THAN_QUADCORE,
- PENTIUM_D,
-
- ATOM = 60,
- ATOM_SILVERTHORNE,
- ATOM_DIAMONDVILLE,
- ATOM_PINEVIEW,
- ATOM_CEDARVIEW,
-
- CORE_I3 = 70,
- CORE_I5,
- CORE_I7,
- CORE_IVY3, /* 22nm Core-iX */
- CORE_IVY5,
- CORE_IVY7,
- CORE_HASWELL3, /* 22nm Core-iX, Haswell */
- CORE_HASWELL5,
- CORE_HASWELL7,
+const struct intel_bcode_str { intel_code_t code; char *str; } intel_bcode_str[] = {
+ #define CODE(x) { x, #x }
+ #define CODE2(x, y) CODE(x)
+ #include "intel_code_t.h"
+ #undef CODE
};
-typedef enum _intel_code_t intel_code_t;
enum _intel_model_t {
UNKNOWN = -1,
@@ -134,12 +89,12 @@ const struct match_entry_t cpudb_intel[] = {
{ 6, 5, -1, -1, -1, 1, -1, -1, MOBILE_PENTIUM , 0, "Mobile Pentium II (Tonga)"},
{ 6, 6, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Pentium II (Dixon)" },
- { 6, 3, -1, -1, -1, 1, -1, -1, XEON , 0, "P-II Xeon" },
- { 6, 5, -1, -1, -1, 1, -1, -1, XEON , 0, "P-II Xeon" },
- { 6, 6, -1, -1, -1, 1, -1, -1, XEON , 0, "P-II Xeon" },
+ { 6, 3, -1, -1, -1, 1, -1, -1, XEON , 0, "P-II Xeon (Klamath)" },
+ { 6, 5, -1, -1, -1, 1, -1, -1, XEON , 0, "P-II Xeon (Drake)" },
+ { 6, 6, -1, -1, -1, 1, -1, -1, XEON , 0, "P-II Xeon (Dixon)" },
- { 6, 5, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-II Celeron (no L2)" },
- { 6, 6, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-II Celeron (128K)" },
+ { 6, 5, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-II Celeron (Covingtons" },
+ { 6, 6, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-II Celeron (Mendocino)" },
/* -------------------------------------------------- */
@@ -148,15 +103,15 @@ const struct match_entry_t cpudb_intel[] = {
{ 6, 10, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Pentium III (Coppermine)"},
{ 6, 11, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Pentium III (Tualatin)" },
- { 6, 7, -1, -1, -1, 1, -1, -1, XEON , 0, "P-III Xeon" },
- { 6, 8, -1, -1, -1, 1, -1, -1, XEON , 0, "P-III Xeon" },
- { 6, 10, -1, -1, -1, 1, -1, -1, XEON , 0, "P-III Xeon" },
- { 6, 11, -1, -1, -1, 1, -1, -1, XEON , 0, "P-III Xeon" },
+ { 6, 7, -1, -1, -1, 1, -1, -1, XEON , 0, "P-III Xeon (Tanner)" },
+ { 6, 8, -1, -1, -1, 1, -1, -1, XEON , 0, "P-III Xeon (Cascades)" },
+ { 6, 10, -1, -1, -1, 1, -1, -1, XEON , 0, "P-III Xeon (Cascades)" },
+ { 6, 11, -1, -1, -1, 1, -1, -1, XEON , 0, "P-III Xeon (Tualatin)" },
- { 6, 7, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-III Celeron" },
- { 6, 8, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-III Celeron" },
- { 6, 10, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-III Celeron" },
- { 6, 11, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-III Celeron" },
+ { 6, 7, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-III Celeron (Katmai)" },
+ { 6, 8, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-III Celeron (Coppermine)" },
+ { 6, 10, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-III Celeron (Coppermine)" },
+ { 6, 11, -1, -1, -1, 1, -1, -1, CELERON , 0, "P-III Celeron (Tualatin)" },
/* Netburst based (Pentium 4 and later)
classic P4s */
@@ -190,17 +145,17 @@ const struct match_entry_t cpudb_intel[] = {
{ 15, 6, -1, 15, -1, 1, -1, -1, XEON , 0, "Xeon (Dempsey)" },
/* Pentium Ds */
- { 15, 4, 4, 15, -1, 1, -1, -1, NO_CODE , 0, "Pentium D" },
- { 15, 4, -1, 15, -1, 1, -1, -1, PENTIUM_D , 0, "Pentium D" },
- { 15, 4, 7, 15, -1, 1, -1, -1, NO_CODE , 0, "Pentium D" },
- { 15, 6, -1, 15, -1, 1, -1, -1, PENTIUM_D , 0, "Pentium D" },
+ { 15, 4, 4, 15, -1, 1, -1, -1, NO_CODE , 0, "Pentium D (SmithField)" },
+ { 15, 4, -1, 15, -1, 1, -1, -1, PENTIUM_D , 0, "Pentium D (SmithField)" },
+ { 15, 4, 7, 15, -1, 1, -1, -1, NO_CODE , 0, "Pentium D (SmithField)" },
+ { 15, 6, -1, 15, -1, 1, -1, -1, PENTIUM_D , 0, "Pentium D (Presler)" },
/* Celeron and Celeron Ds */
- { 15, 1, -1, 15, -1, 1, -1, -1, CELERON , 0, "P-4 Celeron (128K)" },
- { 15, 2, -1, 15, -1, 1, -1, -1, CELERON , 0, "P-4 Celeron (128K)" },
- { 15, 3, -1, 15, -1, 1, -1, -1, CELERON , 0, "Celeron D" },
- { 15, 4, -1, 15, -1, 1, -1, -1, CELERON , 0, "Celeron D" },
- { 15, 6, -1, 15, -1, 1, -1, -1, CELERON , 0, "Celeron D" },
+ { 15, 1, -1, 15, -1, 1, -1, -1, CELERON , 0, "P-4 Celeron (Willamette)" },
+ { 15, 2, -1, 15, -1, 1, -1, -1, CELERON , 0, "P-4 Celeron (Northwood)" },
+ { 15, 3, -1, 15, -1, 1, -1, -1, CELERON , 0, "P-4 Celeron D (Prescott)" },
+ { 15, 4, -1, 15, -1, 1, -1, -1, CELERON , 0, "P-4 Celeron D (Prescott)" },
+ { 15, 6, -1, 15, -1, 1, -1, -1, CELERON , 0, "P-4 Celeron D (Cedar Mill)" },
/* -------------------------------------------------- */
/* Intel Core microarchitecture - P6-based */
@@ -214,7 +169,7 @@ const struct match_entry_t cpudb_intel[] = {
{ 6, 13, -1, -1, -1, 1, -1, -1, MOBILE_PENTIUM_M , 0, "Pentium M (Dothan)" },
{ 6, 13, -1, -1, -1, 1, -1, -1, CELERON , 0, "Celeron M" },
- { 6, 12, -1, -1, -1, -1, -1, -1, ATOM , 0, "Unknown Atom" },
+ { 6, 12, -1, -1, -1, -1, -1, -1, ATOM_UNKNOWN , 0, "Unknown Atom" },
{ 6, 12, -1, -1, -1, -1, -1, -1, ATOM_DIAMONDVILLE , 0, "Atom (Diamondville)" },
{ 6, 12, -1, -1, -1, -1, -1, -1, ATOM_SILVERTHORNE , 0, "Atom (Silverthorne)" },
{ 6, 12, -1, -1, -1, -1, -1, -1, ATOM_CEDARVIEW , 0, "Atom (Cedarview)" },
@@ -260,57 +215,13 @@ const struct match_entry_t cpudb_intel[] = {
{ 6, 7, -1, -1, 23, 2, 3072, -1, WOLFDALE , 0, "Wolfdale (Core 2 Duo) 3M" },
{ 6, 7, -1, -1, 23, 2, 6144, -1, WOLFDALE , 0, "Wolfdale (Core 2 Duo) 6M" },
{ 6, 7, -1, -1, 23, 1, -1, -1, MOBILE_CORE_DUO , 0, "Penryn (Core 2 Duo)" },
+ { 6, 7, -1, -1, 23, 2, 1024, -1, PENRYN , 0, "Penryn (Core 2 Duo)" },
{ 6, 7, -1, -1, 23, 2, 3072, -1, PENRYN , 0, "Penryn (Core 2 Duo) 3M" },
{ 6, 7, -1, -1, 23, 2, 6144, -1, PENRYN , 0, "Penryn (Core 2 Duo) 6M" },
{ 6, 7, -1, -1, 23, 4, 2048, -1, QUAD_CORE , 0, "Yorkfield (Core 2 Quad) 2M"},
{ 6, 7, -1, -1, 23, 4, 3072, -1, QUAD_CORE , 0, "Yorkfield (Core 2 Quad) 3M"},
{ 6, 7, -1, -1, 23, 4, 6144, -1, QUAD_CORE , 0, "Yorkfield (Core 2 Quad) 6M"},
- { 6, 5, -1, -1, 37, 2, -1, -1, NO_CODE , 0, "Unknown Core i3/i5 CPU" },
- { 6, 5, -1, -1, 37, 2, -1, 4096, CORE_I7 , 0, "Arrandale (Core i7)" },
- { 6, 5, -1, -1, 37, 2, -1, 3072, CORE_I5 , 0, "Arrandale (Core i5)" },
- { 6, 5, -1, -1, 37, 2, -1, 4096, CORE_I5 , 0, "Clarkdale (Core i5)" },
- { 6, 5, -1, -1, 37, 4, -1, 8192, CORE_I5 , 0, "Lynnfield (Core i5)" },
- { 6, 5, -1, -1, 37, 2, -1, 3072, CORE_I3 , 0, "Arrandale (Core i3)" },
- { 6, 5, -1, -1, 37, 2, -1, 4096, CORE_I3 , 0, "Clarkdale (Core i3)" },
-
- { 6, 10, -1, -1, 42, -1, -1, -1, NO_CODE , 0, "Unknown Sandy Bridge" },
- { 6, 10, -1, -1, 42, -1, -1, -1, CORE_I7 , 0, "Sandy Bridge i7" },
- { 6, 10, -1, -1, 42, 4, -1, -1, CORE_I7 , 0, "Sandy Bridge (Core i7)" },
- { 6, 10, -1, -1, 42, 4, -1, -1, CORE_I5 , 0, "Sandy Bridge (Core i5)" },
- { 6, 10, -1, -1, 42, 2, -1, -1, CORE_I3 , 0, "Sandy Bridge (Core i3)" },
- { 6, 10, -1, -1, 42, 1, -1, -1, CELERON , 0, "Celeron (Sandy Bridge)" },
- { 6, 10, -1, -1, 42, 2, -1, -1, CELERON , 0, "Celeron (Sandy Bridge)" },
- { 6, 10, -1, -1, 42, 2, -1, -1, PENTIUM , 0, "Pentium (Sandy Bridge)" },
-
- { 6, 10, -1, -1, 26, 1, -1, -1, CORE_I7 , 0, "Intel Core i7" },
- { 6, 10, -1, -1, 26, 4, -1, -1, CORE_I7 , 0, "Bloomfield (Core i7)" },
- { 6, 10, -1, -1, 30, 4, -1, -1, CORE_I7 , 0, "Lynnfield (Core i7)" },
- { 6, 10, -1, -1, 26, 4, -1, -1, XEON_I7 , 0, "Xeon (Bloomfield)" },
-
- { 6, 10, -1, -1, 26, 4, -1, -1, XEON_GAINESTOWN , 0, "Xeon (Gainestown)" },
- { 6, 10, -1, -1, 26, 4, -1, 4096, XEON_GAINESTOWN , 0, "Xeon (Gainestown) 4M" },
- { 6, 10, -1, -1, 26, 4, -1, 8192, XEON_GAINESTOWN , 0, "Xeon (Gainestown) 8M" },
-
- { 6, 12, -1, -1, 44, -1, -1, -1, XEON_WESTMERE , 0, "Xeon (Westmere-based)" },
- { 6, 12, -1, -1, 44, 4, -1, 12288, CORE_I7 , 0, "Gulftown (Core i7)" },
- { 6, 12, -1, -1, 44, -1, -1, 12288, XEON_WESTMERE , 0, "Xeon (Gulftown)" },
-
- { 6, 13, -1, -1, 45, -1, -1, -1, XEON , 0, "Xeon (Sandy Bridge)" },
-
- { 6, 13, -1, -1, 45, -1, -1, -1, CORE_I7 , 0, "Sandy Bridge-E (Core i7)" },
- { 6, 13, -1, -1, 45, -1, -1, -1, CORE_I5 , 0, "Sandy Bridge-E (Core i5)" },
- { 6, 13, -1, -1, 45, -1, -1, -1, CORE_I3 , 0, "Sandy Bridge-E (Core i3)" },
-
- { 6, 10, -1, -1, 58, 4, -1, -1, CORE_IVY7 , 0, "Ivy Bridge (Core i7)" },
- { 6, 10, -1, -1, 58, 4, -1, -1, CORE_IVY5 , 0, "Ivy Bridge (Core i5)" },
- { 6, 10, -1, -1, 58, 2, -1, -1, CORE_IVY3 , 0, "Ivy Bridge (Core i3)" },
-
- { 6, 12, -1, -1, 60, 4, -1, -1, CORE_HASWELL7 , 0, "Haswell (Core i7)" },
- { 6, 12, -1, -1, 60, 4, -1, -1, CORE_HASWELL5 , 0, "Haswell (Core i5)" },
- { 6, 12, -1, -1, 60, 2, -1, -1, CORE_HASWELL3 , 0, "Haswell (Core i3)" },
-
-
/* Core microarchitecture-based Xeons: */
{ 6, 14, -1, -1, 14, 1, -1, -1, XEON , 0, "Xeon LV" },
{ 6, 15, -1, -1, 15, 2, 4096, -1, XEON , _5100, "Xeon (Woodcrest)" },
@@ -324,6 +235,85 @@ const struct match_entry_t cpudb_intel[] = {
{ 6, 7, -1, -1, 23, 4, 3072, -1, XEON , X3300, "Xeon (Yorkfield/3M)" },
{ 6, 7, -1, -1, 23, 4, 6144, -1, XEON , X3300, "Xeon (Yorkfield/6M)" },
+ /* Nehalem CPUs (45nm): */
+ { 6, 10, -1, -1, 26, 4, -1, -1, XEON_GAINESTOWN , 0, "Gainestown (Xeon)" },
+ { 6, 10, -1, -1, 26, 4, -1, 4096, XEON_GAINESTOWN , 0, "Gainestown 4M (Xeon)" },
+ { 6, 10, -1, -1, 26, 4, -1, 8192, XEON_GAINESTOWN , 0, "Gainestown 8M (Xeon)" },
+ { 6, 10, -1, -1, 26, 4, -1, -1, XEON_I7 , 0, "Bloomfield (Xeon)" },
+ { 6, 10, -1, -1, 26, 4, -1, -1, CORE_I7 , 0, "Bloomfield (Core i7)" },
+ { 6, 10, -1, -1, 30, 4, -1, -1, CORE_I7 , 0, "Lynnfield (Core i7)" },
+ { 6, 5, -1, -1, 37, 4, -1, 8192, CORE_I5 , 0, "Lynnfield (Core i5)" },
+
+ /* Westmere CPUs (32nm): */
+ { 6, 5, -1, -1, 37, 2, -1, -1, NO_CODE , 0, "Unknown Core i3/i5" },
+ { 6, 12, -1, -1, 44, -1, -1, -1, XEON_WESTMERE , 0, "Westmere (Xeon)" },
+ { 6, 12, -1, -1, 44, -1, -1, 12288, XEON_WESTMERE , 0, "Gulftown (Xeon)" },
+ { 6, 12, -1, -1, 44, 4, -1, 12288, CORE_I7 , 0, "Gulftown (Core i7)" },
+ { 6, 5, -1, -1, 37, 2, -1, 4096, CORE_I5 , 0, "Clarkdale (Core i5)" },
+ { 6, 5, -1, -1, 37, 2, -1, 4096, CORE_I3 , 0, "Clarkdale (Core i3)" },
+ { 6, 5, -1, -1, 37, 2, -1, -1, PENTIUM , 0, "Arrandale" },
+ { 6, 5, -1, -1, 37, 2, -1, 4096, CORE_I7 , 0, "Arrandale (Core i7)" },
+ { 6, 5, -1, -1, 37, 2, -1, 3072, CORE_I5 , 0, "Arrandale (Core i5)" },
+ { 6, 5, -1, -1, 37, 2, -1, 3072, CORE_I3 , 0, "Arrandale (Core i3)" },
+
+ /* Sandy Bridge CPUs (32nm): */
+ { 6, 10, -1, -1, 42, -1, -1, -1, NO_CODE , 0, "Unknown Sandy Bridge" },
+ { 6, 10, -1, -1, 42, -1, -1, -1, XEON , 0, "Sandy Bridge (Xeon)" },
+ { 6, 10, -1, -1, 42, -1, -1, -1, CORE_I7 , 0, "Sandy Bridge (Core i7)" },
+ { 6, 10, -1, -1, 42, 4, -1, -1, CORE_I7 , 0, "Sandy Bridge (Core i7)" },
+ { 6, 10, -1, -1, 42, 4, -1, -1, CORE_I5 , 0, "Sandy Bridge (Core i5)" },
+ { 6, 10, -1, -1, 42, 2, -1, -1, CORE_I3 , 0, "Sandy Bridge (Core i3)" },
+ { 6, 10, -1, -1, 42, 2, -1, -1, PENTIUM , 0, "Sandy Bridge (Pentium)" },
+ { 6, 10, -1, -1, 42, 1, -1, -1, CELERON , 0, "Sandy Bridge (Celeron)" },
+ { 6, 10, -1, -1, 42, 2, -1, -1, CELERON , 0, "Sandy Bridge (Celeron)" },
+ { 6, 13, -1, -1, 45, -1, -1, -1, NO_CODE , 0, "Sandy Bridge-E" },
+ { 6, 13, -1, -1, 45, -1, -1, -1, XEON , 0, "Sandy Bridge-E (Xeon)" },
+
+ /* Ivy Bridge CPUs (22nm): */
+ { 6, 10, -1, -1, 58, -1, -1, -1, XEON , 0, "Ivy Bridge (Xeon)" },
+ { 6, 10, -1, -1, 58, 4, -1, -1, CORE_IVY7 , 0, "Ivy Bridge (Core i7)" },
+ { 6, 10, -1, -1, 58, 4, -1, -1, CORE_IVY5 , 0, "Ivy Bridge (Core i5)" },
+ { 6, 10, -1, -1, 58, 2, -1, -1, CORE_IVY3 , 0, "Ivy Bridge (Core i3)" },
+ { 6, 10, -1, -1, 58, 2, -1, -1, PENTIUM , 0, "Ivy Bridge (Pentium)" },
+ { 6, 10, -1, -1, 58, 1, -1, -1, CELERON , 0, "Ivy Bridge (Celeron)" },
+ { 6, 10, -1, -1, 58, 2, -1, -1, CELERON , 0, "Ivy Bridge (Celeron)" },
+ { 6, 14, -1, -1, 62, -1, -1, -1, NO_CODE , 0, "Ivy Bridge-E" },
+
+ /* Haswell CPUs (22nm): */
+ { 6, 12, -1, -1, 60, -1, -1, -1, XEON , 0, "Haswell (Xeon)" },
+ { 6, 12, -1, -1, 60, 4, -1, -1, CORE_HASWELL7 , 0, "Haswell (Core i7)" },
+ { 6, 5, -1, -1, 69, 4, -1, -1, CORE_HASWELL7 , 0, "Haswell (Core i7)" },
+ { 6, 12, -1, -1, 60, 4, -1, -1, CORE_HASWELL5 , 0, "Haswell (Core i5)" },
+ { 6, 5, -1, -1, 69, 4, -1, -1, CORE_HASWELL5 , 0, "Haswell (Core i5)" },
+ { 6, 12, -1, -1, 60, 2, -1, -1, CORE_HASWELL3 , 0, "Haswell (Core i3)" },
+ { 6, 5, -1, -1, 69, 2, -1, -1, CORE_HASWELL3 , 0, "Haswell (Core i3)" },
+ { 6, 12, -1, -1, 60, 2, -1, -1, PENTIUM , 0, "Haswell (Pentium)" },
+ { 6, 12, -1, -1, 60, 2, -1, -1, CELERON , 0, "Haswell (Celeron)" },
+ { 6, 12, -1, -1, 60, 1, -1, -1, CELERON , 0, "Haswell (Celeron)" },
+ { 6, 15, -1, -1, 63, -1, -1, -1, NO_CODE , 0, "Haswell-E" },
+
+ /* Broadwell CPUs (14nm): */
+ { 6, 7, -1, -1, 71, 4, -1, -1, CORE_BROADWELL7 , 0, "Broadwell (Core i7)" },
+ { 6, 7, -1, -1, 71, 4, -1, -1, CORE_BROADWELL5 , 0, "Broadwell (Core i5)" },
+ { 6, 13, -1, -1, 61, 4, -1, -1, CORE_BROADWELL7 , 0, "Broadwell-U (Core i7)" },
+ { 6, 13, -1, -1, 61, 2, -1, -1, CORE_BROADWELL7 , 0, "Broadwell-U (Core i7)" },
+ { 6, 13, -1, -1, 61, 2, -1, -1, CORE_BROADWELL5 , 0, "Broadwell-U (Core i5)" },
+ { 6, 13, -1, -1, 61, 2, -1, -1, CORE_BROADWELL3 , 0, "Broadwell-U (Core i3)" },
+ { 6, 13, -1, -1, 61, 2, -1, -1, PENTIUM , 0, "Broadwell-U (Pentium)" },
+ { 6, 13, -1, -1, 61, 2, -1, -1, CELERON , 0, "Broadwell-U (Celeron)" },
+ { 6, 13, -1, -1, 61, 2, -1, -1, NA , 0, "Broadwell-U (Core M)" },
+ { 6, 15, -1, -1, 79, 2, -1, -1, CORE_BROADWELL3 , 0, "Broadwell-E (Core i3)" },
+ { 6, 15, -1, -1, 79, 2, -1, -1, CORE_BROADWELL5 , 0, "Broadwell-E (Core i5)" },
+ { 6, 15, -1, -1, 79, 4, -1, -1, CORE_BROADWELL5 , 0, "Broadwell-E (Core i5)" },
+ { 6, 15, -1, -1, 79, 2, -1, -1, CORE_BROADWELL7 , 0, "Broadwell-E (Core i7)" },
+ { 6, 15, -1, -1, 79, 4, -1, -1, CORE_BROADWELL7 , 0, "Broadwell-E (Core i7)" },
+
+ /* Skylake CPUs (14nm): */
+ { 6, 14, -1, -1, 94, 4, -1, -1, CORE_BROADWELL7 , 0, "Skylake (Core i7)" },
+ { 6, 14, -1, -1, 94, 4, -1, -1, CORE_BROADWELL5 , 0, "Skylake (Core i5)" },
+ { 6, 14, -1, -1, 94, 4, -1, -1, CORE_BROADWELL3 , 0, "Skylake (Core i3)" },
+ { 6, 14, -1, -1, 94, 4, -1, -1, PENTIUM , 0, "Skylake (Pentium)" },
+
/* Itaniums */
{ 7, -1, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Itanium" },
{ 15, -1, -1, 16, -1, 1, -1, -1, NO_CODE , 0, "Itanium 2" },
@@ -343,7 +333,6 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
{ 31, CPU_FEATURE_PBE },
};
const struct feature_map_t matchtable_ecx1[] = {
- { 1, CPU_FEATURE_PCLMUL },
{ 2, CPU_FEATURE_DTS64 },
{ 4, CPU_FEATURE_DS_CPL },
{ 5, CPU_FEATURE_VMX },
@@ -354,37 +343,45 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
{ 14, CPU_FEATURE_XTPR },
{ 15, CPU_FEATURE_PDCM },
{ 18, CPU_FEATURE_DCA },
- { 20, CPU_FEATURE_SSE4_2 },
- { 22, CPU_FEATURE_MOVBE },
- { 25, CPU_FEATURE_AES },
- { 26, CPU_FEATURE_XSAVE },
- { 27, CPU_FEATURE_OSXSAVE },
- { 28, CPU_FEATURE_AVX },
- { 30, CPU_FEATURE_RDRAND },
- };
- const struct feature_map_t matchtable_ebx7[] = {
- { 5, CPU_FEATURE_AVX2 },
+ { 21, CPU_FEATURE_X2APIC },
};
const struct feature_map_t matchtable_edx81[] = {
{ 20, CPU_FEATURE_XD },
};
+ const struct feature_map_t matchtable_ebx7[] = {
+ { 2, CPU_FEATURE_SGX },
+ { 4, CPU_FEATURE_HLE },
+ { 11, CPU_FEATURE_RTM },
+ { 16, CPU_FEATURE_AVX512F },
+ { 17, CPU_FEATURE_AVX512DQ },
+ { 18, CPU_FEATURE_RDSEED },
+ { 19, CPU_FEATURE_ADX },
+ { 26, CPU_FEATURE_AVX512PF },
+ { 27, CPU_FEATURE_AVX512ER },
+ { 28, CPU_FEATURE_AVX512CD },
+ { 29, CPU_FEATURE_SHA_NI },
+ { 30, CPU_FEATURE_AVX512BW },
+ { 31, CPU_FEATURE_AVX512VL },
+ };
if (raw->basic_cpuid[0][0] >= 1) {
match_features(matchtable_edx1, COUNT_OF(matchtable_edx1), raw->basic_cpuid[1][3], data);
match_features(matchtable_ecx1, COUNT_OF(matchtable_ecx1), raw->basic_cpuid[1][2], data);
}
- if (raw->basic_cpuid[0][0] >= 7) {
- match_features(matchtable_ebx7, COUNT_OF(matchtable_ebx7), raw->basic_cpuid[7][1], data);
- }
if (raw->ext_cpuid[0][0] >= 1) {
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
}
+ // detect TSX/AVX512:
+ if (raw->basic_cpuid[0][0] >= 7) {
+ match_features(matchtable_ebx7, COUNT_OF(matchtable_ebx7), raw->basic_cpuid[7][1], data);
+ }
}
enum _cache_type_t {
L1I,
L1D,
L2,
- L3
+ L3,
+ L4
};
typedef enum _cache_type_t cache_type_t;
@@ -409,6 +406,12 @@ static void check_case(uint8_t on, cache_type_t cache, int size, int assoc, int
data->l3_cache = size;
data->l3_assoc = assoc;
data->l3_cacheline = linesize;
+ break;
+ case L4:
+ data->l4_cache = size;
+ data->l4_assoc = assoc;
+ data->l4_cacheline = linesize;
+ break;
default:
break;
}
@@ -529,6 +532,8 @@ static void decode_intel_deterministic_cache_info(struct cpu_raw_data_t* raw,
type = L2;
else if (level == 3 && typenumber == 3)
type = L3;
+ else if (level == 4 && typenumber == 3)
+ type = L4;
else {
warnf("deterministic_cache: unknown level/typenumber combo (%d/%d), cannot\n", level, typenumber);
warnf("deterministic_cache: recognize cache type\n");
@@ -561,8 +566,12 @@ static int decode_intel_extended_topology(struct cpu_raw_data_t* raw,
}
}
if (num_smt == -1 || num_core == -1) return 0;
- data->num_cores = num_core / num_smt;
data->num_logical_cpus = num_core;
+ data->num_cores = num_core / num_smt;
+ // make sure num_cores is at least 1. In VMs, the CPUID instruction
+ // is rigged and may give nonsensical results, but we should at least
+ // avoid outputs like data->num_cores == 0.
+ if (data->num_cores <= 0) data->num_cores = 1;
return 1;
}
@@ -587,7 +596,9 @@ static void decode_intel_number_of_cores(struct cpu_raw_data_t* raw,
data->num_logical_cpus = logical_cpus;
} else {
data->num_cores = 1;
- data->num_logical_cpus = (logical_cpus >= 2 ? logical_cpus : 2);
+ data->num_logical_cpus = (logical_cpus >= 1 ? logical_cpus : 1);
+ if (data->num_logical_cpus == 1)
+ data->flags[CPU_FEATURE_HT] = 0;
}
} else {
data->num_cores = data->num_logical_cpus = 1;
@@ -596,7 +607,7 @@ static void decode_intel_number_of_cores(struct cpu_raw_data_t* raw,
static intel_code_t get_brand_code(struct cpu_id_t* data)
{
- intel_code_t code = NO_CODE;
+ intel_code_t code = (intel_code_t) NO_CODE;
int i, need_matchtable = 1, core_ix_base = 0;
const char* bs = data->brand_str;
const char* s;
@@ -607,15 +618,16 @@ static intel_code_t get_brand_code(struct cpu_id_t* data)
{ CELERON, "Celeron" },
{ MOBILE_PENTIUM_M, "Pentium(R) M" },
{ CORE_SOLO, "Pentium(R) Dual CPU" },
+ { CORE_SOLO, "Pentium(R) Dual-Core" },
{ PENTIUM_D, "Pentium(R) D" },
{ PENTIUM, "Pentium" },
{ CORE_SOLO, "Genuine Intel(R) CPU" },
{ CORE_SOLO, "Intel(R) Core(TM)" },
{ ATOM_DIAMONDVILLE, "Atom(TM) CPU [N ][23]## " },
{ ATOM_SILVERTHORNE, "Atom(TM) CPU Z" },
- { ATOM_PINEVIEW, "Atom(TM) CPU D" },
- { ATOM_CEDARVIEW, "Atom(TM) CPU N####" },
- { ATOM, "Atom(TM) CPU" },
+ { ATOM_PINEVIEW, "Atom(TM) CPU [ND][45]## " },
+ { ATOM_CEDARVIEW, "Atom(TM) CPU [ND]#### " },
+ { ATOM_UNKNOWN, "Atom(TM) CPU" },
};
if (strstr(bs, "Mobile")) {
@@ -637,6 +649,9 @@ static intel_code_t get_brand_code(struct cpu_id_t* data)
/* if it has FMA, then it is at least Haswell */
if (data->flags[CPU_FEATURE_FMA3])
core_ix_base = CORE_HASWELL3;
+ /* if it has RTM, then it is at least a Broadwell-E or Skylake */
+ if (data->flags[CPU_FEATURE_RDSEED])
+ core_ix_base = CORE_BROADWELL3;
switch (bs[i + 9]) {
case '3': code = core_ix_base + 0; break;
@@ -659,7 +674,8 @@ static intel_code_t get_brand_code(struct cpu_id_t* data)
code = XEON_GAINESTOWN;
else if (match_pattern(bs, "[ELXW]56##"))
code = XEON_WESTMERE;
- else if (data->l3_cache > 0)
+ else if (data->l3_cache > 0 && data->family == 16)
+ /* restrict by family, since later Xeons also have L3 ... */
code = XEON_IRWIN;
}
if (code == XEONMP && data->l3_cache > 0)
@@ -770,8 +786,75 @@ static intel_model_t get_model_code(struct cpu_id_t* data)
#undef HAVE
}
-int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
+static void decode_intel_sgx_features(const struct cpu_raw_data_t* raw, struct cpu_id_t* data)
{
+ struct cpu_epc_t epc;
+ int i;
+
+ if (raw->basic_cpuid[0][0] < 0x12) return; // no 12h leaf
+ if (raw->basic_cpuid[0x12][0] == 0) return; // no sub-leafs available, probably it's disabled by BIOS
+
+ // decode sub-leaf 0:
+ if (raw->basic_cpuid[0x12][0] & 1) data->sgx.flags[INTEL_SGX1] = 1;
+ if (raw->basic_cpuid[0x12][0] & 2) data->sgx.flags[INTEL_SGX2] = 1;
+ if (data->sgx.flags[INTEL_SGX1] || data->sgx.flags[INTEL_SGX2])
+ data->sgx.present = 1;
+ data->sgx.misc_select = raw->basic_cpuid[0x12][1];
+ data->sgx.max_enclave_32bit = (raw->basic_cpuid[0x12][3] ) & 0xff;
+ data->sgx.max_enclave_64bit = (raw->basic_cpuid[0x12][3] >> 8) & 0xff;
+
+ // decode sub-leaf 1:
+ data->sgx.secs_attributes = raw->intel_fn12h[1][0] | (((uint64_t) raw->intel_fn12h[1][1]) << 32);
+ data->sgx.secs_xfrm = raw->intel_fn12h[1][2] | (((uint64_t) raw->intel_fn12h[1][3]) << 32);
+
+ // decode higher-order subleafs, whenever present:
+ data->sgx.num_epc_sections = -1;
+ for (i = 0; i < 1000000; i++) {
+ epc = cpuid_get_epc(i, raw);
+ if (epc.length == 0) {
+ debugf(2, "SGX: epc section request for %d returned null, no more EPC sections.\n", i);
+ data->sgx.num_epc_sections = i;
+ break;
+ }
+ }
+ if (data->sgx.num_epc_sections == -1) {
+ debugf(1, "SGX: warning: seems to be infinitude of EPC sections.\n");
+ data->sgx.num_epc_sections = 1000000;
+ }
+}
+
+struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw)
+{
+ uint32_t regs[4];
+ struct cpu_epc_t retval = {0, 0};
+ if (raw && index < MAX_INTELFN12H_LEVEL - 2) {
+ // this was queried already, use the data:
+ memcpy(regs, raw->intel_fn12h[2 + index], sizeof(regs));
+ } else {
+ // query this ourselves:
+ regs[0] = 0x12;
+ regs[2] = 2 + index;
+ regs[1] = regs[3] = 0;
+ cpu_exec_cpuid_ext(regs);
+ }
+
+ // decode values:
+ if ((regs[0] & 0xf) == 0x1) {
+ retval.start_addr |= (regs[0] & 0xfffff000); // bits [12, 32) -> bits [12, 32)
+ retval.start_addr |= ((uint64_t) (regs[1] & 0x000fffff)) << 32; // bits [0, 20) -> bits [32, 52)
+ retval.length |= (regs[2] & 0xfffff000); // bits [12, 32) -> bits [12, 32)
+ retval.length |= ((uint64_t) (regs[3] & 0x000fffff)) << 32; // bits [0, 20) -> bits [32, 52)
+ }
+ return retval;
+}
+
+int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
+{
+ intel_code_t brand_code;
+ intel_model_t model_code;
+ int i;
+ char* brand_code_str = NULL;
+
load_intel_features(raw, data);
if (raw->basic_cpuid[0][0] >= 4) {
/* Deterministic way is preferred, being more generic */
@@ -780,8 +863,31 @@ int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
decode_intel_oldstyle_cache_info(raw, data);
}
decode_intel_number_of_cores(raw, data);
- match_cpu_codename(cpudb_intel, COUNT_OF(cpudb_intel), data,
- get_brand_code(data), get_model_code(data));
+
+ brand_code = get_brand_code(data);
+ model_code = get_model_code(data);
+ for (i = 0; i < COUNT_OF(intel_bcode_str); i++) {
+ if (brand_code == intel_bcode_str[i].code) {
+ brand_code_str = intel_bcode_str[i].str;
+ break;
+ }
+ }
+ if (brand_code_str)
+ debugf(2, "Detected Intel brand code: %d (%s)\n", brand_code, brand_code_str);
+ else
+ debugf(2, "Detected Intel brand code: %d\n", brand_code);
+ debugf(2, "Detected Intel model code: %d\n", model_code);
+
+ internal->code.intel = brand_code;
+
+ if (data->flags[CPU_FEATURE_SGX]) {
+ debugf(2, "SGX seems to be present, decoding...\n");
+ // if SGX is indicated by the CPU, verify its presence:
+ decode_intel_sgx_features(raw, data);
+ }
+
+ internal->score = match_cpu_codename(cpudb_intel, COUNT_OF(cpudb_intel), data,
+ brand_code, model_code);
return 0;
}
diff --git a/contrib/libcpuid/include/libcpuid/recog_intel.h b/contrib/libcpuid/include/libcpuid/recog_intel.h
index 67279373271..b99c783bf43 100644
--- a/contrib/libcpuid/include/libcpuid/recog_intel.h
+++ b/contrib/libcpuid/include/libcpuid/recog_intel.h
@@ -26,7 +26,7 @@
#ifndef __RECOG_INTEL_H__
#define __RECOG_INTEL_H__
-int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
+int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal);
void cpuid_get_list_intel(struct cpu_list_t* list);
#endif /*__RECOG_INTEL_H__*/