From 5644ef5461b5d3ff266206d8ee70d4b575ea6658 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 20 Jul 2011 21:21:03 -0400 Subject: [PATCH] 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. --- ChangeLog | 9 ++++++++- NEWS | 4 ++-- elf/tst-audit4.c | 22 ++++++++++++++++++---- elf/tst-audit6.c | 22 ++++++++++++++++++---- sysdeps/x86_64/dl-trampoline.S | 17 ++++++++++++----- 5 files changed, 58 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 593dddd..f47300f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,13 @@ 2011-07-20 Ulrich Drepper - * sysdeps/x86_64/bits/link.h (La_x86_64_ymm): Force 16-byt alignment. + [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. + + * sysdeps/x86_64/bits/link.h (La_x86_64_ymm): Force 16-byte alignment. 2011-07-09 Andreas Schwab diff --git a/NEWS b/NEWS index eeef739..2dd7bea 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -GNU C Library NEWS -- history of user-visible changes. 2011-7-19 +GNU C Library NEWS -- history of user-visible changes. 2011-7-20 Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc. See the end for copying conditions. @@ -9,7 +9,7 @@ Version 2.15 * The following bugs are resolved with this release: - 9696, 12868, 12874, 12885, 12907, 12922, 12935 + 9696, 12868, 12874, 12885, 12907, 12922, 12935, 13007 * New program pldd to list loaded object of a process Implemented by Ulrich Drepper. diff --git a/elf/tst-audit4.c b/elf/tst-audit4.c index b17d4a6..c4f1d5b 100644 --- a/elf/tst-audit4.c +++ b/elf/tst-audit4.c @@ -6,16 +6,30 @@ #include #include + +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 1f6dcb1..64209a1 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 5564a11..1b97929 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 -- 2.7.4