[Xenomai-git] Gilles Chanteperdrix : FPU tracer.

2009-12-19 Thread GIT version control
Module: xenomai-gch
Branch: fpu-tracer
Commit: 5fb185858c95c2f6cd45565efdecd72a28a2152f
URL:
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=5fb185858c95c2f6cd45565efdecd72a28a2152f

Author: Gilles Chanteperdrix 
Date:   Sat Apr 11 20:32:11 2009 +0200

FPU tracer.

Working on x86_32 and x86_64.

---

 include/asm-generic/fp_dump.h |  149 
 include/asm-powerpc/fp_dump.h |  126 +++
 include/asm-x86/bits/pod_32.h |   49 ++-
 include/asm-x86/bits/pod_64.h |   50 +++-
 include/asm-x86/fp_dump.h |  175 +
 include/nucleus/fpu_trace.h   |   49 +++
 ksrc/arch/x86/patches/fp_tracepoints.diff |  107 ++
 ksrc/nucleus/Makefile |4 +-
 ksrc/nucleus/fpu_trace.c  |  566 +
 ksrc/nucleus/pod.c|2 +
 ksrc/nucleus/shadow.c |4 +
 src/testsuite/switchtest/switchtest.c |2 +
 12 files changed, 1265 insertions(+), 18 deletions(-)

