hc
2023-11-22 983d7f83616922a6439b4352d1b3af488ee27f95
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// SPDX-License-Identifier: GPL-2.0
/*
 * Code for tracing calls in Linux kernel.
 * Copyright (C) 2009-2016 Helge Deller <deller@gmx.de>
 *
 * based on code for x86 which is:
 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
 *
 * future possible enhancements:
 *     - add CONFIG_DYNAMIC_FTRACE
 *    - add CONFIG_STACK_TRACER
 */
 
#include <linux/init.h>
#include <linux/ftrace.h>
 
#include <asm/assembly.h>
#include <asm/sections.h>
#include <asm/ftrace.h>
 
 
#define __hot __attribute__ ((__section__ (".text.hot")))
 
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
/*
 * Hook the return address and push it in the stack of return addrs
 * in current thread info.
 */
static void __hot prepare_ftrace_return(unsigned long *parent,
                   unsigned long self_addr)
{
   unsigned long old;
   extern int parisc_return_to_handler;
 
   if (unlikely(ftrace_graph_is_dead()))
       return;
 
   if (unlikely(atomic_read(&current->tracing_graph_pause)))
       return;
 
   old = *parent;
 
   if (!function_graph_enter(old, self_addr, 0, NULL))
       /* activate parisc_return_to_handler() as return point */
       *parent = (unsigned long) &parisc_return_to_handler;
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
void notrace __hot ftrace_function_trampoline(unsigned long parent,
               unsigned long self_addr,
               unsigned long org_sp_gr3)
{
   extern ftrace_func_t ftrace_trace_function;  /* depends on CONFIG_DYNAMIC_FTRACE */
   extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace);
 
   if (ftrace_trace_function != ftrace_stub) {
       /* struct ftrace_ops *op, struct pt_regs *regs); */
       ftrace_trace_function(parent, self_addr, NULL, NULL);
       return;
   }
 
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
   if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub ||
       ftrace_graph_entry != ftrace_graph_entry_stub) {
       unsigned long *parent_rp;
 
       /* calculate pointer to %rp in stack */
       parent_rp = (unsigned long *) (org_sp_gr3 - RP_OFFSET);
       /* sanity check: parent_rp should hold parent */
       if (*parent_rp != parent)
           return;
 
       prepare_ftrace_return(parent_rp, self_addr);
       return;
   }
#endif
}