]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/trace/ftrace.c
Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds
[linux-2.6-omap-h63xx.git] / kernel / trace / ftrace.c
index 43665add980586d13f30559f406e0a8c006951dc..4dda4f60a2a9262770e3195b894e48b8178296a3 100644 (file)
@@ -161,14 +161,23 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
  * not recorded via the compilation.
  */
 static DEFINE_SPINLOCK(ftrace_hash_lock);
-#define ftrace_hash_lock(flags)          spin_lock_irqsave(ftrace_hash_lock, flags)
-#define ftrace_hash_unlock(flags) spin_lock_irqsave(ftrace_hash_lock, flags)
+#define ftrace_hash_lock(flags)          spin_lock_irqsave(&ftrace_hash_lock, flags)
+#define ftrace_hash_unlock(flags) \
+                       spin_unlock_irqrestore(&ftrace_hash_lock, flags)
 #else
 /* This is protected via the ftrace_lock with MCOUNT_RECORD. */
-#define ftrace_hash_lock(flags)   do { (void)flags; } while (0)
+#define ftrace_hash_lock(flags)   do { (void)(flags); } while (0)
 #define ftrace_hash_unlock(flags) do { } while(0)
 #endif
 
+/*
+ * Since MCOUNT_ADDR may point to mcount itself, we do not want
+ * to get it confused by reading a reference in the code as we
+ * are parsing on objcopy output of text. Use a variable for
+ * it instead.
+ */
+static unsigned long mcount_addr = MCOUNT_ADDR;
+
 static struct task_struct *ftraced_task;
 
 enum {
@@ -567,6 +576,16 @@ static void ftrace_shutdown_replenish(void)
        ftrace_pages->next = (void *)get_zeroed_page(GFP_KERNEL);
 }
 
+static void print_ip_ins(const char *fmt, unsigned char *p)
+{
+       int i;
+
+       printk(KERN_CONT "%s", fmt);
+
+       for (i = 0; i < MCOUNT_INSN_SIZE; i++)
+               printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
+}
+
 static int
 ftrace_code_disable(struct dyn_ftrace *rec)
 {
@@ -577,10 +596,27 @@ ftrace_code_disable(struct dyn_ftrace *rec)
        ip = rec->ip;
 
        nop = ftrace_nop_replace();
-       call = ftrace_call_replace(ip, MCOUNT_ADDR);
+       call = ftrace_call_replace(ip, mcount_addr);
 
        failed = ftrace_modify_code(ip, call, nop);
        if (failed) {
+               switch (failed) {
+               case 1:
+                       WARN_ON_ONCE(1);
+                       pr_info("ftrace faulted on modifying ");
+                       print_ip_sym(ip);
+                       break;
+               case 2:
+                       WARN_ON_ONCE(1);
+                       pr_info("ftrace failed to modify ");
+                       print_ip_sym(ip);
+                       print_ip_ins(" expected: ", call);
+                       print_ip_ins(" actual: ", (unsigned char *)ip);
+                       print_ip_ins(" replace: ", nop);
+                       printk(KERN_CONT "\n");
+                       break;
+               }
+
                rec->flags |= FTRACE_FL_FAILED;
                return 0;
        }