power: smb349: add callback to update charger
[linux-2.6.git] / include / linux / kprobes.h
index e373c4a..dd7c12e 100644 (file)
  *             <jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *             <prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/config.h>
+#include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/smp.h>
 #include <linux/percpu.h>
 #include <linux/spinlock.h>
 #include <linux/rcupdate.h>
+#include <linux/mutex.h>
 
+#ifdef CONFIG_KPROBES
 #include <asm/kprobes.h>
 
 /* kprobe_status settings */
 
 /* Attach to insert probes on any functions which should be ignored*/
 #define __kprobes      __attribute__((__section__(".kprobes.text")))
+#else /* CONFIG_KPROBES */
+typedef int kprobe_opcode_t;
+struct arch_specific_insn {
+       int dummy;
+};
+#define __kprobes
+#endif /* CONFIG_KPROBES */
 
 struct kprobe;
 struct pt_regs;
@@ -73,18 +82,28 @@ struct kprobe {
        /* location of the probe point */
        kprobe_opcode_t *addr;
 
+       /* Allow user to indicate symbol name of the probe point */
+       const char *symbol_name;
+
+       /* Offset into the symbol */
+       unsigned int offset;
+
        /* Called before addr is executed. */
        kprobe_pre_handler_t pre_handler;
 
        /* Called after addr is executed, unless... */
        kprobe_post_handler_t post_handler;
 
-       /* ... called if executing addr causes a fault (eg. page fault).
-        * Return 1 if it handled fault, otherwise kernel will see it. */
+       /*
+        * ... called if executing addr causes a fault (eg. page fault).
+        * Return 1 if it handled fault, otherwise kernel will see it.
+        */
        kprobe_fault_handler_t fault_handler;
 
-       /* ... called if breakpoint trap occurs in probe handler.
-        * Return 1 if it handled break, otherwise kernel will see it. */
+       /*
+        * ... called if breakpoint trap occurs in probe handler.
+        * Return 1 if it handled break, otherwise kernel will see it.
+        */
        kprobe_break_handler_t break_handler;
 
        /* Saved opcode (which has been replaced with breakpoint) */
@@ -92,8 +111,40 @@ struct kprobe {
 
        /* copy of the original instruction */
        struct arch_specific_insn ainsn;
+
+       /*
+        * Indicates various status flags.
+        * Protected by kprobe_mutex after this kprobe is registered.
+        */
+       u32 flags;
 };
 
+/* Kprobe status flags */
+#define KPROBE_FLAG_GONE       1 /* breakpoint has already gone */
+#define KPROBE_FLAG_DISABLED   2 /* probe is temporarily disabled */
+#define KPROBE_FLAG_OPTIMIZED  4 /*
+                                  * probe is really optimized.
+                                  * NOTE:
+                                  * this flag is only for optimized_kprobe.
+                                  */
+
+/* Has this kprobe gone ? */
+static inline int kprobe_gone(struct kprobe *p)
+{
+       return p->flags & KPROBE_FLAG_GONE;
+}
+
+/* Is this kprobe disabled ? */
+static inline int kprobe_disabled(struct kprobe *p)
+{
+       return p->flags & (KPROBE_FLAG_DISABLED | KPROBE_FLAG_GONE);
+}
+
+/* Is this kprobe really running optimized path ? */
+static inline int kprobe_optimized(struct kprobe *p)
+{
+       return p->flags & KPROBE_FLAG_OPTIMIZED;
+}
 /*
  * Special probe type that uses setjmp-longjmp type tricks to resume
  * execution at a specified entry with a matching prototype corresponding
@@ -106,20 +157,12 @@ struct kprobe {
  */
 struct jprobe {
        struct kprobe kp;
-       kprobe_opcode_t *entry; /* probe handling code to jump to */
+       void *entry;    /* probe handling code to jump to */
 };
 
-DECLARE_PER_CPU(struct kprobe *, current_kprobe);
-DECLARE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+/* For backward compatibility with old code using JPROBE_ENTRY() */
+#define JPROBE_ENTRY(handler)  (handler)
 
-#ifdef ARCH_SUPPORTS_KRETPROBES
-extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs);
-#else /* ARCH_SUPPORTS_KRETPROBES */
-static inline void arch_prepare_kretprobe(struct kretprobe *rp,
-                                       struct pt_regs *regs)
-{
-}
-#endif /* ARCH_SUPPORTS_KRETPROBES */
 /*
  * Function-return probe -
  * Note:
@@ -133,45 +176,141 @@ static inline void arch_prepare_kretprobe(struct kretprobe *rp,
 struct kretprobe {
        struct kprobe kp;
        kretprobe_handler_t handler;
+       kretprobe_handler_t entry_handler;
        int maxactive;
        int nmissed;
+       size_t data_size;
        struct hlist_head free_instances;
-       struct hlist_head used_instances;
+       spinlock_t lock;
 };
 
 struct kretprobe_instance {
-       struct hlist_node uflist; /* either on free list or used list */
        struct hlist_node hlist;
        struct kretprobe *rp;
        kprobe_opcode_t *ret_addr;
        struct task_struct *task;
