[Xenomai-git] Gilles Chanteperdrix : FPU tracer.
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
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