Module: xenomai-forge Branch: next Commit: ee15006a565d68270ec5b7fc72e6dda70c82e8d5 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=ee15006a565d68270ec5b7fc72e6dda70c82e8d5
Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org> Date: Tue Jun 4 07:47:26 2013 +0200 x86: fix FPU features detection Unconditionnaly using cpuid 1 to detect fpu features does not work: - the cpuid instruction is not available on all cpus - on cpus with cpuid instruction, it is necessary to invoke cpuid 0 to know if cpuid 1 is supported. So, instead of re-implementing what the Linux kernel already implements, use the macro it provides in kernel-space, and the flags exported by /proc/cpuinfo in user-space, like we do on ARM. --- include/asm-x86/fptest.h | 72 ++++++++++++++++++++++++++++----------------- 1 files changed, 45 insertions(+), 27 deletions(-) diff --git a/include/asm-x86/fptest.h b/include/asm-x86/fptest.h index 6c98027..2611389 100644 --- a/include/asm-x86/fptest.h +++ b/include/asm-x86/fptest.h @@ -4,6 +4,19 @@ #ifdef __KERNEL__ #include <linux/module.h> #include <asm/i387.h> +#include <asm/processor.h> + +#ifndef cpu_has_xmm2 +#ifdef cpu_has_sse2 +#define cpu_has_xmm2 cpu_has_sse2 +#else +#define cpu_has_xmm2 0 +#endif +#endif + +#ifndef cpu_has_avx +#define cpu_has_avx 0 +#endif static inline int fp_kernel_supported(void) { @@ -39,38 +52,43 @@ static inline void fp_linux_end(void) kernel_fpu_end(); } +static inline void fp_features_init(void) +{ +} + #else /* !__KERNEL__ */ #include <stdio.h> #define printk printf -#endif /* !__KERNEL__ */ #define FP_FEATURE_SSE2 0x01 #define FP_FEATURE_AVX 0x02 -#define FP_CPUID_SSE2_MASK (1 << 26) -#define FP_CPUID_AVX_MASK ((1 << 27) | (1 << 28)) - static unsigned long fp_features; -static inline void fp_features_init(void) +#define cpu_has_xmm2 (fp_features & FP_FEATURE_SSE2) +#define cpu_has_avx (fp_features & FP_FEATURE_AVX) + +static void fp_features_init(void) { - unsigned int eax, ebx, ecx, edx; - - eax = 1; - __asm__ __volatile__("cpuid" - : "=a" (eax), - "=b" (ebx), - "=c" (ecx), - "=d" (edx) - : "0" (eax) - : "memory"); - - if (edx & FP_CPUID_SSE2_MASK) - fp_features |= FP_FEATURE_SSE2; - /* check for both xsave and avx */ - if ((ecx & FP_CPUID_AVX_MASK) == FP_CPUID_AVX_MASK) - fp_features |= FP_FEATURE_AVX; + char buffer[1024]; + FILE *f = fopen("/proc/cpuinfo", "r"); + if(!f) + return; + + while(fgets(buffer, sizeof(buffer), f)) { + if(strncmp(buffer, "flags", sizeof("flags") - 1)) + continue; + + if (strstr(buffer, "sse2")) + fp_features |= FP_FEATURE_SSE2; + if (strstr(buffer, "avx")) + fp_features |= FP_FEATURE_AVX; + break; + } + + fclose(f); } +#endif /* !__KERNEL__ */ static inline void fp_regs_set(unsigned val) { @@ -79,7 +97,7 @@ static inline void fp_regs_set(unsigned val) for (i = 0; i < 8; i++) __asm__ __volatile__("fildl %0": /* no output */ :"m"(val)); - if (fp_features & FP_FEATURE_AVX) + if (cpu_has_avx) __asm__ __volatile__( "vmovupd %0,%%ymm0;" "vmovupd %0,%%ymm1;" @@ -90,7 +108,7 @@ static inline void fp_regs_set(unsigned val) "vmovupd %0,%%ymm6;" "vmovupd %0,%%ymm7;" : : "m" (vec[0])); - else if (fp_features & FP_FEATURE_SSE2) + else if (cpu_has_xmm2) __asm__ __volatile__( "movupd %0,%%xmm0;" "movupd %0,%%xmm1;" @@ -111,7 +129,7 @@ static inline unsigned fp_regs_check(unsigned val) for (i = 0; i < 8; i++) __asm__ __volatile__("fistpl %0":"=m"(e[7 - i])); - if (fp_features & FP_FEATURE_AVX) { + if (cpu_has_avx) { __asm__ __volatile__( "vmovupd %%ymm0,%0;" "vmovupd %%ymm1,%1;" @@ -125,7 +143,7 @@ static inline unsigned fp_regs_check(unsigned val) "=m" (vec[2][0]), "=m" (vec[3][0]), "=m" (vec[4][0]), "=m" (vec[5][0]), "=m" (vec[6][0]), "=m" (vec[7][0])); - } else if (fp_features & FP_FEATURE_SSE2) { + } else if (cpu_has_xmm2) { __asm__ __volatile__( "movupd %%xmm0,%0;" "movupd %%xmm1,%1;" @@ -147,7 +165,7 @@ static inline unsigned fp_regs_check(unsigned val) result = e[i]; } - if (fp_features & FP_FEATURE_AVX) { + if (cpu_has_avx) { for (i = 0; i < 8; i++) { int error = 0; if (vec[i][0] != val) { @@ -164,7 +182,7 @@ static inline unsigned fp_regs_check(unsigned val) (unsigned long long)vec[i][2], val, val); } - } else if (fp_features & FP_FEATURE_SSE2) { + } else if (cpu_has_xmm2) { for (i = 0; i < 8; i++) if (vec[i][0] != val) { printk("xmm%d: %llu != %u\n", _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git