]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/x86/kernel/ftrace_32.S
2b160f238a4296aac2e7eb75bb789bffa491deac
[karo-tx-linux.git] / arch / x86 / kernel / ftrace_32.S
1 /*
2  *  Copyright (C) 2017  Steven Rostedt, VMware Inc.
3  */
4
5 #include <linux/linkage.h>
6 #include <asm/page_types.h>
7 #include <asm/segment.h>
8 #include <asm/export.h>
9 #include <asm/ftrace.h>
10
11 #ifdef CONFIG_FUNCTION_TRACER
12 #ifdef CONFIG_DYNAMIC_FTRACE
13
14 ENTRY(mcount)
15         ret
16 END(mcount)
17
18 ENTRY(ftrace_caller)
19         pushl   %eax
20         pushl   %ecx
21         pushl   %edx
22         pushl   $0                              /* Pass NULL as regs pointer */
23         movl    4*4(%esp), %eax
24         movl    0x4(%ebp), %edx
25         movl    function_trace_op, %ecx
26         subl    $MCOUNT_INSN_SIZE, %eax
27
28 .globl ftrace_call
29 ftrace_call:
30         call    ftrace_stub
31
32         addl    $4, %esp                        /* skip NULL pointer */
33         popl    %edx
34         popl    %ecx
35         popl    %eax
36 .Lftrace_ret:
37 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
38 .globl ftrace_graph_call
39 ftrace_graph_call:
40         jmp     ftrace_stub
41 #endif
42
43 /* This is weak to keep gas from relaxing the jumps */
44 WEAK(ftrace_stub)
45         ret
46 END(ftrace_caller)
47
48 ENTRY(ftrace_regs_caller)
49         pushf   /* push flags before compare (in cs location) */
50
51         /*
52          * i386 does not save SS and ESP when coming from kernel.
53          * Instead, to get sp, &regs->sp is used (see ptrace.h).
54          * Unfortunately, that means eflags must be at the same location
55          * as the current return ip is. We move the return ip into the
56          * ip location, and move flags into the return ip location.
57          */
58         pushl   4(%esp)                         /* save return ip into ip slot */
59
60         pushl   $0                              /* Load 0 into orig_ax */
61         pushl   %gs
62         pushl   %fs
63         pushl   %es
64         pushl   %ds
65         pushl   %eax
66         pushl   %ebp
67         pushl   %edi
68         pushl   %esi
69         pushl   %edx
70         pushl   %ecx
71         pushl   %ebx
72
73         movl    13*4(%esp), %eax                /* Get the saved flags */
74         movl    %eax, 14*4(%esp)                /* Move saved flags into regs->flags location */
75                                                 /* clobbering return ip */
76         movl    $__KERNEL_CS, 13*4(%esp)
77
78         movl    12*4(%esp), %eax                /* Load ip (1st parameter) */
79         subl    $MCOUNT_INSN_SIZE, %eax         /* Adjust ip */
80         movl    0x4(%ebp), %edx                 /* Load parent ip (2nd parameter) */
81         movl    function_trace_op, %ecx         /* Save ftrace_pos in 3rd parameter */
82         pushl   %esp                            /* Save pt_regs as 4th parameter */
83
84 GLOBAL(ftrace_regs_call)
85         call    ftrace_stub
86
87         addl    $4, %esp                        /* Skip pt_regs */
88         movl    14*4(%esp), %eax                /* Move flags back into cs */
89         movl    %eax, 13*4(%esp)                /* Needed to keep addl  from modifying flags */
90         movl    12*4(%esp), %eax                /* Get return ip from regs->ip */
91         movl    %eax, 14*4(%esp)                /* Put return ip back for ret */
92
93         popl    %ebx
94         popl    %ecx
95         popl    %edx
96         popl    %esi
97         popl    %edi
98         popl    %ebp
99         popl    %eax
100         popl    %ds
101         popl    %es
102         popl    %fs
103         popl    %gs
104         addl    $8, %esp                        /* Skip orig_ax and ip */
105         popf                                    /* Pop flags at end (no addl to corrupt flags) */
106         jmp     .Lftrace_ret
107
108         popf
109         jmp     ftrace_stub
110 #else /* ! CONFIG_DYNAMIC_FTRACE */
111
112 ENTRY(mcount)
113         cmpl    $__PAGE_OFFSET, %esp
114         jb      ftrace_stub                     /* Paging not enabled yet? */
115
116         cmpl    $ftrace_stub, ftrace_trace_function
117         jnz     .Ltrace
118 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
119         cmpl    $ftrace_stub, ftrace_graph_return
120         jnz     ftrace_graph_caller
121
122         cmpl    $ftrace_graph_entry_stub, ftrace_graph_entry
123         jnz     ftrace_graph_caller
124 #endif
125 .globl ftrace_stub
126 ftrace_stub:
127         ret
128
129         /* taken from glibc */
130 .Ltrace:
131         pushl   %eax
132         pushl   %ecx
133         pushl   %edx
134         movl    0xc(%esp), %eax
135         movl    0x4(%ebp), %edx
136         subl    $MCOUNT_INSN_SIZE, %eax
137
138         call    *ftrace_trace_function
139
140         popl    %edx
141         popl    %ecx
142         popl    %eax
143         jmp     ftrace_stub
144 END(mcount)
145 #endif /* CONFIG_DYNAMIC_FTRACE */
146 EXPORT_SYMBOL(mcount)
147 #endif /* CONFIG_FUNCTION_TRACER */
148
149 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
150 ENTRY(ftrace_graph_caller)
151         pushl   %eax
152         pushl   %ecx
153         pushl   %edx
154         movl    0xc(%esp), %eax
155         lea     0x4(%ebp), %edx
156         movl    (%ebp), %ecx
157         subl    $MCOUNT_INSN_SIZE, %eax
158         call    prepare_ftrace_return
159         popl    %edx
160         popl    %ecx
161         popl    %eax
162         ret
163 END(ftrace_graph_caller)
164
165 .globl return_to_handler
166 return_to_handler:
167         pushl   %eax
168         pushl   %edx
169         movl    %ebp, %eax
170         call    ftrace_return_to_handler
171         movl    %eax, %ecx
172         popl    %edx
173         popl    %eax
174         jmp     *%ecx
175 #endif