Skip to content

Commit 2cfa197

Browse files
Masami HiramatsuIngo Molnar
authored andcommitted
ftrace/alternatives: Introducing *_text_reserved functions
Introducing *_text_reserved functions for checking the text address range is partially reserved or not. This patch provides checking routines for x86 smp alternatives and dynamic ftrace. Since both functions modify fixed pieces of kernel text, they should reserve and protect those from other dynamic text modifier, like kprobes. This will also be extended when introducing other subsystems which modify fixed pieces of kernel text. Dynamic text modifiers should avoid those. Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: systemtap <systemtap@sources.redhat.com> Cc: DLE <dle-develop@lists.sourceforge.net> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: przemyslaw@pawelczyk.it Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: Mathieu Desnoyers <compudj@krystal.dyndns.org> Cc: Jason Baron <jbaron@redhat.com> LKML-Reference: <20100202214911.4694.16587.stgit@dhcp-100-2-132.bos.redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
1 parent 615d0eb commit 2cfa197

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

arch/x86/include/asm/alternative.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,17 @@ extern void alternatives_smp_module_add(struct module *mod, char *name,
6565
void *text, void *text_end);
6666
extern void alternatives_smp_module_del(struct module *mod);
6767
extern void alternatives_smp_switch(int smp);
68+
extern int alternatives_text_reserved(void *start, void *end);
6869
#else
6970
static inline void alternatives_smp_module_add(struct module *mod, char *name,
7071
void *locks, void *locks_end,
7172
void *text, void *text_end) {}
7273
static inline void alternatives_smp_module_del(struct module *mod) {}
7374
static inline void alternatives_smp_switch(int smp) {}
75+
static inline int alternatives_text_reserved(void *start, void *end)
76+
{
77+
return 0;
78+
}
7479
#endif /* CONFIG_SMP */
7580

7681
/* alternative assembly primitive: */

arch/x86/kernel/alternative.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,22 @@ void alternatives_smp_switch(int smp)
390390
mutex_unlock(&smp_alt);
391391
}
392392

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+
}
393409
#endif
394410

395411
#ifdef CONFIG_PARAVIRT

include/linux/ftrace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ extern void
134134
unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops);
135135
extern void unregister_ftrace_function_probe_all(char *glob);
136136

137+
extern int ftrace_text_reserved(void *start, void *end);
138+
137139
enum {
138140
FTRACE_FL_FREE = (1 << 0),
139141
FTRACE_FL_FAILED = (1 << 1),
@@ -250,6 +252,10 @@ static inline int unregister_ftrace_command(char *cmd_name)
250252
{
251253
return -EINVAL;
252254
}
255+
static inline int ftrace_text_reserved(void *start, void *end)
256+
{
257+
return 0;
258+
}
253259
#endif /* CONFIG_DYNAMIC_FTRACE */
254260

255261
/* totally disable ftrace - can not re-enable after this */

kernel/trace/ftrace.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,21 @@ static void ftrace_bug(int failed, unsigned long ip)
10251025
}
10261026

10271027

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+
10281043
static int
10291044
__ftrace_replace_code(struct dyn_ftrace *rec, int enable)
10301045
{

0 commit comments

Comments
 (0)