diff --git a/include/asm-generic/fp_dump.h b/include/asm-generic/fp_dump.h
new file mode 100644
index 000..fe83ff0
--- /dev/null
+++ b/include/asm-generic/fp_dump.h
@@ -0,0 +1,149 @@
+#ifndef FP_DUMP_INNER_H
+#define FP_DUMP_INNER_H
+
+#include   /* For printk */
+#include   /* For fls */
+#include  /* For do_div */
+
+#ifndef fp_print
+#define fp_print(cookie, fmt, args...) printk(fmt , ##args)
+#endif /* fp_print */
+
+/* Float in course of conversion from base 2 to base 10.
+   f == significand * 2 ^ (exp - 63) * 10 ^ pow10. */
+typedef struct fp_conv {
+   unsigned long long significand;
+   int pow10;
+   int exp;
+} fp_conv_t;
+
+static inline unsigned __attribute__((const)) fp_sq(unsigned x)
+{
+   return x * x;
+}
+
+static inline unsigned __attribute__((const)) fp_pow3(unsigned x)
+{
+   return x * fp_sq(x);
+}
+
+static inline unsigned __attribute__((const)) fp_pow6(unsigned x)
+{
+   return fp_sq(fp_pow3(x));
+}
+
+static inline unsigned __attribute__((const)) fp_pow9(unsigned x)
+{
+   return fp_pow3(fp_pow3(x));
+}
+
+#define fp_flnzul(word) (fls(word) - 1)
+
+static inline unsigned long fp_flnzull(unsigned long long ull)
+{
+   unsigned long h = (ull >> 32);
+   if(h)
+   return 32 + fp_flnzul(h);
+   return fp_flnzul((unsigned long) ull);
+}
+
+static inline unsigned long upow(unsigned long x, unsigned long n)
+{
+   switch(n) {
+case 1: return x;
+case 2: return fp_sq(x);
+case 3: return fp_pow3(x);
+case 6: return fp_pow6(x);
+case 9: return fp_pow9(x);
+   }
+
+   return -1;
+}
+
+/* Divide significand by a power of two and multiply by a power of 10. */
+static inline void shiftmul(fp_conv_t *fp, unsigned shift, unsigned pow10)
+{
+   /* Avoid overflow. */
+   if((fp->significand & (1ULL << 63))) {
+   fp->significand >>= 1;
+   fp->exp++;
+   }
+
+   fp->significand >>= shift - pow10 -1;
+   fp->significand *= upow(5, pow10);
+   fp->exp += shift - 1;
+   fp->pow10 -= pow10;
+}
+
+/* Divide significand by a power of ten and multiply by a power of 2. */
+static inline void divshift(fp_conv_t *fp, unsigned pow10, unsigned shift)
+{
+   do_div(fp->significand, upow(5, pow10));
+   fp->significand <<= shift - pow10 -1;
+   fp->exp -= shift - 1;
+   fp->pow10 += pow10;
+
+   /* Maintain accuracy. */
+   if(!(fp->significand & (1ULL << 63))) {
+   fp->significand <<= 1;
+   fp->exp--;
+}
+}
+
+static inline void fp_disp(void *cookie, fp_conv_t *fp, int neg)
+{
+   /* Normalize. */
+   if(fp->significand && !(fp->significand & (1ULL << 63))) {
+   unsigned shift = 63 - fp_flnzull(fp->significand);
+   fp->significand <<= shift;
+   fp->exp -= shift;
+}
+
+   /* Convert power of 2 exponent to power of 10,
+  bring exponent between 0 and 63 for integers,
+  between 0 and 29 for non integers. */
+   while(fp->exp <= 0)
+   shiftmul(fp, 30, 9);
+   while(fp->exp > 63 || (fp->pow10 && fp->exp >= 29))
+   divshift(fp, 9, 30);
+
+   /* For non-integer, bring integer part between 0 and 10. */
+   if(fp->pow10) {
+   if(fp->exp >= 19)
+   divshift(fp, 6, 20);
+   if(fp->exp >= 9)
+   divshift(fp, 3, 10);
+   if(fp->exp >= 6)
+   divshift(fp, 2, 7);
+   if(fp->exp > 3)
+   divshift(fp, 1, 4);
+}
+
+   {
+   unsigned long long tmp, i;
+   unsigned long f, rem;
+   /* Integer part. */
+   i = fp->significand >> (63 - fp->exp);
+
+   /* Fractionary part, left-aligned. */
+   tmp = (fp->significand << (fp->exp + 1));
+
+  

[Xenomai-git] Gilles Chanteperdrix : fpu-tracer for powerpc now working

2009-12-19 Thread GIT version control
Module: xenomai-gch
Branch: fpu-tracer
Commit: 9f9a8a505623c7769582bb03ba7e41e5629a31ef
URL:
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=9f9a8a505623c7769582bb03ba7e41e5629a31ef

Author: Gilles Chanteperdrix 
Date:   Tue Aug 11 23:50:02 2009 +0200

fpu-tracer for powerpc now working

---

 include/asm-powerpc/bits/pod.h |   50 ---
 ksrc/arch/powerpc/Config.in|3 ++
 ksrc/arch/powerpc/fpu.S|   18 ++
 ksrc/nucleus/pod.c |2 +
 ksrc/nucleus/shadow.c  |2 -
 5 files changed, 64 insertions(+), 11 deletions(-)

diff --git a/include/asm-powerpc/bits/pod.h b/include/asm-powerpc/bits/pod.h
index 8f52f7b..0d47a22 100644
--- a/include/asm-powerpc/bits/pod.h
+++ b/include/asm-powerpc/bits/pod.h
@@ -24,6 +24,7 @@
 #define _XENO_ASM_POWERPC_BITS_POD_H
 
 #include 
+#include 
 
 void xnpod_welcome_thread(struct xnthread *, int);
 
@@ -55,6 +56,7 @@ static inline void xnarch_leave_root(xnarchtcb_t * rootcb)
/* So that xnarch_save_fpu() will operate on the right FPU area. */
rootcb->fpup = rootcb->user_fpu_owner ?
&rootcb->user_fpu_owner->thread : NULL;
+   fp_trace_xeno_leave_root(rootcb->user_fpu_owner == current ? 1 : 2);
 #endif /* CONFIG_XENO_HW_FPU */
 }
 
@@ -199,6 +201,7 @@ static void xnarch_init_fpu(xnarchtcb_t * tcb)
 * in tcb.
 */
rthal_init_fpu(&tcb->ts);
+   fp_trace_xeno_init(1, tcb);
 #endif /* CONFIG_XENO_HW_FPU */
 }
 