+       char data[0];
+};
+
+struct kretprobe_blackpoint {
+       const char *name;
+       void *addr;
+};
+
+struct kprobe_blackpoint {
+       const char *name;
+       unsigned long start_addr;
+       unsigned long range;
 };
 
 #ifdef CONFIG_KPROBES
-extern spinlock_t kretprobe_lock;
+DECLARE_PER_CPU(struct kprobe *, current_kprobe);
+DECLARE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
+/*
+ * For #ifdef avoidance:
+ */
+static inline int kprobes_built_in(void)
+{
+       return 1;
+}
+
+#ifdef CONFIG_KRETPROBES
+extern void arch_prepare_kretprobe(struct kretprobe_instance *ri,
+                                  struct pt_regs *regs);
+extern int arch_trampoline_kprobe(struct kprobe *p);
+#else /* CONFIG_KRETPROBES */
+static inline void arch_prepare_kretprobe(struct kretprobe *rp,
+                                       struct pt_regs *regs)
+{
+}
+static inline int arch_trampoline_kprobe(struct kprobe *p)
+{
+       return 0;
+}
+#endif /* CONFIG_KRETPROBES */
+
+extern struct kretprobe_blackpoint kretprobe_blacklist[];
+
+static inline void kretprobe_assert(struct kretprobe_instance *ri,
+       unsigned long orig_ret_address, unsigned long trampoline_address)
+{
+       if (!orig_ret_address || (orig_ret_address == trampoline_address)) {
+               printk("kretprobe BUG!: Processing kretprobe %p @ %p\n",
+                               ri->rp, ri->rp->kp.addr);
+               BUG();
+       }
+}
+
+#ifdef CONFIG_KPROBES_SANITY_TEST
+extern int init_test_probes(void);
+#else
+static inline int init_test_probes(void)
+{
+       return 0;
+}
+#endif /* CONFIG_KPROBES_SANITY_TEST */
+
 extern int arch_prepare_kprobe(struct kprobe *p);
-extern void arch_copy_kprobe(struct kprobe *p);
 extern void arch_arm_kprobe(struct kprobe *p);
 extern void arch_disarm_kprobe(struct kprobe *p);
-extern void arch_remove_kprobe(struct kprobe *p);
 extern int arch_init_kprobes(void);
 extern void show_registers(struct pt_regs *regs);
 extern kprobe_opcode_t *get_insn_slot(void);
-extern void free_insn_slot(kprobe_opcode_t *slot);
+extern void free_insn_slot(kprobe_opcode_t *slot, int dirty);
+extern void kprobes_inc_nmissed_count(struct kprobe *p);
+
+#ifdef CONFIG_OPTPROBES
+/*
+ * Internal structure for direct jump optimized probe
+ */
+struct optimized_kprobe {
+       struct kprobe kp;
+       struct list_head list;  /* list for optimizing queue */
+       struct arch_optimized_insn optinsn;
+};
+
+/* Architecture dependent functions for direct jump optimization */
+extern int arch_prepared_optinsn(struct arch_optimized_insn *optinsn);
+extern int arch_check_optimized_kprobe(struct optimized_kprobe *op);
+extern int arch_prepare_optimized_kprobe(struct optimized_kprobe *op);
+extern void arch_remove_optimized_kprobe(struct optimized_kprobe *op);
+extern void arch_optimize_kprobes(struct list_head *oplist);
+extern void arch_unoptimize_kprobes(struct list_head *oplist,
+                                   struct list_head *done_list);
+extern void arch_unoptimize_kprobe(struct optimized_kprobe *op);
+extern kprobe_opcode_t *get_optinsn_slot(void);
+extern void free_optinsn_slot(kprobe_opcode_t *slot, int dirty);
+extern int arch_within_optimized_kprobe(struct optimized_kprobe *op,
+                                       unsigned long addr);
+
+extern void opt_pre_handler(struct kprobe *p, struct pt_regs *regs);
+
+#ifdef CONFIG_SYSCTL
+extern int sysctl_kprobes_optimization;
+extern int proc_kprobes_optimization_handler(struct ctl_table *table,
+                                            int write, void __user *buffer,
+                                            size_t *length, loff_t *ppos);
+#endif
+
+#endif /* CONFIG_OPTPROBES */
 
 /* Get the kprobe at this addr (if any) - called with preemption disabled */
 struct kprobe *get_kprobe(void *addr);
