diff options
-rw-r--r-- | arch/x86/include/asm/alternative.h | 5 | ||||
-rw-r--r-- | arch/x86/kernel/alternative.c | 16 | ||||
-rw-r--r-- | include/linux/ftrace.h | 6 | ||||
-rw-r--r-- | kernel/trace/ftrace.c | 15 |
4 files changed, 42 insertions, 0 deletions
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 69b74a7b877f..ac80b7d70014 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h | |||
@@ -65,12 +65,17 @@ extern void alternatives_smp_module_add(struct module *mod, char *name, | |||
65 | void *text, void *text_end); | 65 | void *text, void *text_end); |
66 | extern void alternatives_smp_module_del(struct module *mod); | 66 | extern void alternatives_smp_module_del(struct module *mod); |
67 | extern void alternatives_smp_switch(int smp); | 67 | extern void alternatives_smp_switch(int smp); |
68 | extern int alternatives_text_reserved(void *start, void *end); | ||
68 | #else | 69 | #else |
69 | static inline void alternatives_smp_module_add(struct module *mod, char *name, | 70 | static inline void alternatives_smp_module_add(struct module *mod, char *name, |
70 | void *locks, void *locks_end, | 71 | void *locks, void *locks_end, |
71 | void *text, void *text_end) {} | 72 | void *text, void *text_end) {} |
72 | static inline void alternatives_smp_module_del(struct module *mod) {} | 73 | static inline void alternatives_smp_module_del(struct module *mod) {} |
73 | static inline void alternatives_smp_switch(int smp) {} | 74 | static inline void alternatives_smp_switch(int smp) {} |
75 | static inline int alternatives_text_reserved(void *start, void *end) | ||
76 | { | ||
77 | return 0; | ||
78 | } | ||
74 | #endif /* CONFIG_SMP */ | 79 | #endif /* CONFIG_SMP */ |
75 | 80 | ||
76 | /* alternative assembly primitive: */ | 81 | /* alternative assembly primitive: */ |
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index de7353c0ce9c..3c13284ff86d 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -390,6 +390,22 @@ void alternatives_smp_switch(int smp) | |||
390 | mutex_unlock(&smp_alt); | 390 | mutex_unlock(&smp_alt); |
391 | } | 391 | } |
392 | 392 | ||
393 | /* Return 1 if the address range is reserved for smp-alternatives */ | ||
394 | int alternatives_text_reserved(void *start, void *end) | ||
395 | { | ||
396 | struct smp_alt_module *mod; | ||
397 | u8 **ptr; | ||
398 | |||
399 | list_for_each_entry(mod, &smp_alt_modules, next) { | ||
400 | if (mod->text > end || mod->text_end < start) | ||
401 | continue; | ||
402 | for (ptr = mod->locks; ptr < mod->locks_end; ptr++) | ||
403 | if (start <= *ptr && end >= *ptr) | ||
404 | return 1; | ||
405 | } | ||
406 | |||
407 | return 0; | ||
408 | } | ||
393 | #endif | 409 | #endif |
394 | 410 | ||
395 | #ifdef CONFIG_PARAVIRT | 411 | #ifdef CONFIG_PARAVIRT |
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 0b4f97d24d7f..9d127efed43c 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
@@ -134,6 +134,8 @@ extern void | |||
134 | unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops); | 134 | unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops); |
135 | extern void unregister_ftrace_function_probe_all(char *glob); | 135 | extern void unregister_ftrace_function_probe_all(char *glob); |
136 | 136 | ||
137 | extern int ftrace_text_reserved(void *start, void *end); | ||
138 | |||
137 | enum { | 139 | enum { |
138 | FTRACE_FL_FREE = (1 << 0), | 140 | FTRACE_FL_FREE = (1 << 0), |
139 | FTRACE_FL_FAILED = (1 << 1), | 141 | FTRACE_FL_FAILED = (1 << 1), |
@@ -250,6 +252,10 @@ static inline int unregister_ftrace_command(char *cmd_name) | |||
250 | { | 252 | { |
251 | return -EINVAL; | 253 | return -EINVAL; |
252 | } | 254 | } |
255 | static inline int ftrace_text_reserved(void *start, void *end) | ||
256 | { | ||
257 | return 0; | ||
258 | } | ||
253 | #endif /* CONFIG_DYNAMIC_FTRACE */ | 259 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
254 | 260 | ||
255 | /* totally disable ftrace - can not re-enable after this */ | 261 | /* totally disable ftrace - can not re-enable after this */ |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 1e6640f80454..3d90661a5f40 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -1025,6 +1025,21 @@ static void ftrace_bug(int failed, unsigned long ip) | |||
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | 1027 | ||
1028 | /* Return 1 if the address range is reserved for ftrace */ | ||
1029 | int ftrace_text_reserved(void *start, void *end) | ||
1030 | { | ||
1031 | struct dyn_ftrace *rec; | ||
1032 | struct ftrace_page *pg; | ||
1033 | |||
1034 | do_for_each_ftrace_rec(pg, rec) { | ||
1035 | if (rec->ip <= (unsigned long)end && | ||
1036 | rec->ip + MCOUNT_INSN_SIZE > (unsigned long)start) | ||
1037 | return 1; | ||
1038 | } while_for_each_ftrace_rec(); | ||
1039 | return 0; | ||
1040 | } | ||
1041 | |||
1042 | |||
1028 | static int | 1043 | static int |
1029 | __ftrace_replace_code(struct dyn_ftrace *rec, int enable) | 1044 | __ftrace_replace_code(struct dyn_ftrace *rec, int enable) |
1030 | { | 1045 | { |