Module: xenomai-forge
Branch: next
Commit: f366ac9571e6f78f242a28aab38e552ddc3415cf
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=f366ac9571e6f78f242a28aab38e552ddc3415cf

Author: Jan Kiszka <jan.kis...@siemens.com>
Date:   Tue Jan 29 18:46:13 2013 +0100

switchtest: Add SSE and AVX check

Add a test for switching the lower SSE registers xmm0..7 or AVX
registers ymm0..7, provided the CPU supports the corresponding
feature. As xmm and ymm share their storage, we only need to check
one of the features.

Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>

---

 include/asm-arm/fptest.h            |    4 +
 include/asm-blackfin/fptest.h       |    4 +
 include/asm-nios2/fptest.h          |    4 +
 include/asm-powerpc/fptest.h        |    4 +
 include/asm-sh/fptest.h             |    4 +
 include/asm-x86/fptest.h            |  110 ++++++++++++++++++++++++++++++++++-
 kernel/drivers/testing/switchtest.c |    2 +
 testsuite/switchtest/switchtest.c   |    2 +
 8 files changed, 133 insertions(+), 1 deletions(-)

diff --git a/include/asm-arm/fptest.h b/include/asm-arm/fptest.h
index 924c226..be2bd15 100644
--- a/include/asm-arm/fptest.h
+++ b/include/asm-arm/fptest.h
@@ -54,6 +54,10 @@ static void __attribute__((constructor)) fp_init(void)
 
 #endif /* !__KERNEL__ */
 
