diff options
author | Ulrich Drepper <drepper@gmail.com> | 2011-07-20 21:21:03 -0400 |
---|---|---|
committer | Andreas Schwab <schwab@redhat.com> | 2011-07-25 10:04:42 +0200 |
commit | 722bff7a4ccceeded69ac8c412ff5ee5859964e7 (patch) | |
tree | 30cdca823f4c90ec364a8905a6f57faf0c4a57f3 | |
parent | 63072fc6170f06657800a536c084db5d6e45e80f (diff) | |
download | glibc-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-- | ChangeLog | 9 | ||||
-rw-r--r-- | elf/tst-audit4.c | 22 | ||||
-rw-r--r-- | elf/tst-audit6.c | 22 | ||||
-rw-r--r-- | sysdeps/x86_64/dl-trampoline.S | 17 |
4 files changed, 57 insertions, 13 deletions
@@ -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 |