Linux: Enable gcc AES-NI built-in functions and adapt Hyper-V AES detection code to gcc.

This commit is contained in:
Mounir IDRASSI 2016-08-07 23:45:34 +02:00
parent fe31cf5b83
commit 3fb2eedab8
No known key found for this signature in database
GPG Key ID: DD0C382D5FCFB8FC
2 changed files with 57 additions and 13 deletions

View File

@ -38,6 +38,12 @@ static void SigIllHandlerCPUID(int p)
longjmp(s_jmpNoCPUID, 1);
}
static jmp_buf s_jmpNoAESNI;
static void SigIllHandlerAESNI(int p)
{
longjmp(s_jmpNoAESNI, 1);
}
#if CRYPTOPP_BOOL_X64 == 0
static jmp_buf s_jmpNoSSE2;
static void SigIllHandlerSSE2(int p)
@ -192,6 +198,47 @@ VC_INLINE int IsAMD(const uint32 output[4])
(output[3] /*EDX*/ == 0x444D4163);
}
#if (defined(__AES__) && defined(__PCLMUL__)) || defined(__INTEL_COMPILER) || CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE
static int TryAESNI ()
{
volatile int result = 0;
#ifdef _MSC_VER
__try
#else
SigHandler oldHandler = signal(SIGILL, SigIllHandlerAESNI);
if (oldHandler == SIG_ERR)
return 0;
if (setjmp(s_jmpNoAESNI))
result = 0;
else
#endif
{
__m128i block, subkey, ciphered;
// perform AES round.
block = _mm_setr_epi32(0x11223344,0x55667788,0x99AABBCC,0xDDEEFF00);
subkey = _mm_setr_epi32(0xA5A5A5A5,0xA5A5A5A5,0x5A5A5A5A,0x5A5A5A5A);
ciphered = _mm_aesenc_si128(block, subkey);
#ifdef _MSC_VER
if (ciphered.m128i_u64[0] == LL(0x2f4654b9485061fa) && ciphered.m128i_u64[1] == LL(0xc8b51f1fe1256f99))
#else
if (((uint64_t*)(&ciphered))[0] == LL(0x2f4654b9485061fa) && ((uint64_t*)(&ciphered))[1] == LL(0xc8b51f1fe1256f99))
#endif
result = 1;
}
#ifdef _MSC_VER
__except (EXCEPTION_EXECUTE_HANDLER)
{
// ignore error if AES-NI not supported
}
#else
signal(SIGILL, oldHandler);
#endif
return result;
}
static int Detect_MS_HyperV_AES ()
{
int hasAesNI = 0;
@ -211,19 +258,8 @@ static int Detect_MS_HyperV_AES ()
if (NT_SUCCESS (KeSaveFloatingPointState (&floatingPointState)))
{
#endif
__try
{
__m128i block, subkey, ciphered;
// perform AES round.
block = _mm_setr_epi32(0x11223344,0x55667788,0x99AABBCC,0xDDEEFF00);
subkey = _mm_setr_epi32(0xA5A5A5A5,0xA5A5A5A5,0x5A5A5A5A,0x5A5A5A5A);
ciphered = _mm_aesenc_si128(block, subkey);
hasAesNI = (ciphered.m128i_u64[0] == LL(0x2f4654b9485061fa) && ciphered.m128i_u64[1] == LL(0xc8b51f1fe1256f99));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// ignore error if AES-NI not supported
}
hasAesNI = TryAESNI ();
#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
KeRestoreFloatingPointState (&floatingPointState);
}
@ -233,6 +269,8 @@ static int Detect_MS_HyperV_AES ()
return hasAesNI;
}
#endif
void DetectX86Features()
{
uint32 cpuid[4], cpuid1[4];

View File

@ -160,6 +160,12 @@ ifeq "$(shell uname -s)" "Linux"
PLATFORM := Linux
C_CXX_FLAGS += -DTC_UNIX -DTC_LINUX
GCC_GTEQ_440 := $(shell expr `gcc -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/'` \>= 40400)
ifeq "$(GCC_GTEQ_440)" "1"
CFLAGS += -maes
CXXFLAGS += -maes
endif
ifeq "$(TC_BUILD_CONFIG)" "Release"
C_CXX_FLAGS += -fdata-sections -ffunction-sections