diff options
author | Steven Rostedt <srostedt@redhat.com> | 2008-05-12 15:20:43 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-23 14:33:47 -0400 |
commit | d61f82d06672f57fca410da6f7fffd15867db622 (patch) | |
tree | 62ef5573934eaa638c0d39a45d789691aecbd7d3 /arch/x86/kernel/entry_32.S | |
parent | 3c1720f00bb619302ba19d55986ab565e74d06db (diff) |
ftrace: use dynamic patching for updating mcount calls
This patch replaces the indirect call to the mcount function
pointer with a direct call that will be patched by the
dynamic ftrace routines.
On boot up, the mcount function calls the ftace_stub function.
When the dynamic ftrace code is initialized, the ftrace_stub
is replaced with a call to the ftrace_record_ip, which records
the instruction pointers of the locations that call it.
Later, the ftraced daemon will call kstop_machine and patch all
the locations to nops.
When a ftrace is enabled, the original calls to mcount will now
be set top call ftrace_caller, which will do a direct call
to the registered ftrace function. This direct call is also patched
when the function that should be called is updated.
All patching is performed by a kstop_machine routine to prevent any
type of race conditions that is associated with modifying code
on the fly.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/entry_32.S')
-rw-r--r-- | arch/x86/kernel/entry_32.S | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index f47b9b5440d2..e6517ce0b824 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -1110,10 +1110,50 @@ ENDPROC(xen_failsafe_callback) | |||
1110 | #endif /* CONFIG_XEN */ | 1110 | #endif /* CONFIG_XEN */ |
1111 | 1111 | ||
1112 | #ifdef CONFIG_FTRACE | 1112 | #ifdef CONFIG_FTRACE |
1113 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
1114 | |||
1115 | ENTRY(mcount) | ||
1116 | pushl %eax | ||
1117 | pushl %ecx | ||
1118 | pushl %edx | ||
1119 | movl 0xc(%esp), %eax | ||
1120 | |||
1121 | .globl mcount_call | ||
1122 | mcount_call: | ||
1123 | call ftrace_stub | ||
1124 | |||
1125 | popl %edx | ||
1126 | popl %ecx | ||
1127 | popl %eax | ||
1128 | |||
1129 | ret | ||
1130 | END(mcount) | ||
1131 | |||
1132 | ENTRY(ftrace_caller) | ||
1133 | pushl %eax | ||
1134 | pushl %ecx | ||
1135 | pushl %edx | ||
1136 | movl 0xc(%esp), %eax | ||
1137 | movl 0x4(%ebp), %edx | ||
1138 | |||
1139 | .globl ftrace_call | ||
1140 | ftrace_call: | ||
1141 | call ftrace_stub | ||
1142 | |||
1143 | popl %edx | ||
1144 | popl %ecx | ||
1145 | popl %eax | ||
1146 | |||
1147 | .globl ftrace_stub | ||
1148 | ftrace_stub: | ||
1149 | ret | ||
1150 | END(ftrace_caller) | ||
1151 | |||
1152 | #else /* ! CONFIG_DYNAMIC_FTRACE */ | ||
1153 | |||
1113 | ENTRY(mcount) | 1154 | ENTRY(mcount) |
1114 | cmpl $ftrace_stub, ftrace_trace_function | 1155 | cmpl $ftrace_stub, ftrace_trace_function |
1115 | jnz trace | 1156 | jnz trace |
1116 | |||
1117 | .globl ftrace_stub | 1157 | .globl ftrace_stub |
1118 | ftrace_stub: | 1158 | ftrace_stub: |
1119 | ret | 1159 | ret |
@@ -1126,7 +1166,7 @@ trace: | |||
1126 | movl 0xc(%esp), %eax | 1166 | movl 0xc(%esp), %eax |
1127 | movl 0x4(%ebp), %edx | 1167 | movl 0x4(%ebp), %edx |
1128 | 1168 | ||
1129 | call *ftrace_trace_function | 1169 | call *ftrace_trace_function |
1130 | 1170 | ||
1131 | popl %edx | 1171 | popl %edx |
1132 | popl %ecx | 1172 | popl %ecx |
@@ -1134,7 +1174,8 @@ trace: | |||
1134 | 1174 | ||
1135 | jmp ftrace_stub | 1175 | jmp ftrace_stub |
1136 | END(mcount) | 1176 | END(mcount) |
1137 | #endif | 1177 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
1178 | #endif /* CONFIG_FTRACE */ | ||
1138 | 1179 | ||
1139 | .section .rodata,"a" | 1180 | .section .rodata,"a" |
1140 | #include "syscall_table_32.S" | 1181 | #include "syscall_table_32.S" |