#include <asm/fpu/api.h>
 #include <asm/fpu/xstate.h>
 #include <asm/cpufeature.h>
+#include <asm/trace/fpu.h>
 
 /*
  * High level FPU state handling functions:
 
        fpu->fpregs_active = 0;
        this_cpu_write(fpu_fpregs_owner_ctx, NULL);
+       trace_x86_fpu_regs_deactivated(fpu);
 }
 
 /* Must be paired with a 'clts' (fpregs_activate_hw()) before! */
 
        fpu->fpregs_active = 1;
        this_cpu_write(fpu_fpregs_owner_ctx, fpu);
+       trace_x86_fpu_regs_activated(fpu);
 }
 
 /*
 
                /* But leave fpu_fpregs_owner_ctx! */
                old_fpu->fpregs_active = 0;
+               trace_x86_fpu_regs_deactivated(old_fpu);
 
                /* Don't change CR0.TS if we just switch! */
                if (fpu.preload) {
                        new_fpu->counter++;
                        __fpregs_activate(new_fpu);
+                       trace_x86_fpu_regs_activated(new_fpu);
                        prefetch(&new_fpu->state);
                } else {
                        __fpregs_deactivate_hw();
 
--- /dev/null
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM x86_fpu
+
+#if !defined(_TRACE_FPU_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_FPU_H
+
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(x86_fpu,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu),
+
+       TP_STRUCT__entry(
+               __field(struct fpu *, fpu)
+               __field(bool, fpregs_active)
+               __field(bool, fpstate_active)
+               __field(int, counter)
+               __field(u64, xfeatures)
+               __field(u64, xcomp_bv)
+               ),
+
+       TP_fast_assign(
+               __entry->fpu            = fpu;
+               __entry->fpregs_active  = fpu->fpregs_active;
+               __entry->fpstate_active = fpu->fpstate_active;
+               __entry->counter        = fpu->counter;
+               if (boot_cpu_has(X86_FEATURE_OSXSAVE)) {
+                       __entry->xfeatures = fpu->state.xsave.header.xfeatures;
+                       __entry->xcomp_bv  = fpu->state.xsave.header.xcomp_bv;
+               }
+       ),
+       TP_printk("x86/fpu: %p fpregs_active: %d fpstate_active: %d counter: %d xfeatures: %llx xcomp_bv: %llx",
+                       __entry->fpu,
+                       __entry->fpregs_active,
+                       __entry->fpstate_active,
+                       __entry->counter,
+                       __entry->xfeatures,
+                       __entry->xcomp_bv
+       )
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_state,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_before_save,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_after_save,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_before_restore,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_after_restore,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_regs_activated,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_regs_deactivated,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_activate_state,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_deactivate_state,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_init_state,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_dropped,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_copy_src,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_copy_dst,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+DEFINE_EVENT(x86_fpu, x86_fpu_xstate_check_failed,
+       TP_PROTO(struct fpu *fpu),
+       TP_ARGS(fpu)
+);
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH asm/trace/
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE fpu
+#endif /* _TRACE_FPU_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
 
 
 #include <linux/hardirq.h>
 
+#define CREATE_TRACE_POINTS
+#include <asm/trace/fpu.h>
+
 /*
  * Represents the initial FPU state. It's mostly (but not completely) zeroes,
  * depending on the FPU hardware format:
        WARN_ON_FPU(fpu != ¤t->thread.fpu);
 
        preempt_disable();
+       trace_x86_fpu_before_save(fpu);
        if (fpu->fpregs_active) {
                if (!copy_fpregs_to_fpstate(fpu)) {
                        if (use_eager_fpu())
                                fpregs_deactivate(fpu);
                }
        }
+       trace_x86_fpu_after_save(fpu);
        preempt_enable();
 }
 EXPORT_SYMBOL_GPL(fpu__save);
        }
        preempt_enable();
 
+       trace_x86_fpu_copy_src(src_fpu);
+       trace_x86_fpu_copy_dst(dst_fpu);
+
        return 0;
 }
 
 
        if (!fpu->fpstate_active) {
                fpstate_init(&fpu->state);
+               trace_x86_fpu_init_state(fpu);
 
+               trace_x86_fpu_activate_state(fpu);
                /* Safe to do for the current task: */
                fpu->fpstate_active = 1;
        }
        } else {
                if (!fpu->fpstate_active) {
                        fpstate_init(&fpu->state);
+                       trace_x86_fpu_init_state(fpu);
 
+                       trace_x86_fpu_activate_state(fpu);
                        /* Safe to do for current and for stopped child tasks: */
                        fpu->fpstate_active = 1;
                }
                fpu->last_cpu = -1;
        } else {
                fpstate_init(&fpu->state);
+               trace_x86_fpu_init_state(fpu);
 
+               trace_x86_fpu_activate_state(fpu);
                /* Safe to do for stopped child tasks: */
                fpu->fpstate_active = 1;
        }
 
        /* Avoid __kernel_fpu_begin() right after fpregs_activate() */
        kernel_fpu_disable();
+       trace_x86_fpu_before_restore(fpu);
        fpregs_activate(fpu);
        copy_kernel_to_fpregs(&fpu->state);
        fpu->counter++;
+       trace_x86_fpu_after_restore(fpu);
        kernel_fpu_enable();
 }
 EXPORT_SYMBOL_GPL(fpu__restore);
 
        fpu->fpstate_active = 0;
 
+       trace_x86_fpu_dropped(fpu);
+
        preempt_enable();
 }
 
 
 #include <asm/fpu/regset.h>
 
 #include <asm/sigframe.h>
+#include <asm/trace/fpu.h>
 
 static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32;
 
                         */
                        state_size = sizeof(struct fxregs_state);
                        fx_only = 1;
+                       trace_x86_fpu_xstate_check_failed(fpu);
                } else {
                        state_size = fx_sw_user.xstate_size;
                        xfeatures = fx_sw_user.xfeatures;
                if (__copy_from_user(&fpu->state.xsave, buf_fx, state_size) ||
                    __copy_from_user(&env, buf, sizeof(env))) {
                        fpstate_init(&fpu->state);
+                       trace_x86_fpu_init_state(fpu);
                        err = -1;
                } else {
                        sanitize_restored_xstate(tsk, &env, xfeatures, fx_only);