aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/asm-generic/vmlinux.lds.h8
-rw-r--r--include/linux/module.h2
-rw-r--r--include/linux/tracepoint.h35
-rw-r--r--kernel/module.c16
-rw-r--r--kernel/tracepoint.c31
5 files changed, 50 insertions, 42 deletions
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index f53708be95eb..57b1b6811b61 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -166,10 +166,8 @@
166 CPU_KEEP(exit.data) \ 166 CPU_KEEP(exit.data) \
167 MEM_KEEP(init.data) \ 167 MEM_KEEP(init.data) \
168 MEM_KEEP(exit.data) \ 168 MEM_KEEP(exit.data) \
169 . = ALIGN(32); \ 169 STRUCT_ALIGN(); \
170 VMLINUX_SYMBOL(__start___tracepoints) = .; \
171 *(__tracepoints) \ 170 *(__tracepoints) \
172 VMLINUX_SYMBOL(__stop___tracepoints) = .; \
173 /* implement dynamic printk debug */ \ 171 /* implement dynamic printk debug */ \
174 . = ALIGN(8); \ 172 . = ALIGN(8); \
175 VMLINUX_SYMBOL(__start___verbose) = .; \ 173 VMLINUX_SYMBOL(__start___verbose) = .; \
@@ -218,6 +216,10 @@
218 VMLINUX_SYMBOL(__start_rodata) = .; \ 216 VMLINUX_SYMBOL(__start_rodata) = .; \
219 *(.rodata) *(.rodata.*) \ 217 *(.rodata) *(.rodata.*) \
220 *(__vermagic) /* Kernel version magic */ \ 218 *(__vermagic) /* Kernel version magic */ \
219 . = ALIGN(8); \
220 VMLINUX_SYMBOL(__start___tracepoints_ptrs) = .; \
221 *(__tracepoints_ptrs) /* Tracepoints: pointer array */\
222 VMLINUX_SYMBOL(__stop___tracepoints_ptrs) = .; \
221 *(__markers_strings) /* Markers: strings */ \ 223 *(__markers_strings) /* Markers: strings */ \
222 *(__tracepoints_strings)/* Tracepoints: strings */ \ 224 *(__tracepoints_strings)/* Tracepoints: strings */ \
223 } \ 225 } \
diff --git a/include/linux/module.h b/include/linux/module.h
index 7695a303bb55..9bdf27c7615b 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -377,7 +377,7 @@ struct module
377 keeping pointers to this stuff */ 377 keeping pointers to this stuff */
378 char *args; 378 char *args;
379#ifdef CONFIG_TRACEPOINTS 379#ifdef CONFIG_TRACEPOINTS
380 struct tracepoint *tracepoints; 380 struct tracepoint * const *tracepoints_ptrs;
381 unsigned int num_tracepoints; 381 unsigned int num_tracepoints;
382#endif 382#endif
383#ifdef HAVE_JUMP_LABEL 383#ifdef HAVE_JUMP_LABEL
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index c6814616653b..97c84a58efb8 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -33,12 +33,7 @@ struct tracepoint {
33 void (*regfunc)(void); 33 void (*regfunc)(void);
34 void (*unregfunc)(void); 34 void (*unregfunc)(void);
35 struct tracepoint_func __rcu *funcs; 35 struct tracepoint_func __rcu *funcs;
36} __attribute__((aligned(32))); /* 36};
37 * Aligned on 32 bytes because it is
38 * globally visible and gcc happily
39 * align these on the structure size.
40 * Keep in sync with vmlinux.lds.h.
41 */
42 37
43/* 38/*
44 * Connect a probe to a tracepoint. 39 * Connect a probe to a tracepoint.
@@ -61,15 +56,15 @@ extern void tracepoint_probe_update_all(void);
61 56
62struct tracepoint_iter { 57struct tracepoint_iter {
63 struct module *module; 58 struct module *module;
64 struct tracepoint *tracepoint; 59 struct tracepoint * const *tracepoint;
65}; 60};
66 61
67extern void tracepoint_iter_start(struct tracepoint_iter *iter); 62extern void tracepoint_iter_start(struct tracepoint_iter *iter);
68extern void tracepoint_iter_next(struct tracepoint_iter *iter); 63extern void tracepoint_iter_next(struct tracepoint_iter *iter);
69extern void tracepoint_iter_stop(struct tracepoint_iter *iter); 64extern void tracepoint_iter_stop(struct tracepoint_iter *iter);
70extern void tracepoint_iter_reset(struct tracepoint_iter *iter); 65extern void tracepoint_iter_reset(struct tracepoint_iter *iter);
71extern int tracepoint_get_iter_range(struct tracepoint **tracepoint, 66extern int tracepoint_get_iter_range(struct tracepoint * const **tracepoint,
72 struct tracepoint *begin, struct tracepoint *end); 67 struct tracepoint * const *begin, struct tracepoint * const *end);
73 68
74/* 69/*
75 * tracepoint_synchronize_unregister must be called between the last tracepoint 70 * tracepoint_synchronize_unregister must be called between the last tracepoint
@@ -84,11 +79,13 @@ static inline void tracepoint_synchronize_unregister(void)
84#define PARAMS(args...) args 79#define PARAMS(args...) args
85 80
86#ifdef CONFIG_TRACEPOINTS 81#ifdef CONFIG_TRACEPOINTS
87extern void tracepoint_update_probe_range(struct tracepoint *begin, 82extern
88 struct tracepoint *end); 83void tracepoint_update_probe_range(struct tracepoint * const *begin,
84 struct tracepoint * const *end);
89#else 85#else
90static inline void tracepoint_update_probe_range(struct tracepoint *begin, 86static inline
91 struct tracepoint *end) 87void tracepoint_update_probe_range(struct tracepoint * const *begin,
88 struct tracepoint * const *end)
92{ } 89{ }
93#endif /* CONFIG_TRACEPOINTS */ 90#endif /* CONFIG_TRACEPOINTS */
94 91
@@ -174,12 +171,20 @@ do_trace: \
174 { \ 171 { \
175 } 172 }
176 173
174/*
175 * We have no guarantee that gcc and the linker won't up-align the tracepoint
176 * structures, so we create an array of pointers that will be used for iteration
177 * on the tracepoints.
178 */
177#define DEFINE_TRACE_FN(name, reg, unreg) \ 179#define DEFINE_TRACE_FN(name, reg, unreg) \
178 static const char __tpstrtab_##name[] \ 180 static const char __tpstrtab_##name[] \
179 __attribute__((section("__tracepoints_strings"))) = #name; \ 181 __attribute__((section("__tracepoints_strings"))) = #name; \
180 struct tracepoint __tracepoint_##name \ 182 struct tracepoint __tracepoint_##name \
181 __attribute__((section("__tracepoints"), aligned(32))) = \ 183 __attribute__((section("__tracepoints"))) = \
182 { __tpstrtab_##name, 0, reg, unreg, NULL } 184 { __tpstrtab_##name, 0, reg, unreg, NULL }; \
185 static struct tracepoint * const __tracepoint_ptr_##name __used \
186 __attribute__((section("__tracepoints_ptrs"))) = \
187 &__tracepoint_##name;
183 188
184#define DEFINE_TRACE(name) \ 189#define DEFINE_TRACE(name) \
185 DEFINE_TRACE_FN(name, NULL, NULL); 190 DEFINE_TRACE_FN(name, NULL, NULL);
diff --git a/kernel/module.c b/kernel/module.c
index 34e00b708fad..efa290ea94bf 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2460,9 +2460,9 @@ static void find_module_sections(struct module *mod, struct load_info *info)
2460#endif 2460#endif
2461 2461
2462#ifdef CONFIG_TRACEPOINTS 2462#ifdef CONFIG_TRACEPOINTS
2463 mod->tracepoints = section_objs(info, "__tracepoints", 2463 mod->tracepoints_ptrs = section_objs(info, "__tracepoints_ptrs",
2464 sizeof(*mod->tracepoints), 2464 sizeof(*mod->tracepoints_ptrs),
2465 &mod->num_tracepoints); 2465 &mod->num_tracepoints);
2466#endif 2466#endif
2467#ifdef HAVE_JUMP_LABEL 2467#ifdef HAVE_JUMP_LABEL
2468 mod->jump_entries = section_objs(info, "__jump_table", 2468 mod->jump_entries = section_objs(info, "__jump_table",
@@ -3393,7 +3393,7 @@ void module_layout(struct module *mod,
3393 struct modversion_info *ver, 3393 struct modversion_info *ver,
3394 struct kernel_param *kp, 3394 struct kernel_param *kp,
3395 struct kernel_symbol *ks, 3395 struct kernel_symbol *ks,
3396 struct tracepoint *tp) 3396 struct tracepoint * const *tp)
3397{ 3397{
3398} 3398}
3399EXPORT_SYMBOL(module_layout); 3399EXPORT_SYMBOL(module_layout);
@@ -3407,8 +3407,8 @@ void module_update_tracepoints(void)
3407 mutex_lock(&module_mutex); 3407 mutex_lock(&module_mutex);
3408 list_for_each_entry(mod, &modules, list) 3408 list_for_each_entry(mod, &modules, list)
3409 if (!mod->taints) 3409 if (!mod->taints)
3410 tracepoint_update_probe_range(mod->tracepoints, 3410 tracepoint_update_probe_range(mod->tracepoints_ptrs,
3411 mod->tracepoints + mod->num_tracepoints); 3411 mod->tracepoints_ptrs + mod->num_tracepoints);
3412 mutex_unlock(&module_mutex); 3412 mutex_unlock(&module_mutex);
3413} 3413}
3414 3414
@@ -3432,8 +3432,8 @@ int module_get_iter_tracepoints(struct tracepoint_iter *iter)
3432 else if (iter_mod > iter->module) 3432 else if (iter_mod > iter->module)
3433 iter->tracepoint = NULL; 3433 iter->tracepoint = NULL;
3434 found = tracepoint_get_iter_range(&iter->tracepoint, 3434 found = tracepoint_get_iter_range(&iter->tracepoint,
3435 iter_mod->tracepoints, 3435 iter_mod->tracepoints_ptrs,
3436 iter_mod->tracepoints 3436 iter_mod->tracepoints_ptrs
3437 + iter_mod->num_tracepoints); 3437 + iter_mod->num_tracepoints);
3438 if (found) { 3438 if (found) {
3439 iter->module = iter_mod; 3439 iter->module = iter_mod;
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index e95ee7f31d43..68187af4889e 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -27,8 +27,8 @@
27#include <linux/sched.h> 27#include <linux/sched.h>
28#include <linux/jump_label.h> 28#include <linux/jump_label.h>
29 29
30extern struct tracepoint __start___tracepoints[]; 30extern struct tracepoint * const __start___tracepoints_ptrs[];
31extern struct tracepoint __stop___tracepoints[]; 31extern struct tracepoint * const __stop___tracepoints_ptrs[];
32 32
33/* Set to 1 to enable tracepoint debug output */ 33/* Set to 1 to enable tracepoint debug output */
34static const int tracepoint_debug; 34static const int tracepoint_debug;
@@ -298,10 +298,10 @@ static void disable_tracepoint(struct tracepoint *elem)
298 * 298 *
299 * Updates the probe callback corresponding to a range of tracepoints. 299 * Updates the probe callback corresponding to a range of tracepoints.
300 */ 300 */
301void 301void tracepoint_update_probe_range(struct tracepoint * const *begin,
302tracepoint_update_probe_range(struct tracepoint *begin, struct tracepoint *end) 302 struct tracepoint * const *end)
303{ 303{
304 struct tracepoint *iter; 304 struct tracepoint * const *iter;
305 struct tracepoint_entry *mark_entry; 305 struct tracepoint_entry *mark_entry;
306 306
307 if (!begin) 307 if (!begin)
@@ -309,12 +309,12 @@ tracepoint_update_probe_range(struct tracepoint *begin, struct tracepoint *end)
309 309
310 mutex_lock(&tracepoints_mutex); 310 mutex_lock(&tracepoints_mutex);
311 for (iter = begin; iter < end; iter++) { 311 for (iter = begin; iter < end; iter++) {
312 mark_entry = get_tracepoint(iter->name); 312 mark_entry = get_tracepoint((*iter)->name);
313 if (mark_entry) { 313 if (mark_entry) {
314 set_tracepoint(&mark_entry, iter, 314 set_tracepoint(&mark_entry, *iter,
315 !!mark_entry->refcount); 315 !!mark_entry->refcount);
316 } else { 316 } else {
317 disable_tracepoint(iter); 317 disable_tracepoint(*iter);
318 } 318 }
319 } 319 }
320 mutex_unlock(&tracepoints_mutex); 320 mutex_unlock(&tracepoints_mutex);
@@ -326,8 +326,8 @@ tracepoint_update_probe_range(struct tracepoint *begin, struct tracepoint *end)
326static void tracepoint_update_probes(void) 326static void tracepoint_update_probes(void)
327{ 327{
328 /* Core kernel tracepoints */ 328 /* Core kernel tracepoints */
329 tracepoint_update_probe_range(__start___tracepoints, 329 tracepoint_update_probe_range(__start___tracepoints_ptrs,
330 __stop___tracepoints); 330 __stop___tracepoints_ptrs);
331 /* tracepoints in modules. */ 331 /* tracepoints in modules. */
332 module_update_tracepoints(); 332 module_update_tracepoints();
333} 333}
@@ -514,8 +514,8 @@ EXPORT_SYMBOL_GPL(tracepoint_probe_update_all);
514 * Will return the first tracepoint in the range if the input tracepoint is 514 * Will return the first tracepoint in the range if the input tracepoint is
515 * NULL. 515 * NULL.
516 */ 516 */
517int tracepoint_get_iter_range(struct tracepoint **tracepoint, 517int tracepoint_get_iter_range(struct tracepoint * const **tracepoint,
518 struct tracepoint *begin, struct tracepoint *end) 518 struct tracepoint * const *begin, struct tracepoint * const *end)
519{ 519{
520 if (!*tracepoint && begin != end) { 520 if (!*tracepoint && begin != end) {
521 *tracepoint = begin; 521 *tracepoint = begin;
@@ -534,7 +534,8 @@ static void tracepoint_get_iter(struct tracepoint_iter *iter)
534 /* Core kernel tracepoints */ 534 /* Core kernel tracepoints */
535 if (!iter->module) { 535 if (!iter->module) {
536 found = tracepoint_get_iter_range(&iter->tracepoint, 536 found = tracepoint_get_iter_range(&iter->tracepoint,
537 __start___tracepoints, __stop___tracepoints); 537 __start___tracepoints_ptrs,
538 __stop___tracepoints_ptrs);
538 if (found) 539 if (found)
539 goto end; 540 goto end;
540 } 541 }
@@ -585,8 +586,8 @@ int tracepoint_module_notify(struct notifier_block *self,
585 switch (val) { 586 switch (val) {
586 case MODULE_STATE_COMING: 587 case MODULE_STATE_COMING:
587 case MODULE_STATE_GOING: 588 case MODULE_STATE_GOING:
588 tracepoint_update_probe_range(mod->tracepoints, 589 tracepoint_update_probe_range(mod->tracepoints_ptrs,
589 mod->tracepoints + mod->num_tracepoints); 590 mod->tracepoints_ptrs + mod->num_tracepoints);
590 break; 591 break;
591 } 592 }
592 return 0; 593 return 0;