1 /* SPDX-License-Identifier: GPL-2.0 !! 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 * !! 2 /* 3 * arch/sh/lib/mcount.S !! 3 * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com) 4 * 4 * 5 * Copyright (C) 2008, 2009 Paul Mundt !! 5 * This file implements mcount(), which is used to collect profiling data. 6 * Copyright (C) 2008, 2009 Matt Fleming !! 6 * This can also be tweaked for kernel stack overflow detection. 7 */ 7 */ 8 #include <asm/ftrace.h> << 9 #include <asm/thread_info.h> << 10 #include <asm/asm-offsets.h> << 11 << 12 #define MCOUNT_ENTER() \ << 13 mov.l r4, @-r15; \ << 14 mov.l r5, @-r15; \ << 15 mov.l r6, @-r15; \ << 16 mov.l r7, @-r15; \ << 17 sts.l pr, @-r15; \ << 18 \ << 19 mov.l @(20,r15),r4; \ << 20 sts pr, r5 << 21 8 22 #define MCOUNT_LEAVE() \ !! 9 #include <linux/export.h> 23 lds.l @r15+, pr; \ !! 10 #include <linux/linkage.h> 24 mov.l @r15+, r7; \ << 25 mov.l @r15+, r6; \ << 26 mov.l @r15+, r5; \ << 27 rts; \ << 28 mov.l @r15+, r4 << 29 11 30 #ifdef CONFIG_STACK_DEBUG << 31 /* 12 /* 32 * Perform diagnostic checks on the state of t !! 13 * This is the main variant and is called by C code. GCC's -pg option 33 * !! 14 * automatically instruments every C function with a call to this. 34 * Check for stack overflow. If there is less << 35 * then it has overflowed. << 36 * << 37 * Make sure the stack pointer contains a vali << 38 * addresses for kernel stacks are anywhere af << 39 * (after __bss_stop) and anywhere in init_thr << 40 */ 15 */ 41 #define STACK_CHECK() << 42 mov #(THREAD_SIZE >> 10), r0; << 43 shll8 r0; << 44 shll2 r0; << 45 << 46 /* r1 = sp & (THREAD_SIZE - 1) */ << 47 mov #-1, r1; << 48 add r0, r1; << 49 and r15, r1; << 50 << 51 mov #TI_SIZE, r3; << 52 mov #(STACK_WARN >> 8), r2; << 53 shll8 r2; << 54 add r3, r2; << 55 << 56 /* Is the stack overflowing? */ << 57 cmp/hi r2, r1; << 58 bf stack_panic; << 59 << 60 /* If sp > __bss_stop then we're OK. * << 61 mov.l .L_ebss, r1; << 62 cmp/hi r1, r15; << 63 bt 1f; << 64 << 65 /* If sp < init_stack, we're not OK. * << 66 mov.l .L_init_thread_union, r1; << 67 cmp/hs r1, r15; << 68 bf stack_panic; << 69 << 70 /* If sp > init_stack && sp < __bss_st << 71 add r0, r1; << 72 cmp/hs r1, r15; << 73 bt stack_panic; << 74 1: << 75 #else << 76 #define STACK_CHECK() << 77 #endif /* CONFIG_STACK_DEBUG */ << 78 16 79 .align 2 !! 17 .text 80 .globl _mcount !! 18 .align 32 81 .type _mcount,@function !! 19 .globl _mcount 82 .globl mcount !! 20 .type _mcount,#function 83 .type mcount,@function !! 21 EXPORT_SYMBOL(_mcount) >> 22 .globl mcount >> 23 .type mcount,#function 84 _mcount: 24 _mcount: 85 mcount: 25 mcount: 86 STACK_CHECK() !! 26 #ifdef CONFIG_FUNCTION_TRACER 87 << 88 #ifndef CONFIG_FUNCTION_TRACER << 89 rts << 90 nop << 91 #else << 92 MCOUNT_ENTER() << 93 << 94 #ifdef CONFIG_DYNAMIC_FTRACE 27 #ifdef CONFIG_DYNAMIC_FTRACE 95 .globl mcount_call !! 28 /* Do nothing, the retl/nop below is all we need. */ 96 mcount_call: << 97 mov.l .Lftrace_stub, r6 << 98 #else 29 #else 99 mov.l .Lftrace_trace_function, r6 !! 30 sethi %hi(ftrace_trace_function), %g1 100 mov.l ftrace_stub, r7 !! 31 sethi %hi(ftrace_stub), %g2 101 cmp/eq r6, r7 !! 32 ldx [%g1 + %lo(ftrace_trace_function)], %g1 102 bt skip_trace !! 33 or %g2, %lo(ftrace_stub), %g2 103 mov.l @r6, r6 !! 34 cmp %g1, %g2 104 #endif !! 35 be,pn %icc, 1f 105 !! 36 mov %i7, %g3 106 jsr @r6 !! 37 save %sp, -176, %sp 107 nop !! 38 mov %g3, %o1 108 !! 39 jmpl %g1, %o7 >> 40 mov %i7, %o0 >> 41 ret >> 42 restore >> 43 /* not reached */ >> 44 1: 109 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 45 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 110 mov.l .Lftrace_graph_return, r6 !! 46 sethi %hi(ftrace_graph_return), %g1 111 mov.l .Lftrace_stub, r7 !! 47 ldx [%g1 + %lo(ftrace_graph_return)], %g3 112 cmp/eq r6, r7 !! 48 cmp %g2, %g3 113 bt 1f !! 49 bne,pn %xcc, 5f 114 !! 50 sethi %hi(ftrace_graph_entry_stub), %g2 115 mov.l .Lftrace_graph_caller, r0 !! 51 sethi %hi(ftrace_graph_entry), %g1 116 jmp @r0 !! 52 or %g2, %lo(ftrace_graph_entry_stub), %g2 >> 53 ldx [%g1 + %lo(ftrace_graph_entry)], %g1 >> 54 cmp %g1, %g2 >> 55 be,pt %xcc, 2f >> 56 nop >> 57 5: mov %i7, %g2 >> 58 mov %fp, %g3 >> 59 save %sp, -176, %sp >> 60 mov %g2, %l0 >> 61 ba,pt %xcc, ftrace_graph_caller >> 62 mov %g3, %l1 >> 63 #endif >> 64 2: >> 65 #endif >> 66 #endif >> 67 retl 117 nop 68 nop >> 69 .size _mcount,.-_mcount >> 70 .size mcount,.-mcount 118 71 119 1: !! 72 #ifdef CONFIG_FUNCTION_TRACER 120 mov.l .Lftrace_graph_entry, r6 !! 73 .globl ftrace_stub 121 mov.l .Lftrace_graph_entry_stub, r7 !! 74 .type ftrace_stub,#function 122 cmp/eq r6, r7 !! 75 ftrace_stub: 123 bt skip_trace !! 76 retl 124 << 125 mov.l .Lftrace_graph_caller, r0 << 126 jmp @r0 << 127 nop 77 nop 128 !! 78 .size ftrace_stub,.-ftrace_stub 129 .align 2 << 130 .Lftrace_graph_return: << 131 .long ftrace_graph_return << 132 .Lftrace_graph_entry: << 133 .long ftrace_graph_entry << 134 .Lftrace_graph_entry_stub: << 135 .long ftrace_graph_entry_stub << 136 .Lftrace_graph_caller: << 137 .long ftrace_graph_caller << 138 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ << 139 << 140 .globl skip_trace << 141 skip_trace: << 142 MCOUNT_LEAVE() << 143 << 144 .align 2 << 145 .Lftrace_trace_function: << 146 .long ftrace_trace_function << 147 << 148 #ifdef CONFIG_DYNAMIC_FTRACE 79 #ifdef CONFIG_DYNAMIC_FTRACE 149 #ifdef CONFIG_FUNCTION_GRAPH_TRACER !! 80 .globl ftrace_caller 150 /* !! 81 .type ftrace_caller,#function 151 * NOTE: Do not move either ftrace_graph_call << 152 * as this will affect the calculation of GRAP << 153 */ << 154 .globl ftrace_graph_call << 155 ftrace_graph_call: << 156 mov.l .Lskip_trace, r0 << 157 jmp @r0 << 158 nop << 159 << 160 .align 2 << 161 .Lskip_trace: << 162 .long skip_trace << 163 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ << 164 << 165 .globl ftrace_caller << 166 ftrace_caller: 82 ftrace_caller: 167 MCOUNT_ENTER() !! 83 mov %i7, %g2 168 !! 84 mov %fp, %g3 169 .globl ftrace_call !! 85 save %sp, -176, %sp >> 86 mov %g2, %o1 >> 87 mov %g2, %l0 >> 88 mov %g3, %l1 >> 89 .globl ftrace_call 170 ftrace_call: 90 ftrace_call: 171 mov.l .Lftrace_stub, r6 !! 91 call ftrace_stub 172 jsr @r6 !! 92 mov %i7, %o0 173 nop << 174 << 175 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 93 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 176 bra ftrace_graph_call !! 94 .globl ftrace_graph_call 177 nop !! 95 ftrace_graph_call: 178 #else !! 96 call ftrace_stub 179 MCOUNT_LEAVE() << 180 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ << 181 #endif /* CONFIG_DYNAMIC_FTRACE */ << 182 << 183 .align 2 << 184 << 185 /* << 186 * NOTE: From here on the locations of the .Lf << 187 * ftrace_stub itself are fixed. Adding additi << 188 * the displacement for the memory table and b << 189 * Place new labels either after the ftrace_st << 190 * ftrace_caller. You have been warned. << 191 */ << 192 .Lftrace_stub: << 193 .long ftrace_stub << 194 << 195 .globl ftrace_stub << 196 ftrace_stub: << 197 rts << 198 nop 97 nop 199 !! 98 #endif >> 99 ret >> 100 restore 200 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 101 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 201 .globl ftrace_graph_caller !! 102 .size ftrace_graph_call,.-ftrace_graph_call 202 ftrace_graph_caller: !! 103 #endif 203 mov.l 2f, r1 !! 104 .size ftrace_call,.-ftrace_call 204 jmp @r1 !! 105 .size ftrace_caller,.-ftrace_caller 205 nop !! 106 #endif 206 1: !! 107 #endif 207 /* << 208 * MCOUNT_ENTER() pushed 5 registers o << 209 * the stack address containing our re << 210 * r15 + 20. << 211 */ << 212 mov #20, r0 << 213 add r15, r0 << 214 mov r0, r4 << 215 << 216 mov.l .Lprepare_ftrace_return, r0 << 217 jsr @r0 << 218 nop << 219 << 220 MCOUNT_LEAVE() << 221 << 222 .align 2 << 223 2: .long skip_trace << 224 .Lprepare_ftrace_return: << 225 .long prepare_ftrace_return << 226 << 227 .globl return_to_handler << 228 return_to_handler: << 229 /* << 230 * Save the return values. << 231 */ << 232 mov.l r0, @-r15 << 233 mov.l r1, @-r15 << 234 << 235 mov #0, r4 << 236 << 237 mov.l .Lftrace_return_to_handler, r0 << 238 jsr @r0 << 239 nop << 240 << 241 /* << 242 * The return value from ftrace_return << 243 * address that we should return to. << 244 */ << 245 lds r0, pr << 246 mov.l @r15+, r1 << 247 rts << 248 mov.l @r15+, r0 << 249 << 250 << 251 .align 2 << 252 .Lftrace_return_to_handler: << 253 .long ftrace_return_to_handler << 254 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ << 255 #endif /* CONFIG_FUNCTION_TRACER */ << 256 << 257 #ifdef CONFIG_STACK_DEBUG << 258 .globl stack_panic << 259 stack_panic: << 260 mov.l .Ldump_stack, r0 << 261 jsr @r0 << 262 nop << 263 << 264 mov.l .Lpanic, r0 << 265 jsr @r0 << 266 mov.l .Lpanic_s, r4 << 267 << 268 rts << 269 nop << 270 << 271 .align 2 << 272 .L_init_thread_union: << 273 .long init_thread_union << 274 .L_ebss: << 275 .long __bss_stop << 276 .Lpanic: << 277 .long panic << 278 .Lpanic_s: << 279 .long .Lpanic_str << 280 .Ldump_stack: << 281 .long dump_stack << 282 108 283 .section .rodata !! 109 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 284 .align 2 !! 110 ENTRY(ftrace_graph_caller) 285 .Lpanic_str: !! 111 mov %l0, %o0 286 .string "Stack error" !! 112 mov %i7, %o1 287 #endif /* CONFIG_STACK_DEBUG */ !! 113 call prepare_ftrace_return >> 114 mov %l1, %o2 >> 115 ret >> 116 restore %o0, -8, %i7 >> 117 END(ftrace_graph_caller) >> 118 >> 119 ENTRY(return_to_handler) >> 120 save %sp, -176, %sp >> 121 call ftrace_return_to_handler >> 122 mov %fp, %o0 >> 123 jmpl %o0 + 8, %g0 >> 124 restore >> 125 END(return_to_handler) >> 126 #endif
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.