mirror of
https://github.com/anrieff/libcpuid
synced 2024-12-16 16:35:45 +00:00
Related to issue #67: Information about the availability of SGX
Initial commit adding support for detection of SGX. Not tested yet. Increment version number due to binary incompatibility of the sizes of cpu_raw_data_t and cpu_id_t.
This commit is contained in:
parent
94843e8fd5
commit
4cf8cfa862
16 changed files with 340 additions and 20 deletions
|
@ -40,3 +40,9 @@ Version 0.3.0 (2016-07-09):
|
||||||
of L4 cache.
|
of L4 cache.
|
||||||
* MSR functions supported on FreeBSD.
|
* MSR functions supported on FreeBSD.
|
||||||
* INFO_VOLTAGE request supported by cpu_msrinfo().
|
* INFO_VOLTAGE request supported by cpu_msrinfo().
|
||||||
|
|
||||||
|
Version 0.4.0 (2016-09-30):
|
||||||
|
* A backwards-incompatible change, since the sizeof cpu_raw_data_t and
|
||||||
|
cpu_id_t are now different.
|
||||||
|
* Better detection of AMD clock multiplier with msrinfo.
|
||||||
|
* Support for Intel SGX detection
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
AC_INIT([libcpuid CPU Identification library], [0.3.0], [libcpuid-devel@lists.sourceforge.net], [libcpuid])
|
AC_INIT([libcpuid CPU Identification library], [0.4.0], [libcpuid-devel@lists.sourceforge.net], [libcpuid])
|
||||||
AC_CONFIG_SRCDIR([libcpuid/libcpuid.h])
|
AC_CONFIG_SRCDIR([libcpuid/libcpuid.h])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
@ -21,7 +21,8 @@ dnl 12:1:0 Version 0.2.0: two more fields to cpu_id_t
|
||||||
dnl 12:1:1 Version 0.2.1: more processors support
|
dnl 12:1:1 Version 0.2.1: more processors support
|
||||||
dnl 12:1:2 Version 0.2.2: more processors support, *BSD/Solaris support, updates to MSR stuff
|
dnl 12:1:2 Version 0.2.2: more processors support, *BSD/Solaris support, updates to MSR stuff
|
||||||
dnl 13:0:0 Version 0.3.0: increment max Intel leaf 04 entries to 8
|
dnl 13:0:0 Version 0.3.0: increment max Intel leaf 04 entries to 8
|
||||||
LIBCPUID_CURRENT=13
|
dnl 14:0:0 Version 0.4.0: add one more field per cpu_raw_data_t and cpu_id_t
|
||||||
|
LIBCPUID_CURRENT=14
|
||||||
LIBCPUID_AGE=0
|
LIBCPUID_AGE=0
|
||||||
LIBCPUID_REVISION=0
|
LIBCPUID_REVISION=0
|
||||||
AC_SUBST([LIBCPUID_AGE])
|
AC_SUBST([LIBCPUID_AGE])
|
||||||
|
|
|
@ -90,6 +90,7 @@ typedef enum {
|
||||||
NEED_CLOCK_IC,
|
NEED_CLOCK_IC,
|
||||||
NEED_RDMSR,
|
NEED_RDMSR,
|
||||||
NEED_SSE_UNIT_SIZE,
|
NEED_SSE_UNIT_SIZE,
|
||||||
|
NEED_SGX,
|
||||||
} output_data_switch;
|
} output_data_switch;
|
||||||
|
|
||||||
int need_input = 0,
|
int need_input = 0,
|
||||||
|
@ -100,7 +101,8 @@ int need_input = 0,
|
||||||
need_timed_clockreport = 0,
|
need_timed_clockreport = 0,
|
||||||
verbose_level = 0,
|
verbose_level = 0,
|
||||||
need_version = 0,
|
need_version = 0,
|
||||||
need_cpulist = 0;
|
need_cpulist = 0,
|
||||||
|
need_sgx = 0;
|
||||||
|
|
||||||
#define MAX_REQUESTS 32
|
#define MAX_REQUESTS 32
|
||||||
int num_requests = 0;
|
int num_requests = 0;
|
||||||
|
@ -145,6 +147,7 @@ matchtable[] = {
|
||||||
{ NEED_CLOCK_IC , "--clock-ic" , 1},
|
{ NEED_CLOCK_IC , "--clock-ic" , 1},
|
||||||
{ NEED_RDMSR , "--rdmsr" , 0},
|
{ NEED_RDMSR , "--rdmsr" , 0},
|
||||||
{ NEED_SSE_UNIT_SIZE, "--sse-size" , 1},
|
{ NEED_SSE_UNIT_SIZE, "--sse-size" , 1},
|
||||||
|
{ NEED_SGX , "--sgx" , 1},
|
||||||
};
|
};
|
||||||
|
|
||||||
const int sz_match = (sizeof(matchtable) / sizeof(matchtable[0]));
|
const int sz_match = (sizeof(matchtable) / sizeof(matchtable[0]));
|
||||||
|
@ -458,6 +461,25 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw,
|
||||||
data->detection_hints[CPU_HINT_SSE_SIZE_AUTH] ? "authoritative" : "non-authoritative");
|
data->detection_hints[CPU_HINT_SSE_SIZE_AUTH] ? "authoritative" : "non-authoritative");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NEED_SGX:
|
||||||
|
{
|
||||||
|
fprintf(fout, "SGX: %d (%s)\n", data->sgx.present, data->sgx.present ? "present" : "absent");
|
||||||
|
if (data->sgx.present) {
|
||||||
|
fprintf(fout, "SGX max enclave size (32-bit): 2^%d\n", data->sgx.max_enclave_32bit);
|
||||||
|
fprintf(fout, "SGX max enclave size (64-bit): 2^%d\n", data->sgx.max_enclave_64bit);
|
||||||
|
fprintf(fout, "SGX1 extensions : %d (%s)\n", data->sgx.flags[INTEL_SGX1], data->sgx.flags[INTEL_SGX1] ? "present" : "absent");
|
||||||
|
fprintf(fout, "SGX2 extensions : %d (%s)\n", data->sgx.flags[INTEL_SGX2], data->sgx.flags[INTEL_SGX2] ? "present" : "absent");
|
||||||
|
fprintf(fout, "SGX MISCSELECT : %08x\n", data->sgx.misc_select);
|
||||||
|
fprintf(fout, "SGX SECS.ATTRIBUTES mask : %016llx\n", data->sgx.secs_attributes);
|
||||||
|
fprintf(fout, "SGX SECS.XSAVE feature mask : %016llx\n", data->sgx.secs_xfrm);
|
||||||
|
fprintf(fout, "SGX EPC sections count : %d\n", data->sgx.num_epc_sections);
|
||||||
|
for (i = 0; i < data->sgx.num_epc_sections; i++) {
|
||||||
|
struct cpu_epc_t epc = cpuid_get_epc(i, raw);
|
||||||
|
fprintf(fout, "SGX EPC section #%-8d: start = %llx, size = %llu\n", epc.start_addr, epc.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
fprintf(fout, "How did you get here?!?\n");
|
fprintf(fout, "How did you get here?!?\n");
|
||||||
break;
|
break;
|
||||||
|
|
9
debian/changelog
vendored
9
debian/changelog
vendored
|
@ -1,3 +1,12 @@
|
||||||
|
libcpuid (0.4.0) unstable; urgency=log
|
||||||
|
|
||||||
|
* 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).
|
||||||
|
|
||||||
|
-- Georgiev, Veselin <anrieff@gmail.com> Thu, 30 Sep 2016 22:39:37 +0300
|
||||||
|
|
||||||
libcpuid (0.3.0) unstable; urgency=low
|
libcpuid (0.3.0) unstable; urgency=low
|
||||||
|
|
||||||
* A backwards-incompatible change, since the sizeof cpu_raw_data_t and
|
* A backwards-incompatible change, since the sizeof cpu_raw_data_t and
|
||||||
|
|
|
@ -5,7 +5,7 @@ all: libcpuid.lib
|
||||||
ASM = ml64 /nologo
|
ASM = ml64 /nologo
|
||||||
CC = cl.exe /nologo /TC
|
CC = cl.exe /nologo /TC
|
||||||
OPTFLAGS = /MT
|
OPTFLAGS = /MT
|
||||||
DEFINES = /D "VERSION=\"0.3.0\""
|
DEFINES = /D "VERSION=\"0.4.0\""
|
||||||
OBJECTS = masm-x64.obj asm-bits.obj cpuid_main.obj libcpuid_util.obj recog_amd.obj recog_intel.obj rdtsc.obj
|
OBJECTS = masm-x64.obj asm-bits.obj cpuid_main.obj libcpuid_util.obj recog_amd.obj recog_intel.obj rdtsc.obj
|
||||||
|
|
||||||
libcpuid.lib: $(OBJECTS)
|
libcpuid.lib: $(OBJECTS)
|
||||||
|
|
|
@ -12,7 +12,7 @@ all: libcpuid.lib
|
||||||
|
|
||||||
CC = cl.exe /nologo /TC
|
CC = cl.exe /nologo /TC
|
||||||
OPTFLAGS = /MT
|
OPTFLAGS = /MT
|
||||||
DEFINES = /D "VERSION=\"0.3.0\""
|
DEFINES = /D "VERSION=\"0.4.0\""
|
||||||
OBJECTS = asm-bits.obj cpuid_main.obj libcpuid_util.obj recog_amd.obj recog_intel.obj rdtsc.obj
|
OBJECTS = asm-bits.obj cpuid_main.obj libcpuid_util.obj recog_amd.obj recog_intel.obj rdtsc.obj
|
||||||
|
|
||||||
libcpuid.lib: $(OBJECTS)
|
libcpuid.lib: $(OBJECTS)
|
||||||
|
|
|
@ -6,6 +6,52 @@ if len(sys.argv) != 2:
|
||||||
print "Usage: check-consistency <path>"
|
print "Usage: check-consistency <path>"
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def getEnumElements(enumName):
|
||||||
|
f = open("%s/libcpuid.h" % sys.argv[1], "r")
|
||||||
|
l = []
|
||||||
|
on = False
|
||||||
|
rexp = re.compile(r'^\s*([A-Z0-9_]+)(\s*=\s*[A-Z0-9_]+)?\s*,.*$')
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith("typedef enum {"):
|
||||||
|
l = []
|
||||||
|
on = True
|
||||||
|
if on and rexp.match(line):
|
||||||
|
l.append(rexp.findall(line)[0][0])
|
||||||
|
if on and line.startswith("} "):
|
||||||
|
on = False
|
||||||
|
if line.find(enumName) != -1:
|
||||||
|
return l
|
||||||
|
f.close()
|
||||||
|
return []
|
||||||
|
|
||||||
|
def getConstant(constantName):
|
||||||
|
f = open("%s/libcpuid_constants.h" % sys.argv[1], "r")
|
||||||
|
value = 0
|
||||||
|
for line in f:
|
||||||
|
items = line.strip().split()
|
||||||
|
if len(items) >= 3 and items[0] == "#define" and items[1] == constantName:
|
||||||
|
value = int(items[2])
|
||||||
|
f.close()
|
||||||
|
return value
|
||||||
|
|
||||||
|
def checkEnumSize(enumName, constantName):
|
||||||
|
print "Checking enum `%s':" % enumName,
|
||||||
|
count = len(getEnumElements(enumName)) - 1
|
||||||
|
themax = getConstant(constantName)
|
||||||
|
print "%d elements; max size (%s=%d)..." % (count, constantName, themax),
|
||||||
|
if count > themax:
|
||||||
|
print "FAILED"
|
||||||
|
global firstError
|
||||||
|
firstError = False
|
||||||
|
else:
|
||||||
|
print "OK"
|
||||||
|
|
||||||
|
checkEnumSize("cpu_feature_t", "CPU_FLAGS_MAX")
|
||||||
|
checkEnumSize("cpu_hint_t", "CPU_HINTS_MAX")
|
||||||
|
checkEnumSize("cpu_sgx_feature_t", "SGX_FLAGS_MAX")
|
||||||
|
|
||||||
rexp = re.compile('.*{ CPU_FEATURE_([^,]+), "([^"]+)".*}.*')
|
rexp = re.compile('.*{ CPU_FEATURE_([^,]+), "([^"]+)".*}.*')
|
||||||
print "Finding features:"
|
print "Finding features:"
|
||||||
for fn in glob.glob("%s/*.c" % sys.argv[1]):
|
for fn in glob.glob("%s/*.c" % sys.argv[1]):
|
||||||
|
|
|
@ -386,6 +386,18 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data)
|
||||||
data->intel_fn11[i][2] = i;
|
data->intel_fn11[i][2] = i;
|
||||||
cpu_exec_cpuid_ext(data->intel_fn11[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);
|
return set_error(ERR_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,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,
|
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][0], data->intel_fn11[i][1],
|
||||||
data->intel_fn11[i][2], data->intel_fn11[i][3]);
|
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, ""))
|
if (strcmp(filename, ""))
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
@ -462,9 +482,11 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
|
||||||
}
|
}
|
||||||
syntax = 1;
|
syntax = 1;
|
||||||
syntax = syntax && parse_token("basic_cpuid", token, value, data->basic_cpuid, MAX_CPUID_LEVEL, &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("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_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_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) {
|
if (!syntax) {
|
||||||
warnf("Error: %s:%d: Syntax error\n", filename, cur_line);
|
warnf("Error: %s:%d: Syntax error\n", filename, cur_line);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
@ -622,6 +644,7 @@ const char* cpu_feature_str(cpu_feature_t feature)
|
||||||
{ CPU_FEATURE_SHA_NI, "sha_ni" },
|
{ CPU_FEATURE_SHA_NI, "sha_ni" },
|
||||||
{ CPU_FEATURE_AVX512BW, "avx512bw" },
|
{ CPU_FEATURE_AVX512BW, "avx512bw" },
|
||||||
{ CPU_FEATURE_AVX512VL, "avx512vl" },
|
{ CPU_FEATURE_AVX512VL, "avx512vl" },
|
||||||
|
{ CPU_FEATURE_SGX, "sgx" },
|
||||||
};
|
};
|
||||||
unsigned i, n = COUNT_OF(matchtable);
|
unsigned i, n = COUNT_OF(matchtable);
|
||||||
if (n != NUM_CPU_FEATURES) {
|
if (n != NUM_CPU_FEATURES) {
|
||||||
|
|
|
@ -31,3 +31,4 @@ cpuid_get_total_cpus @27
|
||||||
cpu_msr_driver_open_core @28
|
cpu_msr_driver_open_core @28
|
||||||
cpuid_get_vendor @29
|
cpuid_get_vendor @29
|
||||||
cpu_rdmsr_range @30
|
cpu_rdmsr_range @30
|
||||||
|
cpuid_get_epc @31
|
||||||
|
|
|
@ -41,7 +41,7 @@ RSC=rc.exe
|
||||||
# PROP Intermediate_Dir "Release"
|
# PROP Intermediate_Dir "Release"
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||||
# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D VERSION=\"0.3.0\" /YX /FD /c
|
# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D VERSION=\"0.4.0\" /YX /FD /c
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
BSC32=bscmake.exe
|
BSC32=bscmake.exe
|
||||||
|
@ -64,7 +64,7 @@ LIB32=link.exe -lib
|
||||||
# PROP Intermediate_Dir "Debug"
|
# PROP Intermediate_Dir "Debug"
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D VERSION=\"0.3.0\" /YX /FD /GZ /c
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D VERSION=\"0.4.0\" /YX /FD /GZ /c
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
BSC32=bscmake.exe
|
BSC32=bscmake.exe
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
* \file libcpuid.h
|
* \file libcpuid.h
|
||||||
* \author Veselin Georgiev
|
* \author Veselin Georgiev
|
||||||
* \date Oct 2008
|
* \date Oct 2008
|
||||||
* \version 0.3.0
|
* \version 0.4.0
|
||||||
*
|
*
|
||||||
* Version history:
|
* Version history:
|
||||||
*
|
*
|
||||||
|
@ -53,6 +53,10 @@
|
||||||
* for AMD CPUs. Level 4 cache support for Crystalwell
|
* for AMD CPUs. Level 4 cache support for Crystalwell
|
||||||
* (a backwards-incompatible change since the sizeof
|
* (a backwards-incompatible change since the sizeof
|
||||||
* cpu_raw_data_t is now different).
|
* 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
|
/** @mainpage A simple libcpuid introduction
|
||||||
|
@ -133,6 +137,81 @@ struct cpu_raw_data_t {
|
||||||
enumeration leaf), this stores the result of CPUID with
|
enumeration leaf), this stores the result of CPUID with
|
||||||
eax = 11 and ecx = 0, 1, 2... */
|
eax = 11 and ecx = 0, 1, 2... */
|
||||||
uint32_t intel_fn11[MAX_INTELFN11_LEVEL][4];
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -265,6 +344,9 @@ struct cpu_id_t {
|
||||||
* @see Hints
|
* @see Hints
|
||||||
*/
|
*/
|
||||||
uint8_t detection_hints[CPU_HINTS_MAX];
|
uint8_t detection_hints[CPU_HINTS_MAX];
|
||||||
|
|
||||||
|
/** contains information about SGX features if the processor, if present */
|
||||||
|
struct cpu_sgx_t sgx;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -395,6 +477,7 @@ typedef enum {
|
||||||
CPU_FEATURE_SHA_NI, /*!< SHA-1/SHA-256 instructions */
|
CPU_FEATURE_SHA_NI, /*!< SHA-1/SHA-256 instructions */
|
||||||
CPU_FEATURE_AVX512BW, /*!< AVX-512 Byte/Word granular insns */
|
CPU_FEATURE_AVX512BW, /*!< AVX-512 Byte/Word granular insns */
|
||||||
CPU_FEATURE_AVX512VL, /*!< AVX-512 128/256 vector length extensions */
|
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 */
|
||||||
/* termination: */
|
/* termination: */
|
||||||
NUM_CPU_FEATURES,
|
NUM_CPU_FEATURES,
|
||||||
} cpu_feature_t;
|
} cpu_feature_t;
|
||||||
|
@ -410,6 +493,36 @@ typedef enum {
|
||||||
NUM_CPU_HINTS,
|
NUM_CPU_HINTS,
|
||||||
} cpu_hint_t;
|
} 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
|
* @brief Describes common library error codes
|
||||||
*/
|
*/
|
||||||
|
@ -756,6 +869,32 @@ int cpu_clock_by_ic(int millis, int runs);
|
||||||
*/
|
*/
|
||||||
int cpu_clock(void);
|
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
|
* @brief Returns the libcpuid version
|
||||||
*
|
*
|
||||||
|
|
|
@ -28,3 +28,4 @@ cpuid_get_total_cpus
|
||||||
cpu_msr_driver_open_core
|
cpu_msr_driver_open_core
|
||||||
cpuid_get_vendor
|
cpuid_get_vendor
|
||||||
cpu_rdmsr_range
|
cpu_rdmsr_range
|
||||||
|
cpuid_get_epc
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
#define MAX_EXT_CPUID_LEVEL 32
|
#define MAX_EXT_CPUID_LEVEL 32
|
||||||
#define MAX_INTELFN4_LEVEL 8
|
#define MAX_INTELFN4_LEVEL 8
|
||||||
#define MAX_INTELFN11_LEVEL 4
|
#define MAX_INTELFN11_LEVEL 4
|
||||||
|
#define MAX_INTELFN12H_LEVEL 4
|
||||||
|
#define MAX_INTELFN14H_LEVEL 4
|
||||||
#define CPU_HINTS_MAX 16
|
#define CPU_HINTS_MAX 16
|
||||||
|
#define SGX_FLAGS_MAX 14
|
||||||
|
|
||||||
#endif /* __LIBCPUID_CONSTANTS_H__ */
|
#endif /* __LIBCPUID_CONSTANTS_H__ */
|
||||||
|
|
|
@ -102,7 +102,7 @@
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;VERSION="0.3.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<MinimalRebuild>true</MinimalRebuild>
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
@ -117,7 +117,7 @@
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;VERSION="0.3.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
<PrecompiledHeader>
|
<PrecompiledHeader>
|
||||||
|
@ -130,7 +130,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.3.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<PrecompiledHeader>
|
<PrecompiledHeader>
|
||||||
</PrecompiledHeader>
|
</PrecompiledHeader>
|
||||||
|
@ -142,7 +142,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.3.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<PrecompiledHeader>
|
<PrecompiledHeader>
|
||||||
</PrecompiledHeader>
|
</PrecompiledHeader>
|
||||||
|
@ -157,7 +157,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.3.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<PrecompiledHeader>
|
<PrecompiledHeader>
|
||||||
</PrecompiledHeader>
|
</PrecompiledHeader>
|
||||||
|
@ -169,7 +169,7 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.3.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<PrecompiledHeader>
|
<PrecompiledHeader>
|
||||||
</PrecompiledHeader>
|
</PrecompiledHeader>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="VERSION=\"0.3.0\""
|
PreprocessorDefinitions="VERSION=\"0.4.0\""
|
||||||
MinimalRebuild="TRUE"
|
MinimalRebuild="TRUE"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
CharacterSet="2">
|
CharacterSet="2">
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
PreprocessorDefinitions="VERSION=\"0.3.0\""
|
PreprocessorDefinitions="VERSION=\"0.4.0\""
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
CharacterSet="2">
|
CharacterSet="2">
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
PreprocessorDefinitions="VERSION=\"0.3.0\""
|
PreprocessorDefinitions="VERSION=\"0.4.0\""
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
|
|
|
@ -349,6 +349,7 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
|
||||||
{ 20, CPU_FEATURE_XD },
|
{ 20, CPU_FEATURE_XD },
|
||||||
};
|
};
|
||||||
const struct feature_map_t matchtable_ebx7[] = {
|
const struct feature_map_t matchtable_ebx7[] = {
|
||||||
|
{ 2, CPU_FEATURE_SGX },
|
||||||
{ 4, CPU_FEATURE_HLE },
|
{ 4, CPU_FEATURE_HLE },
|
||||||
{ 11, CPU_FEATURE_RTM },
|
{ 11, CPU_FEATURE_RTM },
|
||||||
{ 16, CPU_FEATURE_AVX512F },
|
{ 16, CPU_FEATURE_AVX512F },
|
||||||
|
@ -783,6 +784,68 @@ static intel_model_t get_model_code(struct cpu_id_t* data)
|
||||||
#undef HAVE
|
#undef HAVE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
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:
|
||||||
|
struct cpu_epc_t retval = {0, 0};
|
||||||
|
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)
|
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_code_t brand_code;
|
||||||
|
@ -815,6 +878,12 @@ int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, stru
|
||||||
|
|
||||||
internal->code.intel = brand_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,
|
internal->score = match_cpu_codename(cpudb_intel, COUNT_OF(cpudb_intel), data,
|
||||||
brand_code, model_code);
|
brand_code, model_code);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue