]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - include/linux/ftrace.h
Merge tag 'f2fs-for-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
[linux.git] / include / linux / ftrace.h
index 9141f22632864d9814cabe4e7544b6401fc4cf4a..7247d35c3d160af210f35e07393fd04da361326b 100644 (file)
@@ -51,6 +51,7 @@ static inline void early_trace_init(void) { }
 
 struct module;
 struct ftrace_hash;
+struct ftrace_direct_func;
 
 #if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_MODULES) && \
        defined(CONFIG_DYNAMIC_FTRACE)
@@ -142,24 +143,30 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);
  * PID     - Is affected by set_ftrace_pid (allows filtering on those pids)
  * RCU     - Set when the ops can only be called when RCU is watching.
  * TRACE_ARRAY - The ops->private points to a trace_array descriptor.
+ * PERMANENT - Set when the ops is permanent and should not be affected by
+ *             ftrace_enabled.
+ * DIRECT - Used by the direct ftrace_ops helper for direct functions
+ *            (internal ftrace only, should not be used by others)
  */
 enum {
-       FTRACE_OPS_FL_ENABLED                   = 1 << 0,
-       FTRACE_OPS_FL_DYNAMIC                   = 1 << 1,
-       FTRACE_OPS_FL_SAVE_REGS                 = 1 << 2,
-       FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED    = 1 << 3,
-       FTRACE_OPS_FL_RECURSION_SAFE            = 1 << 4,
-       FTRACE_OPS_FL_STUB                      = 1 << 5,
-       FTRACE_OPS_FL_INITIALIZED               = 1 << 6,
-       FTRACE_OPS_FL_DELETED                   = 1 << 7,
-       FTRACE_OPS_FL_ADDING                    = 1 << 8,
-       FTRACE_OPS_FL_REMOVING                  = 1 << 9,
-       FTRACE_OPS_FL_MODIFYING                 = 1 << 10,
-       FTRACE_OPS_FL_ALLOC_TRAMP               = 1 << 11,
-       FTRACE_OPS_FL_IPMODIFY                  = 1 << 12,
-       FTRACE_OPS_FL_PID                       = 1 << 13,
-       FTRACE_OPS_FL_RCU                       = 1 << 14,
-       FTRACE_OPS_FL_TRACE_ARRAY               = 1 << 15,
+       FTRACE_OPS_FL_ENABLED                   = BIT(0),
+       FTRACE_OPS_FL_DYNAMIC                   = BIT(1),
+       FTRACE_OPS_FL_SAVE_REGS                 = BIT(2),
+       FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED    = BIT(3),
+       FTRACE_OPS_FL_RECURSION_SAFE            = BIT(4),
+       FTRACE_OPS_FL_STUB                      = BIT(5),
+       FTRACE_OPS_FL_INITIALIZED               = BIT(6),
+       FTRACE_OPS_FL_DELETED                   = BIT(7),
+       FTRACE_OPS_FL_ADDING                    = BIT(8),
+       FTRACE_OPS_FL_REMOVING                  = BIT(9),
+       FTRACE_OPS_FL_MODIFYING                 = BIT(10),
+       FTRACE_OPS_FL_ALLOC_TRAMP               = BIT(11),
+       FTRACE_OPS_FL_IPMODIFY                  = BIT(12),
+       FTRACE_OPS_FL_PID                       = BIT(13),
+       FTRACE_OPS_FL_RCU                       = BIT(14),
+       FTRACE_OPS_FL_TRACE_ARRAY               = BIT(15),
+       FTRACE_OPS_FL_PERMANENT                 = BIT(16),
+       FTRACE_OPS_FL_DIRECT                    = BIT(17),
 };
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -239,6 +246,70 @@ static inline void ftrace_free_init_mem(void) { }
 static inline void ftrace_free_mem(struct module *mod, void *start, void *end) { }
 #endif /* CONFIG_FUNCTION_TRACER */
 
