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

Reply via email to