|
@@ -26,67 +26,16 @@
|
|
|
#include <string.h>
|
|
#include <string.h>
|
|
|
#include <ctype.h>
|
|
#include <ctype.h>
|
|
|
#include "libcpuid.h"
|
|
#include "libcpuid.h"
|
|
|
-#include "recog_intel.h"
|
|
|
|
|
#include "libcpuid_util.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,
|
|
|
|
|
- CORE_BROADWELL3, /* 14nm Core-iX, Broadwell */
|
|
|
|
|
- CORE_BROADWELL5,
|
|
|
|
|
- CORE_BROADWELL7,
|
|
|
|
|
- CORE_SKYLAKE3, /* 14nm Core-iX, Skylake */
|
|
|
|
|
- CORE_SKYLAKE5,
|
|
|
|
|
- CORE_SKYLAKE7,
|
|
|
|
|
|
|
+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 {
|
|
enum _intel_model_t {
|
|
|
UNKNOWN = -1,
|
|
UNKNOWN = -1,
|
|
@@ -140,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, 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, 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)" },
|
|
|
|
|
|
|
|
/* -------------------------------------------------- */
|
|
/* -------------------------------------------------- */
|
|
|
|
|
|
|
@@ -154,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, 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, 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)
|
|
/* Netburst based (Pentium 4 and later)
|
|
|
classic P4s */
|
|
classic P4s */
|
|
@@ -196,17 +145,17 @@ const struct match_entry_t cpudb_intel[] = {
|
|
|
{ 15, 6, -1, 15, -1, 1, -1, -1, XEON , 0, "Xeon (Dempsey)" },
|
|
{ 15, 6, -1, 15, -1, 1, -1, -1, XEON , 0, "Xeon (Dempsey)" },
|
|
|
|
|
|
|
|
/* Pentium Ds */
|
|
/* 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 */
|
|
/* 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 */
|
|
/* Intel Core microarchitecture - P6-based */
|
|
@@ -220,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, MOBILE_PENTIUM_M , 0, "Pentium M (Dothan)" },
|
|
|
{ 6, 13, -1, -1, -1, 1, -1, -1, CELERON , 0, "Celeron M" },
|
|
{ 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_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_SILVERTHORNE , 0, "Atom (Silverthorne)" },
|
|
|
{ 6, 12, -1, -1, -1, -1, -1, -1, ATOM_CEDARVIEW , 0, "Atom (Cedarview)" },
|
|
{ 6, 12, -1, -1, -1, -1, -1, -1, ATOM_CEDARVIEW , 0, "Atom (Cedarview)" },
|
|
@@ -266,6 +215,7 @@ 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, 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, 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, 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, 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, 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, 2048, -1, QUAD_CORE , 0, "Yorkfield (Core 2 Quad) 2M"},
|
|
@@ -301,6 +251,7 @@ const struct match_entry_t cpudb_intel[] = {
|
|
|
{ 6, 12, -1, -1, 44, 4, -1, 12288, CORE_I7 , 0, "Gulftown (Core i7)" },
|
|
{ 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_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, 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, 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_I5 , 0, "Arrandale (Core i5)" },
|
|
|
{ 6, 5, -1, -1, 37, 2, -1, 3072, CORE_I3 , 0, "Arrandale (Core i3)" },
|
|
{ 6, 5, -1, -1, 37, 2, -1, 3072, CORE_I3 , 0, "Arrandale (Core i3)" },
|
|
@@ -351,11 +302,16 @@ const struct match_entry_t cpudb_intel[] = {
|
|
|
{ 6, 13, -1, -1, 61, 2, -1, -1, PENTIUM , 0, "Broadwell-U (Pentium)" },
|
|
{ 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, CELERON , 0, "Broadwell-U (Celeron)" },
|
|
|
{ 6, 13, -1, -1, 61, 2, -1, -1, NA , 0, "Broadwell-U (Core M)" },
|
|
{ 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): */
|
|
/* Skylake CPUs (14nm): */
|
|
|
- { 6, 14, -1, -1, 94, 4, -1, -1, CORE_SKYLAKE7 , 0, "Skylake (Core i7)" },
|
|
|
|
|
- { 6, 14, -1, -1, 94, 4, -1, -1, CORE_SKYLAKE5 , 0, "Skylake (Core i5)" },
|
|
|
|
|
- { 6, 14, -1, -1, 94, 4, -1, -1, CORE_SKYLAKE3 , 0, "Skylake (Core i3)" },
|
|
|
|
|
|
|
+ { 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)" },
|
|
{ 6, 14, -1, -1, 94, 4, -1, -1, PENTIUM , 0, "Skylake (Pentium)" },
|
|
|
|
|
|
|
|
/* Itaniums */
|
|
/* Itaniums */
|
|
@@ -377,7 +333,6 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
|
|
|
{ 31, CPU_FEATURE_PBE },
|
|
{ 31, CPU_FEATURE_PBE },
|
|
|
};
|
|
};
|
|
|
const struct feature_map_t matchtable_ecx1[] = {
|
|
const struct feature_map_t matchtable_ecx1[] = {
|
|
|
- { 1, CPU_FEATURE_PCLMUL },
|
|
|
|
|
{ 2, CPU_FEATURE_DTS64 },
|
|
{ 2, CPU_FEATURE_DTS64 },
|
|
|
{ 4, CPU_FEATURE_DS_CPL },
|
|
{ 4, CPU_FEATURE_DS_CPL },
|
|
|
{ 5, CPU_FEATURE_VMX },
|
|
{ 5, CPU_FEATURE_VMX },
|
|
@@ -388,16 +343,26 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
|
|
|
{ 14, CPU_FEATURE_XTPR },
|
|
{ 14, CPU_FEATURE_XTPR },
|
|
|
{ 15, CPU_FEATURE_PDCM },
|
|
{ 15, CPU_FEATURE_PDCM },
|
|
|
{ 18, CPU_FEATURE_DCA },
|
|
{ 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 },
|
|
|
|
|
- { 30, CPU_FEATURE_RDRAND },
|
|
|
|
|
|
|
+ { 21, CPU_FEATURE_X2APIC },
|
|
|
};
|
|
};
|
|
|
const struct feature_map_t matchtable_edx81[] = {
|
|
const struct feature_map_t matchtable_edx81[] = {
|
|
|
{ 20, CPU_FEATURE_XD },
|
|
{ 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) {
|
|
if (raw->basic_cpuid[0][0] >= 1) {
|
|
|
match_features(matchtable_edx1, COUNT_OF(matchtable_edx1), raw->basic_cpuid[1][3], data);
|
|
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);
|
|
match_features(matchtable_ecx1, COUNT_OF(matchtable_ecx1), raw->basic_cpuid[1][2], data);
|
|
@@ -405,13 +370,18 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
|
|
|
if (raw->ext_cpuid[0][0] >= 1) {
|
|
if (raw->ext_cpuid[0][0] >= 1) {
|
|
|
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
|
|
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 {
|
|
enum _cache_type_t {
|
|
|
L1I,
|
|
L1I,
|
|
|
L1D,
|
|
L1D,
|
|
|
L2,
|
|
L2,
|
|
|
- L3
|
|
|
|
|
|
|
+ L3,
|
|
|
|
|
+ L4
|
|
|
};
|
|
};
|
|
|
typedef enum _cache_type_t cache_type_t;
|
|
typedef enum _cache_type_t cache_type_t;
|
|
|
|
|
|
|
@@ -436,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_cache = size;
|
|
|
data->l3_assoc = assoc;
|
|
data->l3_assoc = assoc;
|
|
|
data->l3_cacheline = linesize;
|
|
data->l3_cacheline = linesize;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case L4:
|
|
|
|
|
+ data->l4_cache = size;
|
|
|
|
|
+ data->l4_assoc = assoc;
|
|
|
|
|
+ data->l4_cacheline = linesize;
|
|
|
|
|
+ break;
|
|
|
default:
|
|
default:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
@@ -556,6 +532,8 @@ static void decode_intel_deterministic_cache_info(struct cpu_raw_data_t* raw,
|
|
|
type = L2;
|
|
type = L2;
|
|
|
else if (level == 3 && typenumber == 3)
|
|
else if (level == 3 && typenumber == 3)
|
|
|
type = L3;
|
|
type = L3;
|
|
|
|
|
+ else if (level == 4 && typenumber == 3)
|
|
|
|
|
+ type = L4;
|
|
|
else {
|
|
else {
|
|
|
warnf("deterministic_cache: unknown level/typenumber combo (%d/%d), cannot\n", level, typenumber);
|
|
warnf("deterministic_cache: unknown level/typenumber combo (%d/%d), cannot\n", level, typenumber);
|
|
|
warnf("deterministic_cache: recognize cache type\n");
|
|
warnf("deterministic_cache: recognize cache type\n");
|
|
@@ -588,8 +566,12 @@ static int decode_intel_extended_topology(struct cpu_raw_data_t* raw,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if (num_smt == -1 || num_core == -1) return 0;
|
|
if (num_smt == -1 || num_core == -1) return 0;
|
|
|
- data->num_cores = num_core / num_smt;
|
|
|
|
|
data->num_logical_cpus = num_core;
|
|
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;
|
|
return 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -614,7 +596,9 @@ static void decode_intel_number_of_cores(struct cpu_raw_data_t* raw,
|
|
|
data->num_logical_cpus = logical_cpus;
|
|
data->num_logical_cpus = logical_cpus;
|
|
|
} else {
|
|
} else {
|
|
|
data->num_cores = 1;
|
|
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 {
|
|
} else {
|
|
|
data->num_cores = data->num_logical_cpus = 1;
|
|
data->num_cores = data->num_logical_cpus = 1;
|
|
@@ -623,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)
|
|
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;
|
|
int i, need_matchtable = 1, core_ix_base = 0;
|
|
|
const char* bs = data->brand_str;
|
|
const char* bs = data->brand_str;
|
|
|
const char* s;
|
|
const char* s;
|
|
@@ -634,15 +618,16 @@ static intel_code_t get_brand_code(struct cpu_id_t* data)
|
|
|
{ CELERON, "Celeron" },
|
|
{ CELERON, "Celeron" },
|
|
|
{ MOBILE_PENTIUM_M, "Pentium(R) M" },
|
|
{ MOBILE_PENTIUM_M, "Pentium(R) M" },
|
|
|
{ CORE_SOLO, "Pentium(R) Dual CPU" },
|
|
{ CORE_SOLO, "Pentium(R) Dual CPU" },
|
|
|
|
|
+ { CORE_SOLO, "Pentium(R) Dual-Core" },
|
|
|
{ PENTIUM_D, "Pentium(R) D" },
|
|
{ PENTIUM_D, "Pentium(R) D" },
|
|
|
{ PENTIUM, "Pentium" },
|
|
{ PENTIUM, "Pentium" },
|
|
|
{ CORE_SOLO, "Genuine Intel(R) CPU" },
|
|
{ CORE_SOLO, "Genuine Intel(R) CPU" },
|
|
|
{ CORE_SOLO, "Intel(R) Core(TM)" },
|
|
{ CORE_SOLO, "Intel(R) Core(TM)" },
|
|
|
{ ATOM_DIAMONDVILLE, "Atom(TM) CPU [N ][23]## " },
|
|
{ ATOM_DIAMONDVILLE, "Atom(TM) CPU [N ][23]## " },
|
|
|
{ ATOM_SILVERTHORNE, "Atom(TM) CPU Z" },
|
|
{ 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")) {
|
|
if (strstr(bs, "Mobile")) {
|
|
@@ -664,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 it has FMA, then it is at least Haswell */
|
|
|
if (data->flags[CPU_FEATURE_FMA3])
|
|
if (data->flags[CPU_FEATURE_FMA3])
|
|
|
core_ix_base = CORE_HASWELL3;
|
|
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]) {
|
|
switch (bs[i + 9]) {
|
|
|
case '3': code = core_ix_base + 0; break;
|
|
case '3': code = core_ix_base + 0; break;
|
|
@@ -798,8 +786,75 @@ static intel_model_t get_model_code(struct cpu_id_t* data)
|
|
|
#undef HAVE
|
|
#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);
|
|
load_intel_features(raw, data);
|
|
|
if (raw->basic_cpuid[0][0] >= 4) {
|
|
if (raw->basic_cpuid[0][0] >= 4) {
|
|
|
/* Deterministic way is preferred, being more generic */
|
|
/* Deterministic way is preferred, being more generic */
|
|
@@ -808,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_oldstyle_cache_info(raw, data);
|
|
|
}
|
|
}
|
|
|
decode_intel_number_of_cores(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;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|