+struct ftrace_func_entry {
+       struct hlist_node hlist;
+       unsigned long ip;
+       unsigned long direct; /* for direct lookup only */
+};
+
+struct dyn_ftrace;
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+extern int ftrace_direct_func_count;
+int register_ftrace_direct(unsigned long ip, unsigned long addr);
+int unregister_ftrace_direct(unsigned long ip, unsigned long addr);
+int modify_ftrace_direct(unsigned long ip, unsigned long old_addr, unsigned long new_addr);
+struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr);
+int ftrace_modify_direct_caller(struct ftrace_func_entry *entry,
+                               struct dyn_ftrace *rec,
+                               unsigned long old_addr,
+                               unsigned long new_addr);
+#else
+# define ftrace_direct_func_count 0
+static inline int register_ftrace_direct(unsigned long ip, unsigned long addr)
+{
+       return -ENOTSUPP;
+}
+static inline int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
+{
+       return -ENOTSUPP;
+}
+static inline int modify_ftrace_direct(unsigned long ip,
+                                      unsigned long old_addr, unsigned long new_addr)
+{
+       return -ENOTSUPP;
+}
+static inline struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr)
+{
+       return NULL;
+}
+static inline int ftrace_modify_direct_caller(struct ftrace_func_entry *entry,
+                                             struct dyn_ftrace *rec,
+                                             unsigned long old_addr,
+                                             unsigned long new_addr)
+{
+       return -ENODEV;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
+
+#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+/*
+ * This must be implemented by the architecture.
+ * It is the way the ftrace direct_ops helper, when called
+ * via ftrace (because there's other callbacks besides the
+ * direct call), can inform the architecture's trampoline that this
+ * routine has a direct caller, and what the caller is.
+ *
+ * For example, in x86, it returns the direct caller
+ * callback function via the regs->orig_ax parameter.
+ * Then in the ftrace trampoline, if this is set, it makes
+ * the return from the trampoline jump to the direct caller
+ * instead of going back to the function it just traced.
+ */
+static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs,
+                                                unsigned long addr) { }
+#endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
+
 #ifdef CONFIG_STACK_TRACER
 
 extern int stack_tracer_enabled;
@@ -291,8 +362,6 @@ static inline void stack_tracer_enable(void) { }
 int ftrace_arch_code_modify_prepare(void);
 int ftrace_arch_code_modify_post_process(void);
 
-struct dyn_ftrace;
-
 enum ftrace_bug_type {
        FTRACE_BUG_UNKNOWN,
        FTRACE_BUG_INIT,
@@ -330,6 +399,7 @@ bool is_ftrace_trampoline(unsigned long addr);
  *  REGS_EN - the function is set up to save regs.
  *  IPMODIFY - the record allows for the IP address to be changed.
  *  DISABLED - the record is not ready to be touched yet
+ *  DIRECT   - there is a direct function to call
  *
  * When a new ftrace_ops is registered and wants a function to save
  * pt_regs, the rec->flag REGS is set. When the function has been
@@ -345,10 +415,12 @@ enum {
        FTRACE_FL_TRAMP_EN      = (1UL << 27),
        FTRACE_FL_IPMODIFY      = (1UL << 26),
        FTRACE_FL_DISABLED      = (1UL << 25),
+       FTRACE_FL_DIRECT        = (1UL << 24),
+       FTRACE_FL_DIRECT_EN     = (1UL << 23),
 };
 
-#define FTRACE_REF_MAX_SHIFT   25
-#define FTRACE_FL_BITS         7
+#define FTRACE_REF_MAX_SHIFT   23
+#define FTRACE_FL_BITS         9
 #define FTRACE_FL_MASKED_BITS  ((1UL << FTRACE_FL_BITS) - 1)
 #define FTRACE_FL_MASK         (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT)
 #define FTRACE_REF_MAX         ((1UL << FTRACE_REF_MAX_SHIFT) - 1)