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

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Sat Jan 11 15:52:04 2014 +0100

cobalt/arm: fix VFP related lockup

Running Xenomai compiled with HW FPU support on a processor without VFP
causes a lockup. Remedy that by testing at run-time whether the processor
supports VFP before using VFP instructions.

---

 kernel/cobalt/arch/arm/switch.S |    9 +++++++++
 kernel/cobalt/arch/arm/thread.c |   14 ++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/kernel/cobalt/arch/arm/switch.S b/kernel/cobalt/arch/arm/switch.S
index 969b28d..dc090b9 100644
--- a/kernel/cobalt/arch/arm/switch.S
+++ b/kernel/cobalt/arch/arm/switch.S
@@ -49,6 +49,12 @@
 
        .macro fpu_switch tmp
 #ifdef CONFIG_VFP
+#if __LINUX_ARM_ARCH__ <= 6
+       ldr     \tmp, =elf_hwcap
+       ldr     \tmp, [\tmp]
+       tst     \tmp, #HWCAP_VFP
+       beq     9999f
+#endif
        @ Always disable VFP so we can lazily save/restore the old
        @ state. This occurs in the context of the previous thread.
        VFPFMRX \tmp, FPEXC
@@ -58,6 +64,9 @@
        bic     \tmp, \tmp, #FPEXC_EN
 #endif
        VFPFMXR FPEXC, \tmp
+#if __LINUX_ARM_ARCH__ <= 6
+9999:
+#endif
 #endif
        .endm
 
diff --git a/kernel/cobalt/arch/arm/thread.c b/kernel/cobalt/arch/arm/thread.c
index 53c9879..f6e50c1 100644
--- a/kernel/cobalt/arch/arm/thread.c
+++ b/kernel/cobalt/arch/arm/thread.c
@@ -58,7 +58,14 @@ static inline union vfp_state *get_fpu_owner(void)
        unsigned int cpu;
 #ifdef CONFIG_SMP
        unsigned int fpexc;
+#endif
+
+#if __LINUX_ARM_ARCH__ <= 6
+       if ((elf_hwcap & HWCAP_VFP) == 0)
+               return NULL;
+#endif
 
+#ifdef CONFIG_SMP
        fpexc = do_vfp_fmrx(FPEXC);
        if (!(fpexc & FPEXC_EN))
                return NULL;
@@ -260,6 +267,13 @@ int xnarch_handle_fpu_fault(struct xnthread *from,
                /* FPU is already enabled, probably an exception */
                return 0;
 
+#if __LINUX_ARM_ARCH__ <= 6
+       if ((elf_hwcap & HWCAP_VFP) == 0)
+               /* VFP instruction emitted, on a cpu without VFP, this
+                  is an error */
+               return 0;
+#endif
+
        xnthread_set_state(to, XNFPU);
        xnarch_switch_fpu(from, to);
 


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

Reply via email to