aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-07-20 21:21:03 -0400
committerAndreas Schwab <schwab@redhat.com>2011-07-25 10:04:42 +0200
commit722bff7a4ccceeded69ac8c412ff5ee5859964e7 (patch)
tree30cdca823f4c90ec364a8905a6f57faf0c4a57f3
parent63072fc6170f06657800a536c084db5d6e45e80f (diff)
downloadglibc-722bff7a4ccceeded69ac8c412ff5ee5859964e7.tar
glibc-722bff7a4ccceeded69ac8c412ff5ee5859964e7.tar.gz
glibc-722bff7a4ccceeded69ac8c412ff5ee5859964e7.tar.bz2
glibc-722bff7a4ccceeded69ac8c412ff5ee5859964e7.zip
Fix check for AVX enablement
The AVX bit is set if the CPU supports AVX. But this doesn't mean the kernel does. Add checks according to Intel's documentation. (cherry picked from commit 5644ef5461b5d3ff266206d8ee70d4b575ea6658)
-rw-r--r--ChangeLog9
-rw-r--r--elf/tst-audit4.c22
-rw-r--r--elf/tst-audit6.c22
-rw-r--r--sysdeps/x86_64/dl-trampoline.S17
4 files changed, 57 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 515f22c046..9b130a5cd7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2011-07-20 Ulrich Drepper <drepper@gmail.com>
+ [BZ #13007]
+ * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_profile): More complete
+ check for AVX enablement so that we don't crash with old kernels and
+ new hardware.
+ * elf/tst-audit4.c: Add same checks here.
+ * elf/tst-audit6.c: Likewise.
+
+2011-07-20 Ulrich Drepper <drepper@gmail.com>
+
[BZ #12852]
* posix/glob.c (glob): Check passed in values before using them in
expressions to avoid some overflows.
diff --git a/elf/tst-audit4.c b/elf/tst-audit4.c
index b17d4a61a7..c4f1d5bdb9 100644
--- a/elf/tst-audit4.c
+++ b/elf/tst-audit4.c
@@ -6,16 +6,30 @@
#include <cpuid.h>
#include <immintrin.h>
+
+static int
+avx_enabled (void)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) == 0
+ || (ecx & (bit_AVX | bit_OSXSAVE)) != (bit_AVX | bit_OSXSAVE))
+ return 0;
+
+ /* Check the OS has AVX and SSE saving enabled. */
+ asm ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (0));
+
+ return (eax & 6) == 6;
+}
+
+
extern __m256i audit_test (__m256i, __m256i, __m256i, __m256i,
__m256i, __m256i, __m256i, __m256i);
int
main (void)
{
- unsigned int eax, ebx, ecx, edx;
-
/* Run AVX test only if AVX is supported. */
- if (__get_cpuid (1, &eax, &ebx, &ecx, &edx)
- && (ecx & bit_AVX))
+ if (avx_enabled ())
{
__m256i ymm = _mm256_setzero_si256 ();
__m256i ret = audit_test (ymm, ymm, ymm, ymm, ymm, ymm, ymm, ymm);
diff --git a/elf/tst-audit6.c b/elf/tst-audit6.c
index 1f6dcb16e9..64209a152e 100644
--- a/elf/tst-audit6.c
+++ b/elf/tst-audit6.c
@@ -8,14 +8,28 @@
extern __m128i audit_test (__m128i, __m128i, __m128i, __m128i,
__m128i, __m128i, __m128i, __m128i);
-int
-main (void)
+
+static int
+avx_enabled (void)
{
unsigned int eax, ebx, ecx, edx;
+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) == 0
+ || (ecx & (bit_AVX | bit_OSXSAVE)) != (bit_AVX | bit_OSXSAVE))
+ return 0;
+
+ /* Check the OS has AVX and SSE saving enabled. */
+ asm ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (0));
+
+ return (eax & 6) == 6;
+}
+
+
+int
+main (void)
+{
/* Run AVX test only if AVX is supported. */
- if (__get_cpuid (1, &eax, &ebx, &ecx, &edx)
- && (ecx & bit_AVX))
+ if (avx_enabled ())
{
__m128i xmm = _mm_setzero_si128 ();
__m128i ret = audit_test (xmm, xmm, xmm, xmm, xmm, xmm, xmm, xmm);
diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S
index 5564a11af2..1b97929aaa 100644
--- a/sysdeps/x86_64/dl-trampoline.S
+++ b/sysdeps/x86_64/dl-trampoline.S
@@ -1,5 +1,5 @@
/* PLT trampolines. x86-64 version.
- Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2007, 2009, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -139,10 +139,17 @@ L(have_avx):
movl $1, %eax
cpuid
movq %r11,%rbx # Restore rbx
- movl $1, %eax
- testl $(1 << 28), %ecx
- jne 2f
- negl %eax
+ xorl %eax, %eax
+ // AVX and XSAVE supported?
+ testl $((1 << 28) | (1 << 27)), %ecx
+ je 2f
+ xorl %ecx, %ecx
+ // Get XFEATURE_ENABLED_MASK
+ xgetbv
+ andl $0x6, %eax
+ cmpl $0x6, %eax
+ // Nonzero if SSE and AVX state saving is enabled.
+ sete %al
2: movl %eax, L(have_avx)(%rip)
cmpl $0, %eax