+void kretprobe_hash_lock(struct task_struct *tsk,
+                        struct hlist_head **head, unsigned long *flags);
+void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags);
 struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
 
 /* kprobe_running() will just return the current_kprobe on this CPU */
 static inline struct kprobe *kprobe_running(void)
 {
-       return (__get_cpu_var(current_kprobe));
+       return (__this_cpu_read(current_kprobe));
 }
 
 static inline void reset_current_kprobe(void)
 {
-       __get_cpu_var(current_kprobe) = NULL;
+       __this_cpu_write(current_kprobe, NULL);
 }
 
 static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
@@ -181,20 +320,44 @@ static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
 
 int register_kprobe(struct kprobe *p);
 void unregister_kprobe(struct kprobe *p);
+int register_kprobes(struct kprobe **kps, int num);
+void unregister_kprobes(struct kprobe **kps, int num);
 int setjmp_pre_handler(struct kprobe *, struct pt_regs *);
 int longjmp_break_handler(struct kprobe *, struct pt_regs *);
 int register_jprobe(struct jprobe *p);
 void unregister_jprobe(struct jprobe *p);
+int register_jprobes(struct jprobe **jps, int num);
+void unregister_jprobes(struct jprobe **jps, int num);
 void jprobe_return(void);
+unsigned long arch_deref_entry_point(void *);
 
 int register_kretprobe(struct kretprobe *rp);
 void unregister_kretprobe(struct kretprobe *rp);
+int register_kretprobes(struct kretprobe **rps, int num);
+void unregister_kretprobes(struct kretprobe **rps, int num);
 
-struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp);
-void add_rp_inst(struct kretprobe_instance *ri);
 void kprobe_flush_task(struct task_struct *tk);
-void recycle_rp_inst(struct kretprobe_instance *ri);
-#else /* CONFIG_KPROBES */
+void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
+
+int disable_kprobe(struct kprobe *kp);
+int enable_kprobe(struct kprobe *kp);
+
+void dump_kprobe(struct kprobe *kp);
+
+#else /* !CONFIG_KPROBES: */
+
+static inline int kprobes_built_in(void)
+{
+       return 0;
+}
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+       return 0;
+}
+static inline struct kprobe *get_kprobe(void *addr)
+{
+       return NULL;
+}
 static inline struct kprobe *kprobe_running(void)
 {
        return NULL;
@@ -203,16 +366,30 @@ static inline int register_kprobe(struct kprobe *p)
 {
        return -ENOSYS;
 }
+static inline int register_kprobes(struct kprobe **kps, int num)
+{
+       return -ENOSYS;
+}
 static inline void unregister_kprobe(struct kprobe *p)
 {
 }
+static inline void unregister_kprobes(struct kprobe **kps, int num)
+{
+}
 static inline int register_jprobe(struct jprobe *p)
 {
        return -ENOSYS;
 }
+static inline int register_jprobes(struct jprobe **jps, int num)
+{
+       return -ENOSYS;
+}
 static inline void unregister_jprobe(struct jprobe *p)
 {
 }
+static inline void unregister_jprobes(struct jprobe **jps, int num)
+{
+}
 static inline void jprobe_return(void)
 {
 }
@@ -220,11 +397,43 @@ static inline int register_kretprobe(struct kretprobe *rp)
 {
        return -ENOSYS;
 }
+static inline int register_kretprobes(struct kretprobe **rps, int num)
+{
+       return -ENOSYS;
+}
 static inline void unregister_kretprobe(struct kretprobe *rp)
 {
 }
+static inline void unregister_kretprobes(struct kretprobe **rps, int num)
+{
+}
 static inline void kprobe_flush_task(struct task_struct *tk)
 {
 }
-#endif                         /* CONFIG_KPROBES */
-#endif                         /* _LINUX_KPROBES_H */
+static inline int disable_kprobe(struct kprobe *kp)
+{
+       return -ENOSYS;
+}
+static inline int enable_kprobe(struct kprobe *kp)
+{
+       return -ENOSYS;
+}
+#endif /* CONFIG_KPROBES */
+static inline int disable_kretprobe(struct kretprobe *rp)
+{
+       return disable_kprobe(&rp->kp);
+}
+static inline int enable_kretprobe(struct kretprobe *rp)
+{
+       return enable_kprobe(&rp->kp);
+}
+static inline int disable_jprobe(struct jprobe *jp)
+{
+       return disable_kprobe(&jp->kp);
+}
+static inline int enable_jprobe(struct jprobe *jp)
+{
+       return enable_kprobe(&jp->kp);
+}
+
+#endif /* _LINUX_KPROBES_H */