aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/ftrace.h
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2012-04-30 16:20:23 -0400
committerSteven Rostedt <rostedt@goodmis.org>2012-07-19 13:20:03 -0400
commit08f6fba503111e0336f2b4d6915a4a18f9b60e51 (patch)
tree119f971348614154552b70fb5cbe358f7c532a18 /include/linux/ftrace.h
parent28fb5dfa783c25dbeeb25a72663f8066a3a517f5 (diff)
ftrace/x86: Add separate function to save regs
Add a way to have different functions calling different trampolines. If a ftrace_ops wants regs saved on the return, then have only the functions with ops registered to save regs. Functions registered by other ops would not be affected, unless the functions overlap. If one ftrace_ops registered functions A, B and C and another ops registered fucntions to save regs on A, and D, then only functions A and D would be saving regs. Function B and C would work as normal. Although A is registered by both ops: normal and saves regs; this is fine as saving the regs is needed to satisfy one of the ops that calls it but the regs are ignored by the other ops function. x86_64 implements the full regs saving, and i386 just passes a NULL for regs to satisfy the ftrace_ops passing. Where an arch must supply both regs and ftrace_ops parameters, even if regs is just NULL. It is OK for an arch to pass NULL regs. All function trace users that require regs passing must add the flag FTRACE_OPS_FL_SAVE_REGS when registering the ftrace_ops. If the arch does not support saving regs then the ftrace_ops will fail to register. The flag FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED may be set that will prevent the ftrace_ops from failing to register. In this case, the handler may either check if regs is not NULL or check if ARCH_SUPPORTS_FTRACE_SAVE_REGS. If the arch supports passing regs it will set this macro and pass regs for ops that request them. All other archs will just pass NULL. Link: Link: http://lkml.kernel.org/r/20120711195745.107705970@goodmis.org Cc: Alexander van Heukelum <heukelum@fastmail.fm> Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'include/linux/ftrace.h')
-rw-r--r--include/linux/ftrace.h107
1 files changed, 100 insertions, 7 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index e4202881fb00..ab39990cc43f 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -71,12 +71,28 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip,
71 * could be controled by following calls: 71 * could be controled by following calls:
72 * ftrace_function_local_enable 72 * ftrace_function_local_enable
73 * ftrace_function_local_disable 73 * ftrace_function_local_disable
74 * SAVE_REGS - The ftrace_ops wants regs saved at each function called
75 * and passed to the callback. If this flag is set, but the
76 * architecture does not support passing regs
77 * (ARCH_SUPPORTS_FTRACE_SAVE_REGS is not defined), then the
78 * ftrace_ops will fail to register, unless the next flag
79 * is set.
80 * SAVE_REGS_IF_SUPPORTED - This is the same as SAVE_REGS, but if the
81 * handler can handle an arch that does not save regs
82 * (the handler tests if regs == NULL), then it can set
83 * this flag instead. It will not fail registering the ftrace_ops
84 * but, the regs field will be NULL if the arch does not support
85 * passing regs to the handler.
86 * Note, if this flag is set, the SAVE_REGS flag will automatically
87 * get set upon registering the ftrace_ops, if the arch supports it.
74 */ 88 */
75enum { 89enum {
76 FTRACE_OPS_FL_ENABLED = 1 << 0, 90 FTRACE_OPS_FL_ENABLED = 1 << 0,
77 FTRACE_OPS_FL_GLOBAL = 1 << 1, 91 FTRACE_OPS_FL_GLOBAL = 1 << 1,
78 FTRACE_OPS_FL_DYNAMIC = 1 << 2, 92 FTRACE_OPS_FL_DYNAMIC = 1 << 2,
79 FTRACE_OPS_FL_CONTROL = 1 << 3, 93 FTRACE_OPS_FL_CONTROL = 1 << 3,
94 FTRACE_OPS_FL_SAVE_REGS = 1 << 4,
95 FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 5,
80}; 96};
81 97
82struct ftrace_ops { 98struct ftrace_ops {
@@ -254,12 +270,31 @@ extern void unregister_ftrace_function_probe_all(char *glob);
254 270
255extern int ftrace_text_reserved(void *start, void *end); 271extern int ftrace_text_reserved(void *start, void *end);
256 272
273/*
274 * The dyn_ftrace record's flags field is split into two parts.
275 * the first part which is '0-FTRACE_REF_MAX' is a counter of
276 * the number of callbacks that have registered the function that
277 * the dyn_ftrace descriptor represents.
278 *
279 * The second part is a mask:
280 * ENABLED - the function is being traced
281 * REGS - the record wants the function to save regs
282 * REGS_EN - the function is set up to save regs.
283 *
284 * When a new ftrace_ops is registered and wants a function to save
285 * pt_regs, the rec->flag REGS is set. When the function has been
286 * set up to save regs, the REG_EN flag is set. Once a function
287 * starts saving regs it will do so until all ftrace_ops are removed
288 * from tracing that function.
289 */
257enum { 290enum {
258 FTRACE_FL_ENABLED = (1 << 30), 291 FTRACE_FL_ENABLED = (1UL << 29),
292 FTRACE_FL_REGS = (1UL << 30),
293 FTRACE_FL_REGS_EN = (1UL << 31)
259}; 294};
260 295
261#define FTRACE_FL_MASK (0x3UL << 30) 296#define FTRACE_FL_MASK (0x7UL << 29)
262#define FTRACE_REF_MAX ((1 << 30) - 1) 297#define FTRACE_REF_MAX ((1UL << 29) - 1)
263 298
264struct dyn_ftrace { 299struct dyn_ftrace {
265 union { 300 union {
@@ -290,9 +325,23 @@ enum {
290 FTRACE_STOP_FUNC_RET = (1 << 4), 325 FTRACE_STOP_FUNC_RET = (1 << 4),
291}; 326};
292 327
328/*
329 * The FTRACE_UPDATE_* enum is used to pass information back
330 * from the ftrace_update_record() and ftrace_test_record()
331 * functions. These are called by the code update routines
332 * to find out what is to be done for a given function.
333 *
334 * IGNORE - The function is already what we want it to be
335 * MAKE_CALL - Start tracing the function
336 * MODIFY_CALL - Stop saving regs for the function
337 * MODIFY_CALL_REGS - Start saving regs for the function
338 * MAKE_NOP - Stop tracing the function
339 */
293enum { 340enum {
294 FTRACE_UPDATE_IGNORE, 341 FTRACE_UPDATE_IGNORE,
295 FTRACE_UPDATE_MAKE_CALL, 342 FTRACE_UPDATE_MAKE_CALL,
343 FTRACE_UPDATE_MODIFY_CALL,
344 FTRACE_UPDATE_MODIFY_CALL_REGS,
296 FTRACE_UPDATE_MAKE_NOP, 345 FTRACE_UPDATE_MAKE_NOP,
297}; 346};
298 347
@@ -344,7 +393,9 @@ extern int ftrace_dyn_arch_init(void *data);
344extern void ftrace_replace_code(int enable); 393extern void ftrace_replace_code(int enable);
345extern int ftrace_update_ftrace_func(ftrace_func_t func); 394extern int ftrace_update_ftrace_func(ftrace_func_t func);
346extern void ftrace_caller(void); 395extern void ftrace_caller(void);
396extern void ftrace_regs_caller(void);
347extern void ftrace_call(void); 397extern void ftrace_call(void);
398extern void ftrace_regs_call(void);
348extern void mcount_call(void); 399extern void mcount_call(void);
349 400
350void ftrace_modify_all_code(int command); 401void ftrace_modify_all_code(int command);
@@ -352,6 +403,15 @@ void ftrace_modify_all_code(int command);
352#ifndef FTRACE_ADDR 403#ifndef FTRACE_ADDR
353#define FTRACE_ADDR ((unsigned long)ftrace_caller) 404#define FTRACE_ADDR ((unsigned long)ftrace_caller)
354#endif 405#endif
406
407#ifndef FTRACE_REGS_ADDR
408#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS
409# define FTRACE_REGS_ADDR ((unsigned long)ftrace_regs_caller)
410#else
411# define FTRACE_REGS_ADDR FTRACE_ADDR
412#endif
413#endif
414
355#ifdef CONFIG_FUNCTION_GRAPH_TRACER 415#ifdef CONFIG_FUNCTION_GRAPH_TRACER
356extern void ftrace_graph_caller(void); 416extern void ftrace_graph_caller(void);
357extern int ftrace_enable_ftrace_graph_caller(void); 417extern int ftrace_enable_ftrace_graph_caller(void);
@@ -407,6 +467,39 @@ extern int ftrace_make_nop(struct module *mod,
407 */ 467 */
408extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr); 468extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr);
409 469
470#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS
471/**
472 * ftrace_modify_call - convert from one addr to another (no nop)
473 * @rec: the mcount call site record
474 * @old_addr: the address expected to be currently called to
475 * @addr: the address to change to
476 *
477 * This is a very sensitive operation and great care needs
478 * to be taken by the arch. The operation should carefully
479 * read the location, check to see if what is read is indeed
480 * what we expect it to be, and then on success of the compare,
481 * it should write to the location.
482 *
483 * The code segment at @rec->ip should be a caller to @old_addr
484 *
485 * Return must be:
486 * 0 on success
487 * -EFAULT on error reading the location
488 * -EINVAL on a failed compare of the contents
489 * -EPERM on error writing to the location
490 * Any other value will be considered a failure.
491 */
492extern int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
493 unsigned long addr);
494#else
495/* Should never be called */
496static inline int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
497 unsigned long addr)
498{
499 return -EINVAL;
500}
501#endif
502
410/* May be defined in arch */ 503/* May be defined in arch */
411extern int ftrace_arch_read_dyn_info(char *buf, int size); 504extern int ftrace_arch_read_dyn_info(char *buf, int size);
412 505