Skip to content

Commit b80f0f6

Browse files
committed
ftrace: Have init/main.c call ftrace directly to free init memory
Relying on free_reserved_area() to call ftrace to free init memory proved to not be sufficient. The issue is that on x86, when debug_pagealloc is enabled, the init memory is not freed, but simply set as not present. Since ftrace was uninformed of this, starting function tracing still tries to update pages that are not present according to the page tables, causing ftrace to bug, as well as killing the kernel itself. Instead of relying on free_reserved_area(), have init/main.c call ftrace directly just before it frees the init memory. Then it needs to use __init_begin and __init_end to know where the init memory location is. Looking at all archs (and testing what I can), it appears that this should work for each of them. Reported-by: kernel test robot <xiaolong.ye@intel.com> Reported-by: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
1 parent 5bd8462 commit b80f0f6

File tree

4 files changed

+8
-9
lines changed

4 files changed

+8
-9
lines changed

include/linux/ftrace.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ struct ftrace_ops_hash {
147147
struct mutex regex_lock;
148148
};
149149

150-
void ftrace_free_mem(void *start, void *end);
150+
void ftrace_free_init_mem(void);
151151
#else
152-
static inline void ftrace_free_mem(void *start, void *end) { }
152+
static inline void ftrace_free_init_mem(void) { }
153153
#endif
154154

155155
/*
@@ -266,7 +266,7 @@ static inline int ftrace_nr_registered_ops(void)
266266
}
267267
static inline void clear_ftrace_function(void) { }
268268
static inline void ftrace_kill(void) { }
269-
static inline void ftrace_free_mem(void *start, void *end) { }
269+
static inline void ftrace_free_init_mem(void) { }
270270
#endif /* CONFIG_FUNCTION_TRACER */
271271

272272
#ifdef CONFIG_STACK_TRACER

init/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,7 @@ static int __ref kernel_init(void *unused)
962962
kernel_init_freeable();
963963
/* need to finish all async __init code before freeing the memory */
964964
async_synchronize_full();
965+
ftrace_free_init_mem();
965966
free_initmem();
966967
mark_readonly();
967968
system_state = SYSTEM_RUNNING;

kernel/trace/ftrace.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
#include <trace/events/sched.h>
3838

39+
#include <asm/sections.h>
3940
#include <asm/setup.h>
4041

4142
#include "trace_output.h"
@@ -5279,10 +5280,10 @@ void ftrace_module_init(struct module *mod)
52795280
}
52805281
#endif /* CONFIG_MODULES */
52815282

5282-
void ftrace_free_mem(void *start_ptr, void *end_ptr)
5283+
void __init ftrace_free_init_mem(void)
52835284
{
5284-
unsigned long start = (unsigned long)start_ptr;
5285-
unsigned long end = (unsigned long)end_ptr;
5285+
unsigned long start = (unsigned long)(&__init_begin);
5286+
unsigned long end = (unsigned long)(&__init_end);
52865287
struct ftrace_page **last_pg = &ftrace_pages_start;
52875288
struct ftrace_page *pg;
52885289
struct dyn_ftrace *rec;

mm/page_alloc.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6606,9 +6606,6 @@ unsigned long free_reserved_area(void *start, void *end, int poison, char *s)
66066606
void *pos;
66076607
unsigned long pages = 0;
66086608

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

0 commit comments

Comments
 (0)