perf_counter: hook up the tracepoint events
[safe/jmp/linux-2.6] / include / linux / perf_counter.h
index 97d86c2..065984c 100644 (file)
 #ifndef _LINUX_PERF_COUNTER_H
 #define _LINUX_PERF_COUNTER_H
 
-#include <asm/atomic.h>
-
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/rculist.h>
-#include <linux/rcupdate.h>
-#include <linux/spinlock.h>
-
-struct task_struct;
+#include <linux/types.h>
+#include <linux/ioctl.h>
 
 /*
  * User-space ABI bits:
@@ -35,12 +28,15 @@ enum hw_event_types {
        /*
         * Common hardware events, generalized by the kernel:
         */
-       PERF_COUNT_CYCLES               =  0,
+       PERF_COUNT_CPU_CYCLES           =  0,
        PERF_COUNT_INSTRUCTIONS         =  1,
        PERF_COUNT_CACHE_REFERENCES     =  2,
        PERF_COUNT_CACHE_MISSES         =  3,
        PERF_COUNT_BRANCH_INSTRUCTIONS  =  4,
        PERF_COUNT_BRANCH_MISSES        =  5,
+       PERF_COUNT_BUS_CYCLES           =  6,
+
+       PERF_HW_EVENTS_MAX              =  7,
 
        /*
         * Special "software" counters provided by the kernel, even if
@@ -50,11 +46,15 @@ enum hw_event_types {
         */
        PERF_COUNT_CPU_CLOCK            = -1,
        PERF_COUNT_TASK_CLOCK           = -2,
-       /*
-        * Future software events:
-        */
-       /* PERF_COUNT_PAGE_FAULTS       = -3,
-          PERF_COUNT_CONTEXT_SWITCHES  = -4, */
+       PERF_COUNT_PAGE_FAULTS          = -3,
+       PERF_COUNT_CONTEXT_SWITCHES     = -4,
+       PERF_COUNT_CPU_MIGRATIONS       = -5,
+       PERF_COUNT_PAGE_FAULTS_MIN      = -6,
+       PERF_COUNT_PAGE_FAULTS_MAJ      = -7,
+
+       PERF_SW_EVENTS_MIN              = -8,
+
+       PERF_TP_EVENTS_MIN              = -65536
 };
 
 /*
@@ -70,35 +70,79 @@ enum perf_counter_record_type {
  * Hardware event to monitor via a performance monitoring counter:
  */
 struct perf_counter_hw_event {
-       s64                     type;
+       __s64                   type;
+
+       __u64                   irq_period;
+       __u64                   record_type;
+       __u64                   read_format;
 
-       u64                     irq_period;
-       u32                     record_type;
+       __u64                   disabled       :  1, /* off by default        */
+                               nmi            :  1, /* NMI sampling          */
+                               raw            :  1, /* raw event type        */
+                               inherit        :  1, /* children inherit it   */
+                               pinned         :  1, /* must always be on PMU */
+                               exclusive      :  1, /* only group on PMU     */
+                               exclude_user   :  1, /* don't count user      */
+                               exclude_kernel :  1, /* ditto kernel          */
+                               exclude_hv     :  1, /* ditto hypervisor      */
+                               exclude_idle   :  1, /* don't count when idle */
 
-       u32                     disabled     :  1, /* off by default */
-                               nmi          :  1, /* NMI sampling   */
-                               raw          :  1, /* raw event type */
-                               __reserved_1 : 29;
+                               __reserved_1   : 54;
 
-       u64                     __reserved_2;
+       __u32                   extra_config_len;
+       __u32                   __reserved_4;
+
+       __u64                   __reserved_2;
+       __u64                   __reserved_3;
 };
 
 /*
- * Kernel-internal data types:
+ * Ioctls that can be done on a perf counter fd:
  */
