Skip to content

Commit 42c269c

Browse files
committed
ftrace: Allow for function tracing to record init functions on boot up
Adding a hook into free_reserve_area() that informs ftrace that boot up init text is being free, lets ftrace safely remove those init functions from its records, which keeps ftrace from trying to modify text that no longer exists. Note, this still does not allow for tracing .init text of modules, as modules require different work for freeing its init code. Link: http://lkml.kernel.org/r/[email protected] Cc: [email protected] Cc: Vlastimil Babka <[email protected]> Cc: Mel Gorman <[email protected]> Cc: Peter Zijlstra <[email protected]> Requested-by: Todd Brandt <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent dbeafd0 commit 42c269c

File tree

6 files changed

+58
-1
lines changed

6 files changed

+58
-1
lines changed

include/linux/ftrace.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ struct ftrace_ops_hash {
146146
struct ftrace_hash *filter_hash;
147147
struct mutex regex_lock;
148148
};
149+
150+
void ftrace_free_mem(void *start, void *end);
151+
#else
152+
static inline void ftrace_free_mem(void *start, void *end) { }
149153
#endif
150154

151155
/*
@@ -262,6 +266,7 @@ static inline int ftrace_nr_registered_ops(void)
262266
}
263267
static inline void clear_ftrace_function(void) { }
264268
static inline void ftrace_kill(void) { }
269+
static inline void ftrace_free_mem(void *start, void *end) { }
265270
#endif /* CONFIG_FUNCTION_TRACER */
266271

267272
#ifdef CONFIG_STACK_TRACER

include/linux/init.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
/* These are for everybody (although not all archs will actually
4141
discard it in modules) */
42-
#define __init __section(.init.text) __cold notrace __latent_entropy
42+
#define __init __section(.init.text) __cold __inittrace __latent_entropy
4343
#define __initdata __section(.init.data)
4444
#define __initconst __section(.init.rodata)
4545
#define __exitdata __section(.exit.data)
@@ -68,8 +68,10 @@
6868

6969
#ifdef MODULE
7070
#define __exitused
71+
#define __inittrace notrace
7172
#else
7273
#define __exitused __used
74+
#define __inittrace
7375
#endif
7476

7577
#define __exit __section(.exit.text) __exitused __cold notrace

kernel/trace/ftrace.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5262,6 +5262,50 @@ void ftrace_module_init(struct module *mod)
52625262
}
52635263
#endif /* CONFIG_MODULES */
52645264

5265+
void ftrace_free_mem(void *start_ptr, void *end_ptr)
5266+
{
5267+
unsigned long start = (unsigned long)start_ptr;
5268+
unsigned long end = (unsigned long)end_ptr;
5269+
struct ftrace_page **last_pg = &ftrace_pages_start;
5270+
struct ftrace_page *pg;
5271+
struct dyn_ftrace *rec;
5272+
struct dyn_ftrace key;
5273+
int order;
5274+
5275+
key.ip = start;
5276+
key.flags = end; /* overload flags, as it is unsigned long */
5277+
5278+
mutex_lock(&ftrace_lock);
5279+
5280+
for (pg = ftrace_pages_start; pg; last_pg = &pg->next, pg = *last_pg) {
5281+
if (end < pg->records[0].ip ||
5282+
start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE))
5283+
continue;
5284+
again:
5285+
rec = bsearch(&key, pg->records, pg->index,
5286+
sizeof(struct dyn_ftrace),
5287+
ftrace_cmp_recs);
5288+
if (!rec)
5289+
continue;
5290+
pg->index--;
5291+
if (!pg->index) {
5292+
*last_pg = pg->next;
5293+
order = get_count_order(pg->size / ENTRIES_PER_PAGE);
5294+
free_pages((unsigned long)pg->records, order);
5295+
kfree(pg);
5296+
pg = container_of(last_pg, struct ftrace_page, next);
5297+
if (!(*last_pg))
5298+
ftrace_pages = pg;
5299+
continue;
5300+
}
5301+
memmove(rec, rec + 1,
5302+
(pg->index - (rec - pg->records)) * sizeof(*rec));
5303+
/* More than one function may be in this block */
5304+
goto again;
5305+
}
5306+
mutex_unlock(&ftrace_lock);
5307+
}
5308+
52655309
void __init ftrace_init(void)
52665310
{
52675311
extern unsigned long __start_mcount_loc[];

mm/page_alloc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include <linux/page_owner.h>
6666
#include <linux/kthread.h>
6767
#include <linux/memcontrol.h>
68+
#include <linux/ftrace.h>
6869

6970
#include <asm/sections.h>
7071
#include <asm/tlbflush.h>
@@ -6605,6 +6606,9 @@ unsigned long free_reserved_area(void *start, void *end, int poison, char *s)
66056606
void *pos;
66066607
unsigned long pages = 0;
66076608

6609+
/* This may be .init text, inform ftrace to remove it */
6610+
ftrace_free_mem(start, end);
6611+
66086612
start = (void *)PAGE_ALIGN((unsigned long)start);
66096613
end = (void *)((unsigned long)end & PAGE_MASK);
66106614
for (pos = start; pos < end; pos += PAGE_SIZE, pages++) {

scripts/recordmcount.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ static int
412412
is_mcounted_section_name(char const *const txtname)
413413
{
414414
return strcmp(".text", txtname) == 0 ||
415+
strcmp(".init.text", txtname) == 0 ||
415416
strcmp(".ref.text", txtname) == 0 ||
416417
strcmp(".sched.text", txtname) == 0 ||
417418
strcmp(".spinlock.text", txtname) == 0 ||

scripts/recordmcount.pl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@
130130
# Acceptable sections to record.
131131
my %text_sections = (
132132
".text" => 1,
133+
".init.text" => 1,
133134
".ref.text" => 1,
134135
".sched.text" => 1,
135136
".spinlock.text" => 1,

0 commit comments

Comments
 (0)