aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/alternative.h5
-rw-r--r--arch/x86/kernel/alternative.c16
-rw-r--r--include/linux/ftrace.h6
-rw-r--r--kernel/trace/ftrace.c15
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);
66extern void alternatives_smp_module_del(struct module *mod); 66extern void alternatives_smp_module_del(struct module *mod);
67extern void alternatives_smp_switch(int smp); 67extern void alternatives_smp_switch(int smp);
68extern int alternatives_text_reserved(void *start, void *end);
68#else 69#else
69static inline void alternatives_smp_module_add(struct module *mod, char *name, 70static 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) {}
72static inline void alternatives_smp_module_del(struct module *mod) {} 73static inline void alternatives_smp_module_del(struct module *mod) {}
73static inline void alternatives_smp_switch(int smp) {} 74static inline void alternatives_smp_switch(int smp) {}
75static 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 */
394int 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
134unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops); 134unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops);
135extern void unregister_ftrace_function_probe_all(char *glob); 135extern void unregister_ftrace_function_probe_all(char *glob);
136 136
137extern int ftrace_text_reserved(void *start, void *end);
138
137enum { 139enum {
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}
255static 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 */
1029int 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
1028static int 1043static int
1029__ftrace_replace_code(struct dyn_ftrace *rec, int enable) 1044__ftrace_replace_code(struct dyn_ftrace *rec, int enable)
1030{ 1045{