x86, k8: Fix build error when K8_NB is disabled
[safe/jmp/linux-2.6] / arch / x86 / kernel / ftrace.c
index 5a1b975..cd37469 100644 (file)
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 
+/*
+ * modifying_code is set to notify NMIs that they need to use
+ * memory barriers when entering or exiting. But we don't want
+ * to burden NMIs with unnecessary memory barriers when code
+ * modification is not being done (which is most of the time).
+ *
+ * A mutex is already held when ftrace_arch_code_modify_prepare
+ * and post_process are called. No locks need to be taken here.
+ *
+ * Stop machine will make sure currently running NMIs are done
+ * and new NMIs will see the updated variable before we need
+ * to worry about NMIs doing memory barriers.
+ */
+static int modifying_code __read_mostly;
+static DEFINE_PER_CPU(int, save_modifying_code);
+
 int ftrace_arch_code_modify_prepare(void)
 {
        set_kernel_text_rw();
+       modifying_code = 1;
        return 0;
 }
 
 int ftrace_arch_code_modify_post_process(void)
 {
+       modifying_code = 0;
        set_kernel_text_ro();
        return 0;
 }
@@ -149,6 +167,11 @@ static void ftrace_mod_code(void)
 
 void ftrace_nmi_enter(void)
 {
+       __get_cpu_var(save_modifying_code) = modifying_code;
+
+       if (!__get_cpu_var(save_modifying_code))
+               return;
+
        if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) {
                smp_rmb();
                ftrace_mod_code();
@@ -160,6 +183,9 @@ void ftrace_nmi_enter(void)
 
 void ftrace_nmi_exit(void)
 {
+       if (!__get_cpu_var(save_modifying_code))
+               return;
+
        /* Finish all executions before clearing nmi_running */
        smp_mb();
        atomic_dec(&nmi_running);
@@ -189,9 +215,26 @@ static void wait_for_nmi(void)
        nmi_wait_count++;
 }
 
+static inline int
+within(unsigned long addr, unsigned long start, unsigned long end)
+{
+       return addr >= start && addr < end;
+}
+
 static int
 do_ftrace_mod_code(unsigned long ip, void *new_code)
 {
+       /*
+        * On x86_64, kernel text mappings are mapped read-only with
+        * CONFIG_DEBUG_RODATA. So we use the kernel identity mapping instead
+        * of the kernel text mapping to modify the kernel text.
+        *
+        * For 32bit kernels, these mappings are same and we can use
+        * kernel identity mapping to modify code.
+        */
+       if (within(ip, (unsigned long)_text, (unsigned long)_etext))
+               ip = (unsigned long)__va(__pa(ip));
+
        mod_code_ip = (void *)ip;
        mod_code_newcode = new_code;
 
@@ -467,13 +510,3 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
        }
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-
-#ifdef CONFIG_FTRACE_SYSCALLS
-
-extern unsigned long *sys_call_table;
-
-unsigned long __init arch_syscall_addr(int nr)
-{
-       return (unsigned long)(&sys_call_table)[nr];
-}
-#endif