1
0
Fork 0
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:
Veselin Georgiev 2016-09-30 22:03:57 +03:00
parent 94843e8fd5
commit 4cf8cfa862
16 changed files with 340 additions and 20 deletions

View file

@ -40,3 +40,9 @@ Version 0.3.0 (2016-07-09):
of L4 cache.
* MSR functions supported on FreeBSD.
* 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

View file

@ -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_HEADERS([config.h])
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: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
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_REVISION=0
AC_SUBST([LIBCPUID_AGE])

View file

@ -90,6 +90,7 @@ typedef enum {
NEED_CLOCK_IC,
NEED_RDMSR,
NEED_SSE_UNIT_SIZE,
NEED_SGX,
} output_data_switch;
int need_input = 0,
@ -100,7 +101,8 @@ int need_input = 0,
need_timed_clockreport = 0,
verbose_level = 0,
need_version = 0,
need_cpulist = 0;
need_cpulist = 0,
need_sgx = 0;
#define MAX_REQUESTS 32
int num_requests = 0;
@ -145,6 +147,7 @@ matchtable[] = {
{ NEED_CLOCK_IC , "--clock-ic" , 1},
{ NEED_RDMSR , "--rdmsr" , 0},
{ NEED_SSE_UNIT_SIZE, "--sse-size" , 1},
{ NEED_SGX , "--sgx" , 1},
};
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");
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:
fprintf(fout, "How did you get here?!?\n");
break;

9
debian/changelog vendored
View file

@ -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
* A backwards-incompatible change, since the sizeof cpu_raw_data_t and

View file

@ -5,7 +5,7 @@ all: libcpuid.lib
ASM = ml64 /nologo
CC = cl.exe /nologo /TC
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
libcpuid.lib: $(OBJECTS)

View file

@ -12,7 +12,7 @@ all: libcpuid.lib
CC = cl.exe /nologo /TC
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
libcpuid.lib: $(OBJECTS)

View file

@ -6,6 +6,52 @@ if len(sys.argv) != 2:
print "Usage: check-consistency <path>"
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_([^,]+), "([^"]+)".*}.*')
print "Finding features:"
for fn in glob.glob("%s/*.c" % sys.argv[1]):

View file

@ -386,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);
}
@ -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,
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);
@ -465,6 +485,8 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
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);
@ -622,6 +644,7 @@ const char* cpu_feature_str(cpu_feature_t feature)
{ CPU_FEATURE_SHA_NI, "sha_ni" },
{ CPU_FEATURE_AVX512BW, "avx512bw" },
{ CPU_FEATURE_AVX512VL, "avx512vl" },
{ CPU_FEATURE_SGX, "sgx" },
};
unsigned i, n = COUNT_OF(matchtable);
if (n != NUM_CPU_FEATURES) {

View file

@ -31,3 +31,4 @@ cpuid_get_total_cpus @27
cpu_msr_driver_open_core @28
cpuid_get_vendor @29
cpu_rdmsr_range @30
cpuid_get_epc @31

View file

@ -41,7 +41,7 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# 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 RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@ -64,7 +64,7 @@ LIB32=link.exe -lib
# PROP Intermediate_Dir "Debug"
# 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 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 RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe

View file

@ -29,7 +29,7 @@
* \file libcpuid.h
* \author Veselin Georgiev
* \date Oct 2008
* \version 0.3.0
* \version 0.4.0
*
* Version history:
*
@ -53,6 +53,10 @@
* 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
@ -133,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;
};
/**
@ -265,6 +344,9 @@ struct cpu_id_t {
* @see Hints
*/
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_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 */
/* termination: */
NUM_CPU_FEATURES,
} cpu_feature_t;
@ -410,6 +493,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
*/
@ -756,6 +869,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
*

View file

@ -28,3 +28,4 @@ cpuid_get_total_cpus
cpu_msr_driver_open_core
cpuid_get_vendor
cpu_rdmsr_range
cpuid_get_epc

View file

@ -39,6 +39,9 @@
#define MAX_EXT_CPUID_LEVEL 32
#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__ */

View file

@ -102,7 +102,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<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>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -117,7 +117,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<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>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
@ -130,7 +130,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.3.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
@ -142,7 +142,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.3.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
@ -157,7 +157,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.3.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
@ -169,7 +169,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseDLL|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.3.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;VERSION="0.4.0";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>

View file

@ -19,7 +19,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="VERSION=\&quot;0.3.0\&quot;"
PreprocessorDefinitions="VERSION=\&quot;0.4.0\&quot;"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@ -60,7 +60,7 @@
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="VERSION=\&quot;0.3.0\&quot;"
PreprocessorDefinitions="VERSION=\&quot;0.4.0\&quot;"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
@ -99,7 +99,7 @@
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="VERSION=\&quot;0.3.0\&quot;"
PreprocessorDefinitions="VERSION=\&quot;0.4.0\&quot;"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"

View file

@ -349,6 +349,7 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
{ 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 },
@ -783,6 +784,68 @@ static intel_model_t get_model_code(struct cpu_id_t* data)
#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)
{
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;
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;