@@ -206,11 +209,14 @@ static inline void xnarch_enable_fpu(xnarchtcb_t *tcb)
 {
 #ifdef CONFIG_XENO_HW_FPU
struct task_struct *task = tcb->user_task;
-
-if (task && task != tcb->user_fpu_owner)
+ 
+   if (task && task != tcb->user_fpu_owner) {
rthal_disable_fpu();
-   else
+   fp_trace_xeno_enable(1, 0, tcb);
+   } else {
rthal_enable_fpu();
+   fp_trace_xeno_enable(2, 0, tcb);
+   }
 #endif /* CONFIG_XENO_HW_FPU */
 }
 
@@ -221,9 +227,13 @@ static void xnarch_save_fpu(xnarchtcb_t * tcb)
rthal_save_fpu(tcb->fpup);
 
if (tcb->user_fpu_owner &&
-   tcb->user_fpu_owner->thread.regs)
+   tcb->user_fpu_owner->thread.regs) {
tcb->user_fpu_owner->thread.regs->msr &= 
~(MSR_FP|MSR_FE0|MSR_FE1);
-   }
+   fp_trace_xeno_save(1, 1, tcb);
+   } else
+   fp_trace_xeno_save(2, 1, tcb);
+   } else
+   fp_trace_xeno_save(3, 1, tcb);
 #endif /* CONFIG_XENO_HW_FPU */
 }
 
@@ -232,6 +242,7 @@ static void xnarch_restore_fpu(xnarchtcb_t * tcb)
 #ifdef CONFIG_XENO_HW_FPU
struct thread_struct *ts;
struct pt_regs *regs;
+   unsigned branch;
 
if (tcb->fpup) {
rthal_restore_fpu(tcb->fpup);
@@ -245,16 +256,37 @@ static void xnarch_restore_fpu(xnarchtcb_t * tcb)
if (regs) {
regs->msr &= ~(MSR_FE0|MSR_FE1);
regs->msr |= (MSR_FP|ts->fpexc_mode);
-   }
-   }
-   }
+   branch = 1;
+   } else
+   branch = 2;
+   } else
+   branch = 3;
+   } else
+   branch = 4;
/*
 * FIXME: We restore FPU "as it was" when Xenomai preempted Linux,
 * whereas we could be much lazier.
 */
-if (tcb->user_task && tcb->user_task != tcb->user_fpu_owner)
+if (tcb->user_task && tcb->user_task != tcb->user_fpu_owner) {
+   fp_trace_xeno_restore(branch, 1, tcb);
rthal_disable_fpu();
+   } else
+   fp_trace_xeno_restore(branch + 10, 1, tcb);
+#endif /* CONFIG_XENO_HW_FPU */
+}
 
+static inline void xnarch_enable_fpu(xnarchtcb_t *tcb)
+{
+#ifdef CONFIG_XENO_HW_FPU
+   struct task_struct *task = tcb->user_task;
+
+if (task && task != tcb->user_fpu_owner) {
+   rthal_disable_fpu();
+   fp_trace_xeno_enable(1, 0, tcb);
+   } else {
+   rthal_enable_fpu();
+   fp_trace_xeno_enable(2, 0, tcb);
+   }
 #endif /* CONFIG_XENO_HW_FPU */
 }
 
diff --git a/ksrc/arch/powerpc/Config.in b/ksrc/arch/powerpc/Config.in
index d0b26db..a24fd0f 100644
--- a/ksrc/arch/powerpc/Config.in
+++ b/ksrc/arch/powerpc/Config.in
@@ -14,6 +14,9 @@ else
mainmenu_option next_comment
comment 'Machine'
bool 'Enable FPU support' CONFIG_XENO_HW_FPU
+if [ "$CONFIG_XENO_HW_FPU" = "y" ]; then
+   bool 'Enable FPU tracer' CONFIG_XENO_HW_FPU_TRACER
+   fi
endmenu
 fi
 fi
diff --git a/ksrc/arch/powerpc/fpu.S b/ksrc/arch/powerpc/fpu.S
index e0adf90..ff9b5d7 100644
--- a/ksrc/arch/powerpc/fpu.S
+++ b/ksrc/arch/powerpc/fpu.S
@@ -72,6 +72,24 @@ _GLOBAL(rthal_save_fpu)
SAVE_32FPRS(0,r