+#define PERF_COUNTER_IOC_ENABLE                _IO('$', 0)
+#define PERF_COUNTER_IOC_DISABLE       _IO('$', 1)
+
+#ifdef __KERNEL__
+/*
+ * Kernel-internal data types and definitions:
+ */
+
+#ifdef CONFIG_PERF_COUNTERS
+# include <asm/perf_counter.h>
+#endif
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/rculist.h>
+#include <linux/rcupdate.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <asm/atomic.h>
+
+struct task_struct;
 
 /**
  * struct hw_perf_counter - performance counter hardware details:
  */
 struct hw_perf_counter {
-       u64                             config;
-       unsigned long                   config_base;
-       unsigned long                   counter_base;
-       int                             nmi;
-       unsigned int                    idx;
-       u64                             prev_count;
+#ifdef CONFIG_PERF_COUNTERS
+       union {
+               struct { /* hardware */
+                       u64                             config;
+                       unsigned long                   config_base;
+                       unsigned long                   counter_base;
+                       int                             nmi;
+                       unsigned int                    idx;
+               };
+               union { /* software */
+                       atomic64_t                      count;
+                       struct hrtimer                  hrtimer;
+               };
+       };
+       atomic64_t                      prev_count;
        u64                             irq_period;
-       s32                             next_count;
+       atomic64_t                      period_left;
+#endif
 };
 
 /*
@@ -122,34 +166,50 @@ struct perf_counter;
  * struct hw_perf_counter_ops - performance counter hw ops
  */
 struct hw_perf_counter_ops {
-       void (*hw_perf_counter_enable)  (struct perf_counter *counter);
-       void (*hw_perf_counter_disable) (struct perf_counter *counter);
-       void (*hw_perf_counter_read)    (struct perf_counter *counter);
+       int (*enable)                   (struct perf_counter *counter);
+       void (*disable)                 (struct perf_counter *counter);
+       void (*read)                    (struct perf_counter *counter);
 };
 
 /**
+ * enum perf_counter_active_state - the states of a counter
+ */
+enum perf_counter_active_state {
+       PERF_COUNTER_STATE_ERROR        = -2,
+       PERF_COUNTER_STATE_OFF          = -1,
+       PERF_COUNTER_STATE_INACTIVE     =  0,
+       PERF_COUNTER_STATE_ACTIVE       =  1,
+};
+
+struct file;
+
+/**
  * struct perf_counter - performance counter kernel representation:
  */
 struct perf_counter {
+#ifdef CONFIG_PERF_COUNTERS
        struct list_head                list_entry;
+       struct list_head                event_entry;
        struct list_head                sibling_list;
        struct perf_counter             *group_leader;
        const struct hw_perf_counter_ops *hw_ops;
 
-       int                             active;
-#if BITS_PER_LONG == 64
+       enum perf_counter_active_state  state;
+       enum perf_counter_active_state  prev_state;
        atomic64_t                      count;
-#else
-       atomic_t                        count32[2];
-#endif
+
        struct perf_counter_hw_event    hw_event;
        struct hw_perf_counter          hw;
 
        struct perf_counter_context     *ctx;
        struct task_struct              *task;
+       struct file                     *filp;
+
+       struct perf_counter             *parent;
+       struct list_head                child_list;
 
        /*
-        * Protect attach/detach:
+        * Protect attach/detach and child_list:
         */
        struct mutex                    mutex;
 
@@ -163,6 +223,10 @@ struct perf_counter {
        struct perf_data                *irqdata;
        struct perf_data                *usrdata;
        struct perf_data                data[2];
+
+       void (*destroy)(struct perf_counter *);
+       struct rcu_head                 rcu_head;
+#endif
 };
 
 /**
@@ -173,13 +237,22 @@ struct perf_counter {
 struct perf_counter_context {
 #ifdef CONFIG_PERF_COUNTERS
        /*
-        * Protect the list of counters:
+        * Protect the states of the counters in the list,
+        * nr_active, and the list:
         */
        spinlock_t              lock;
+       /*
+        * Protect the list of counters.  Locking either mutex or lock
+        * is sufficient to ensure the list doesn't change; to change
+        * the list you need to lock both the mutex and the spinlock.
+        */
+       struct mutex            mutex;
 
        struct list_head        counter_list;
+       struct list_head        event_list;
        int                     nr_counters;
        int                     nr_active;
+       int                     is_active;
        struct task_struct      *task;
 #endif
 };
@@ -192,6 +265,7 @@ struct perf_cpu_context {
        struct perf_counter_context     *task_ctx;
        int                             active_oncpu;
        int                             max_pertask;
+       int                             exclusive;
 };
 
 /*
@@ -206,15 +280,28 @@ hw_perf_counter_init(struct perf_counter *counter);
 extern void perf_counter_task_sched_in(struct task_struct *task, int cpu);
 extern void perf_counter_task_sched_out(struct task_struct *task, int cpu);
 extern void perf_counter_task_tick(struct task_struct *task, int cpu);
-extern void perf_counter_init_task(struct task_struct *task);
+extern void perf_counter_init_task(struct task_struct *child);
+extern void perf_counter_exit_task(struct task_struct *child);
 extern void perf_counter_notify(struct pt_regs *regs);
 extern void perf_counter_print_debug(void);
+extern void perf_counter_unthrottle(void);
 extern u64 hw_perf_save_disable(void);
 extern void hw_perf_restore(u64 ctrl);
-extern void atomic64_counter_set(struct perf_counter *counter, u64 val64);
-extern u64 atomic64_counter_read(struct perf_counter *counter);
 extern int perf_counter_task_disable(void);
 extern int perf_counter_task_enable(void);
+extern int hw_perf_group_sched_in(struct perf_counter *group_leader,
+              struct perf_cpu_context *cpuctx,
+              struct perf_counter_context *ctx, int cpu);
+
+/*
+ * Return 1 for a software counter, 0 for a hardware counter
+ */
+static inline int is_software_counter(struct perf_counter *counter)
+{
+       return !counter->hw_event.raw && counter->hw_event.type < 0;
+}
+
+extern void perf_swcounter_event(enum hw_event_types, u64, int, struct pt_regs *);
 
 #else
 static inline void
@@ -223,13 +310,19 @@ static inline void
 perf_counter_task_sched_out(struct task_struct *task, int cpu)         { }
 static inline void
 perf_counter_task_tick(struct task_struct *task, int cpu)              { }
-static inline void perf_counter_init_task(struct task_struct *task)    { }
+static inline void perf_counter_init_task(struct task_struct *child)   { }
+static inline void perf_counter_exit_task(struct task_struct *child)   { }
 static inline void perf_counter_notify(struct pt_regs *regs)           { }
 static inline void perf_counter_print_debug(void)                      { }
-static inline void hw_perf_restore(u64 ctrl)                   { }
+static inline void perf_counter_unthrottle(void)                       { }
+static inline void hw_perf_restore(u64 ctrl)                           { }
 static inline u64 hw_perf_save_disable(void)                 { return 0; }
 static inline int perf_counter_task_disable(void)      { return -EINVAL; }
 static inline int perf_counter_task_enable(void)       { return -EINVAL; }
+
+static inline void perf_swcounter_event(enum hw_event_types event, u64 nr,
+                                       int nmi, struct pt_regs *regs)  { }
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* _LINUX_PERF_COUNTER_H */