+static inline void fp_features_init(void)
+{
+}
+
 static inline void fp_regs_set(unsigned val)
 {
        if (have_vfp) {
diff --git a/include/asm-blackfin/fptest.h b/include/asm-blackfin/fptest.h
index d14181d..afb11e1 100644
--- a/include/asm-blackfin/fptest.h
+++ b/include/asm-blackfin/fptest.h
@@ -23,6 +23,10 @@ static inline void fp_linux_end(void)
 #define printk printf
 #endif /* !__KERNEL__ */
 
+static inline void fp_features_init(void)
+{
+}
+
 static inline void fp_regs_set(unsigned val)
 {
 }
diff --git a/include/asm-nios2/fptest.h b/include/asm-nios2/fptest.h
index c3a2fe8..9e0d14c 100644
--- a/include/asm-nios2/fptest.h
+++ b/include/asm-nios2/fptest.h
@@ -23,6 +23,10 @@ static inline void fp_linux_end(void)
 #define printk printf
 #endif /* !__KERNEL__ */
 
+static inline void fp_features_init(void)
+{
+}
+
 static inline void fp_regs_set(unsigned val)
 {
 }
diff --git a/include/asm-powerpc/fptest.h b/include/asm-powerpc/fptest.h
index 46b97e0..ab56a8d 100644
--- a/include/asm-powerpc/fptest.h
+++ b/include/asm-powerpc/fptest.h
@@ -36,6 +36,10 @@ static inline void fp_linux_end(void)
 #define printk printf
 #endif /* !__KERNEL__ */
 
+static inline void fp_features_init(void)
+{
+}
+
 static inline void fp_regs_set(unsigned val)
 {
        uint64_t fpval = val;
diff --git a/include/asm-sh/fptest.h b/include/asm-sh/fptest.h
index b6200fd..99547be 100644
--- a/include/asm-sh/fptest.h
+++ b/include/asm-sh/fptest.h
@@ -23,6 +23,10 @@ static inline void fp_linux_end(void)
 #define printk printf
 #endif /* !__KERNEL__ */
 
+static inline void fp_features_init(void)
+{
+}
+
 static inline void fp_regs_set(unsigned val)
 {
 }
diff --git a/include/asm-x86/fptest.h b/include/asm-x86/fptest.h
index 4ddef1d..9c484b0 100644
--- a/include/asm-x86/fptest.h
+++ b/include/asm-x86/fptest.h
@@ -44,21 +44,104 @@ static inline void fp_linux_end(void)
 #define printk printf
 #endif /* !__KERNEL__ */
 
+#define FP_FEATURE_SSE                 0x01
+#define FP_FEATURE_AVX                 0x02
+
+#define FP_CPUID_SSE_MASK              (1 << 25)
+#define FP_CPUID_AVX_MASK              ((1 << 27) | (1 << 28))
+
+static unsigned long fp_features;
+
+static inline 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_SSE_MASK)
+               fp_features |= FP_FEATURE_SSE;
+       /* check for both xsave and avx */
+       if ((ecx & FP_CPUID_AVX_MASK) == FP_CPUID_AVX_MASK)
+               fp_features |= FP_FEATURE_AVX;
+}
+
 static inline void fp_regs_set(unsigned val)
 {
+       uint64_t vec[4] = { val, 0, val, 0 };
        unsigned i;
 
        for (i = 0; i < 8; i++)
                __asm__ __volatile__("fildl %0": /* no output */ :"m"(val));
+       if (fp_features & FP_FEATURE_AVX)
+               __asm__ __volatile__(
+                       "vmovupd %0,%%ymm0;"
+                       "vmovupd %0,%%ymm1;"
+                       "vmovupd %0,%%ymm2;"
+                       "vmovupd %0,%%ymm3;"
+                       "vmovupd %0,%%ymm4;"
+                       "vmovupd %0,%%ymm5;"
+                       "vmovupd %0,%%ymm6;"
+                       "vmovupd %0,%%ymm7;"
+                       : : "m" (vec[0]));
+       else if (fp_features & FP_FEATURE_SSE)
+               __asm__ __volatile__(
+                       "movupd %0,%%xmm0;"
+                       "movupd %0,%%xmm1;"
+                       "movupd %0,%%xmm2;"
+                       "movupd %0,%%xmm3;"
+                       "movupd %0,%%xmm4;"
+                       "movupd %0,%%xmm5;"
+                       "movupd %0,%%xmm6;"
+                       "movupd %0,%%xmm7;"
+                       : : "m" (vec[0]));
 }
 
 static inline unsigned fp_regs_check(unsigned val)
 {
        unsigned i, result = val;
+       uint64_t vec[8][4];
        unsigned e[8];
 
        for (i = 0; i < 8; i++)
                __asm__ __volatile__("fistpl %0":"=m"(e[7 - i]));
+       if (fp_features & FP_FEATURE_AVX) {
+               __asm__ __volatile__(
+                       "vmovupd %%ymm0,%0;"
+                       "vmovupd %%ymm1,%1;"
+                       "vmovupd %%ymm2,%2;"
+                       "vmovupd %%ymm3,%3;"
+                       "vmovupd %%ymm4,%4;"
+                       "vmovupd %%ymm5,%5;"
+                       "vmovupd %%ymm6,%6;"
+                       "vmovupd %%ymm7,%7;"
+                       :
+                       : "m" (vec[0][0]), "m" (vec[1][0]),
+                         "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_SSE) {
+               __asm__ __volatile__(
+                       "movupd %%xmm0,%0;"
+                       "movupd %%xmm1,%1;"
+                       "movupd %%xmm2,%2;"
+                       "movupd %%xmm3,%3;"
+                       "movupd %%xmm4,%4;"
+                       "movupd %%xmm5,%5;"
+                       "movupd %%xmm6,%6;"
+                       "movupd %%xmm7,%7;"
+                       :
+                       : "m" (vec[0][0]), "m" (vec[1][0]),
+                         "m" (vec[2][0]), "m" (vec[3][0]),
+                         "m" (vec[4][0]), "m" (vec[5][0]),
+                         "m" (vec[6][0]), "m" (vec[7][0]));
+       }
 
        for (i = 0; i < 8; i++)
                if (e[i] != val) {
@@ -66,8 +149,33 @@ static inline unsigned fp_regs_check(unsigned val)
                        result = e[i];
                }
 
+       if (fp_features & FP_FEATURE_AVX) {
+               for (i = 0; i < 8; i++) {
+                       int error = 0;
+                       if (vec[i][0] != val) {
+                               result = vec[i][0];
+                               error = 1;
+                       }
+                       if (vec[i][2] != val) {
+                               result = vec[i][2];
+                               error = 1;
+                       }
+                       if (error)
+                               printk("ymm%d: %llu/%llu != %u/%u\n",
+                                      i, (unsigned long long)vec[i][0],
+                                      (unsigned long long)vec[i][2],
+                                      val, val);
+               }
+       } else if (fp_features & FP_FEATURE_SSE) {
+               for (i = 0; i < 8; i++)
+                       if (vec[i][0] != val) {
+                               printk("xmm%d: %llu != %u\n",
+                                      i, (unsigned long long)vec[i][0], val);
+                               result = vec[i][0];
+                       }
+       }
+
        return result;
 }
 
-
 #endif /* _XENO_ASM_X86_FPTEST_H */
diff --git a/kernel/drivers/testing/switchtest.c 
b/kernel/drivers/testing/switchtest.c
index 8195b9a..e078917 100644
--- a/kernel/drivers/testing/switchtest.c
+++ b/kernel/drivers/testing/switchtest.c
@@ -749,6 +749,8 @@ int __init __switchtest_init(void)
 {
        int err;
 
+       fp_features_init();
+
        do {
                snprintf(device.device_name, RTDM_MAX_DEVNAME_LEN,
                         "rttest-switchtest%d",
diff --git a/testsuite/switchtest/switchtest.c 
b/testsuite/switchtest/switchtest.c
index d8114a1..5ef5c8e 100644
--- a/testsuite/switchtest/switchtest.c
+++ b/testsuite/switchtest/switchtest.c
@@ -1147,6 +1147,8 @@ int main(int argc, const char *argv[])
                exit(EXIT_FAILURE);
        }
 
+       fp_features_init();
+
        /* Parse command line options. */
        opterr = 0;
        for (;;) {


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to