aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcryptobox/cryptobox.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-10-15 14:46:43 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-10-15 14:46:43 +0100
commitc49da7d73967e4725a013b5554627ea417adae08 (patch)
treee8e0f130f40b14f93d39e2cab6a3cdda668d2f78 /src/libcryptobox/cryptobox.c
parentc8cfd79d46bc857ef6a09fffa8a9de3c32729020 (diff)
downloadrspamd-c49da7d73967e4725a013b5554627ea417adae08.tar.gz
rspamd-c49da7d73967e4725a013b5554627ea417adae08.zip
Explicitly test CPU instructions even after CPUID call
Diffstat (limited to 'src/libcryptobox/cryptobox.c')
-rw-r--r--src/libcryptobox/cryptobox.c87
1 files changed, 80 insertions, 7 deletions
diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c
index 0923905d7..2ecc707a7 100644
--- a/src/libcryptobox/cryptobox.c
+++ b/src/libcryptobox/cryptobox.c
@@ -40,6 +40,8 @@
#include <cpuid.h>
#endif
+#include <signal.h>
+
unsigned long cpu_config = 0;
static const guchar n0[16] = {0};
@@ -89,6 +91,64 @@ rspamd_cryptobox_cpuid (gint cpu[4], gint info)
#endif
}
+static sig_atomic_t ok = 0;
+
+static void
+rspamd_cryptobox_ill_handler (int signo)
+{
+ ok = 0;
+}
+
+static gboolean
+rspamd_cryptobox_test_instr (gint instr)
+{
+ void (*old_handler) (int);
+
+#if defined(__GNUC__)
+ ok = 1;
+ old_handler = signal (SIGILL, rspamd_cryptobox_ill_handler);
+
+ switch (instr) {
+#ifdef HAVE_SSE2
+ case CPUID_SSE2:
+ __asm__ volatile ("pmuludq %xmm0, %xmm0");
+ break;
+#endif
+#ifdef HAVE_SSE3
+ case CPUID_SSE3:
+ __asm__ volatile ("movshdup %xmm0, %xmm0");
+ break;
+#endif
+#ifdef HAVE_SSSE3
+ case CPUID_SSSE3:
+ __asm__ volatile ("pshufb %xmm0, %xmm0");
+ break;
+#endif
+#ifdef HAVE_SSE41
+ case CPUID_SSE41:
+ __asm__ volatile ("pcmpeqq %xmm0, %xmm0");
+ break;
+#endif
+#ifdef HAVE_AVX
+ case CPUID_AVX:
+ __asm__ volatile ("vpaddq %xmm0, %xmm0, %xmm0");
+ break;
+#endif
+#ifdef HAVE_AVX2
+ case CPUID_AVX2:
+ __asm__ volatile ("vpaddq %ymm0, %ymm0, %ymm0");\
+ break;
+#endif
+ default:
+ break;
+ }
+
+ signal (SIGILL, old_handler);
+#endif
+
+ return ok == 1;
+}
+
void
rspamd_cryptobox_init (void)
{
@@ -102,25 +162,38 @@ rspamd_cryptobox_init (void)
/* Check OSXSAVE bit first of all */
if ((cpu[2] & ((gint)1 << 9))) {
if ((cpu[3] & ((gint)1 << 26))) {
- cpu_config |= CPUID_SSE2;
+ if (rspamd_cryptobox_test_instr (CPUID_SSE2)) {
+ cpu_config |= CPUID_SSE2;
+ }
}
if ((cpu[2] & ((gint)1 << 28))) {
- cpu_config |= CPUID_AVX;
+ if (rspamd_cryptobox_test_instr (CPUID_AVX)) {
+ cpu_config |= CPUID_AVX;
+ }
}
if ((cpu[2] & ((gint)1 << 0))) {
- cpu_config |= CPUID_SSE3;
+ if (rspamd_cryptobox_test_instr (CPUID_SSE3)) {
+ cpu_config |= CPUID_SSE3;
+ }
}
if ((cpu[2] & ((gint)1 << 9))) {
- cpu_config |= CPUID_SSSE3;
+ if (rspamd_cryptobox_test_instr (CPUID_SSSE3)) {
+ cpu_config |= CPUID_SSSE3;
+ }
}
if ((cpu[2] & ((gint)1 << 19))) {
- cpu_config |= CPUID_SSE41;
+ if (rspamd_cryptobox_test_instr (CPUID_SSE41)) {
+ cpu_config |= CPUID_SSE41;
+ }
}
if (nid > 7) {
rspamd_cryptobox_cpuid (cpu, 7);
- if ((cpu[1] & ((gint)1 << 5))) {
- cpu_config |= CPUID_AVX2;
+
+ if ((cpu[1] & ((gint) 1 << 5))) {
+ if (rspamd_cryptobox_test_instr (CPUID_AVX2)) {
+ cpu_config |= CPUID_AVX2;
+ }
}
}
}