perf_events: Simplify code by removing cpu argument to hw_perf_group_sched_in()
[safe/jmp/linux-2.6] / kernel / kprobes.c
index f72e96c..ccec774 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/debugfs.h>
 #include <linux/kdebug.h>
 #include <linux/memory.h>
+#include <linux/ftrace.h>
 
 #include <asm-generic/sections.h>
 #include <asm/cacheflush.h>
@@ -90,6 +91,10 @@ static spinlock_t *kretprobe_table_lock_ptr(unsigned long hash)
  */
 static struct kprobe_blackpoint kprobe_blacklist[] = {
        {"preempt_schedule",},
+       {"native_get_debugreg",},
+       {"irq_entries_start",},
+       {"common_interrupt",},
+       {"mcount",},    /* mcount can be called from everywhere */
        {NULL}    /* Terminator */
 };
 
@@ -121,30 +126,6 @@ static LIST_HEAD(kprobe_insn_pages);
 static int kprobe_garbage_slots;
 static int collect_garbage_slots(void);
 
-static int __kprobes check_safety(void)
-{
-       int ret = 0;
-#if defined(CONFIG_PREEMPT) && defined(CONFIG_FREEZER)
-       ret = freeze_processes();
-       if (ret == 0) {
-               struct task_struct *p, *q;
-               do_each_thread(p, q) {
-                       if (p != current && p->state == TASK_RUNNING &&
-                           p->pid != 0) {
-                               printk("Check failed: %s is running\n",p->comm);
-                               ret = -1;
-                               goto loop_end;
-                       }
-               } while_each_thread(p, q);
-       }
-loop_end:
-       thaw_processes();
-#else
-       synchronize_sched();
-#endif
-       return ret;
-}
-
 /**
  * __get_insn_slot() - Find a slot on an executable page for an instruction.
  * We allocate an executable page if there's no room on existing ones.
@@ -232,9 +213,8 @@ static int __kprobes collect_garbage_slots(void)
 {
        struct kprobe_insn_page *kip, *next;
 
-       /* Ensure no-one is preepmted on the garbages */
-       if (check_safety())
-               return -EAGAIN;
+       /* Ensure no-one is interrupted on the garbages */
+       synchronize_sched();
 
        list_for_each_entry_safe(kip, next, &kprobe_insn_pages, list) {
                int i;
@@ -673,6 +653,40 @@ static kprobe_opcode_t __kprobes *kprobe_addr(struct kprobe *p)
        return (kprobe_opcode_t *)(((char *)addr) + p->offset);
 }
 
+/* Check passed kprobe is valid and return kprobe in kprobe_table. */
+static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p)
+{
+       struct kprobe *old_p, *list_p;
+
+       old_p = get_kprobe(p->addr);
+       if (unlikely(!old_p))
+               return NULL;
+
+       if (p != old_p) {
+               list_for_each_entry_rcu(list_p, &old_p->list, list)
+                       if (list_p == p)
+                       /* kprobe p is a valid probe */
+                               goto valid;
+               return NULL;
+       }
+valid:
+       return old_p;
+}
+
+/* Return error if the kprobe is being re-registered */
+static inline int check_kprobe_rereg(struct kprobe *p)
+{
+       int ret = 0;
+       struct kprobe *old_p;
+
+       mutex_lock(&kprobe_mutex);
+       old_p = __get_valid_kprobe(p);
+       if (old_p)
+               ret = -EINVAL;
+       mutex_unlock(&kprobe_mutex);
+       return ret;
+}
+
 int __kprobes register_kprobe(struct kprobe *p)
 {
        int ret = 0;
@@ -685,9 +699,14 @@ int __kprobes register_kprobe(struct kprobe *p)
                return -EINVAL;
        p->addr = addr;
 
+       ret = check_kprobe_rereg(p);
+       if (ret)
+               return ret;
+
        preempt_disable();
        if (!kernel_text_address((unsigned long) p->addr) ||
-           in_kprobes_functions((unsigned long) p->addr)) {
+           in_kprobes_functions((unsigned long) p->addr) ||
+           ftrace_text_reserved(p->addr, p->addr)) {
                preempt_enable();
                return -EINVAL;
        }
@@ -754,26 +773,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(register_kprobe);
 
-/* Check passed kprobe is valid and return kprobe in kprobe_table. */
-static struct kprobe * __kprobes __get_valid_kprobe(struct kprobe *p)
-{
-       struct kprobe *old_p, *list_p;
-
-       old_p = get_kprobe(p->addr);
-       if (unlikely(!old_p))
-               return NULL;
-
-       if (p != old_p) {
-               list_for_each_entry_rcu(list_p, &old_p->list, list)
-                       if (list_p == p)
-                       /* kprobe p is a valid probe */
-                               goto valid;
-               return NULL;
-       }
-valid:
-       return old_p;
-}
-
 /*
  * Unregister a kprobe without a scheduler synchronization.
  */
@@ -1014,9 +1013,9 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
        /* Pre-allocate memory for max kretprobe instances */
        if (rp->maxactive <= 0) {
 #ifdef CONFIG_PREEMPT
-               rp->maxactive = max(10, 2 * NR_CPUS);
+               rp->maxactive = max_t(unsigned int, 10, 2*num_possible_cpus());
 #else
-               rp->maxactive = NR_CPUS;
+               rp->maxactive = num_possible_cpus();
 #endif
        }
        spin_lock_init(&rp->lock);
@@ -1328,7 +1327,7 @@ static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v)
        return 0;
 }
 
-static struct seq_operations kprobes_seq_ops = {
+static const struct seq_operations kprobes_seq_ops = {
        .start = kprobe_seq_start,
        .next  = kprobe_seq_next,
        .stop  = kprobe_seq_stop,
@@ -1340,7 +1339,7 @@ static int __kprobes kprobes_open(struct inode *inode, struct file *filp)
        return seq_open(filp, &kprobes_seq_ops);
 }
 
-static struct file_operations debugfs_kprobes_operations = {
+static const struct file_operations debugfs_kprobes_operations = {
        .open           = kprobes_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -1522,7 +1521,7 @@ static ssize_t write_enabled_file_bool(struct file *file,
        return count;
 }
 
-static struct file_operations fops_kp = {
+static const struct file_operations fops_kp = {
        .read =         read_enabled_file_bool,
        .write =        write_enabled_file_bool,
 };