aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ftrace.h2
-rw-r--r--include/linux/init.h2
-rw-r--r--kernel/module.c12
-rw-r--r--kernel/trace/ftrace.c32
4 files changed, 41 insertions, 7 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 4936489f9ed8..6b232a2460c0 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -165,10 +165,12 @@ ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { }
165#ifdef CONFIG_FTRACE_MCOUNT_RECORD 165#ifdef CONFIG_FTRACE_MCOUNT_RECORD
166extern void ftrace_init(void); 166extern void ftrace_init(void);
167extern void ftrace_init_module(unsigned long *start, unsigned long *end); 167extern void ftrace_init_module(unsigned long *start, unsigned long *end);
168extern void ftrace_release(void *start, unsigned long size);
168#else 169#else
169static inline void ftrace_init(void) { } 170static inline void ftrace_init(void) { }
170static inline void 171static inline void
171ftrace_init_module(unsigned long *start, unsigned long *end) { } 172ftrace_init_module(unsigned long *start, unsigned long *end) { }
173static inline void ftrace_release(void *start, unsigned long size) { }
172#endif 174#endif
173 175
174#endif /* _LINUX_FTRACE_H */ 176#endif /* _LINUX_FTRACE_H */
diff --git a/include/linux/init.h b/include/linux/init.h
index 93538b696e3d..27f61f6b3cb9 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -40,7 +40,7 @@
40 40
41/* These are for everybody (although not all archs will actually 41/* These are for everybody (although not all archs will actually
42 discard it in modules) */ 42 discard it in modules) */
43#define __init __section(.init.text) __cold 43#define __init __section(.init.text) __cold notrace
44#define __initdata __section(.init.data) 44#define __initdata __section(.init.data)
45#define __initconst __section(.init.rodata) 45#define __initconst __section(.init.rodata)
46#define __exitdata __section(.exit.data) 46#define __exitdata __section(.exit.data)
diff --git a/kernel/module.c b/kernel/module.c
index d753fd9d83ec..7576c2d9462f 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1431,6 +1431,9 @@ static void free_module(struct module *mod)
1431 /* Module unload stuff */ 1431 /* Module unload stuff */
1432 module_unload_free(mod); 1432 module_unload_free(mod);
1433 1433
1434 /* release any pointers to mcount in this module */
1435 ftrace_release(mod->module_core, mod->core_size);
1436
1434 /* This may be NULL, but that's OK */ 1437 /* This may be NULL, but that's OK */
1435 module_free(mod, mod->module_init); 1438 module_free(mod, mod->module_init);
1436 kfree(mod->args); 1439 kfree(mod->args);
@@ -1839,6 +1842,7 @@ static noinline struct module *load_module(void __user *umod,
1839 struct module *mod; 1842 struct module *mod;
1840 long err = 0; 1843 long err = 0;
1841 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 1844 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
1845 void *mseg;
1842 struct exception_table_entry *extable; 1846 struct exception_table_entry *extable;
1843 mm_segment_t old_fs; 1847 mm_segment_t old_fs;
1844 1848
@@ -2190,10 +2194,9 @@ static noinline struct module *load_module(void __user *umod,
2190#endif 2194#endif
2191 } 2195 }
2192 2196
2193 if (mcountindex) { 2197 /* sechdrs[0].sh_size is always zero */
2194 void *mseg = (void *)sechdrs[mcountindex].sh_addr; 2198 mseg = (void *)sechdrs[mcountindex].sh_addr;
2195 ftrace_init_module(mseg, mseg + sechdrs[mcountindex].sh_size); 2199 ftrace_init_module(mseg, mseg + sechdrs[mcountindex].sh_size);
2196 }
2197 2200
2198 err = module_finalize(hdr, sechdrs, mod); 2201 err = module_finalize(hdr, sechdrs, mod);
2199 if (err < 0) 2202 if (err < 0)
@@ -2264,6 +2267,7 @@ static noinline struct module *load_module(void __user *umod,
2264 cleanup: 2267 cleanup:
2265 kobject_del(&mod->mkobj.kobj); 2268 kobject_del(&mod->mkobj.kobj);
2266 kobject_put(&mod->mkobj.kobj); 2269 kobject_put(&mod->mkobj.kobj);
2270 ftrace_release(mod->module_core, mod->core_size);
2267 free_unload: 2271 free_unload:
2268 module_unload_free(mod); 2272 module_unload_free(mod);
2269 module_free(mod, mod->module_init); 2273 module_free(mod, mod->module_init);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 8affb6d00ec1..eadd0eaea9b6 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -294,13 +294,37 @@ static inline void ftrace_del_hash(struct dyn_ftrace *node)
294 294
295static void ftrace_free_rec(struct dyn_ftrace *rec) 295static void ftrace_free_rec(struct dyn_ftrace *rec)
296{ 296{
297 /* no locking, only called from kstop_machine */
298
299 rec->ip = (unsigned long)ftrace_free_records; 297 rec->ip = (unsigned long)ftrace_free_records;
300 ftrace_free_records = rec; 298 ftrace_free_records = rec;
301 rec->flags |= FTRACE_FL_FREE; 299 rec->flags |= FTRACE_FL_FREE;
302} 300}
303 301
302void ftrace_release(void *start, unsigned long size)
303{
304 struct dyn_ftrace *rec;
305 struct ftrace_page *pg;
306 unsigned long s = (unsigned long)start;
307 unsigned long e = s + size;
308 int i;
309
310 if (!start)
311 return;
312
313 /* No interrupt should call this */
314 spin_lock(&ftrace_lock);
315
316 for (pg = ftrace_pages_start; pg; pg = pg->next) {
317 for (i = 0; i < pg->index; i++) {
318 rec = &pg->records[i];
319
320 if ((rec->ip >= s) && (rec->ip < e))
321 ftrace_free_rec(rec);
322 }
323 }
324 spin_unlock(&ftrace_lock);
325
326}
327
304static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip) 328static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
305{ 329{
306 struct dyn_ftrace *rec; 330 struct dyn_ftrace *rec;
@@ -1527,7 +1551,9 @@ static int ftrace_convert_nops(unsigned long *start,
1527 p = start; 1551 p = start;
1528 while (p < end) { 1552 while (p < end) {
1529 addr = ftrace_call_adjust(*p++); 1553 addr = ftrace_call_adjust(*p++);
1554 spin_lock(&ftrace_lock);
1530 ftrace_record_ip(addr); 1555 ftrace_record_ip(addr);
1556 spin_unlock(&ftrace_lock);
1531 ftrace_shutdown_replenish(); 1557 ftrace_shutdown_replenish();
1532 } 1558 }
1533 1559
@@ -1541,6 +1567,8 @@ static int ftrace_convert_nops(unsigned long *start,
1541 1567
1542void ftrace_init_module(unsigned long *start, unsigned long *end) 1568void ftrace_init_module(unsigned long *start, unsigned long *end)
1543{ 1569{
1570 if (start == end)
1571 return;
1544 ftrace_convert_nops(start, end); 1572 ftrace_convert_nops(start, end);
1545} 1573}
1546 1574