1/* 2 * arch/sh/lib/mcount.S 3 * 4 * Copyright (C) 2008, 2009 Paul Mundt 5 * Copyright (C) 2008, 2009 Matt Fleming 6 * 7 * This file is subject to the terms and conditions of the GNU General Public 8 * License. See the file "COPYING" in the main directory of this archive 9 * for more details. 10 */ 11#include <asm/ftrace.h> 12#include <asm/thread_info.h> 13#include <asm/asm-offsets.h> 14 15#define MCOUNT_ENTER() \ 16 mov.l r4, @-r15; \ 17 mov.l r5, @-r15; \ 18 mov.l r6, @-r15; \ 19 mov.l r7, @-r15; \ 20 sts.l pr, @-r15; \ 21 \ 22 mov.l @(20,r15),r4; \ 23 sts pr, r5 24 25#define MCOUNT_LEAVE() \ 26 lds.l @r15+, pr; \ 27 mov.l @r15+, r7; \ 28 mov.l @r15+, r6; \ 29 mov.l @r15+, r5; \ 30 rts; \ 31 mov.l @r15+, r4 32 33#ifdef CONFIG_STACK_DEBUG 34/* 35 * Perform diagnostic checks on the state of the kernel stack. 36 * 37 * Check for stack overflow. If there is less than 1KB free 38 * then it has overflowed. 39 * 40 * Make sure the stack pointer contains a valid address. Valid 41 * addresses for kernel stacks are anywhere after the bss 42 * (after _ebss) and anywhere in init_thread_union (init_stack). 43 */ 44#define STACK_CHECK() \ 45 mov #(THREAD_SIZE >> 10), r0; \ 46 shll8 r0; \ 47 shll2 r0; \ 48 \ 49 /* r1 = sp & (THREAD_SIZE - 1) */ \ 50 mov #-1, r1; \ 51 add r0, r1; \ 52 and r15, r1; \ 53 \ 54 mov #TI_SIZE, r3; \ 55 mov #(STACK_WARN >> 8), r2; \ 56 shll8 r2; \ 57 add r3, r2; \ 58 \ 59 /* Is the stack overflowing? */ \ 60 cmp/hi r2, r1; \ 61 bf stack_panic; \ 62 \ 63 /* If sp > _ebss then we're OK. */ \ 64 mov.l .L_ebss, r1; \ 65 cmp/hi r1, r15; \ 66 bt 1f; \ 67 \ 68 /* If sp < init_stack, we're not OK. */ \ 69 mov.l .L_init_thread_union, r1; \ 70 cmp/hs r1, r15; \ 71 bf stack_panic; \ 72 \ 73 /* If sp > init_stack && sp < _ebss, not OK. */ \ 74 add r0, r1; \ 75 cmp/hs r1, r15; \ 76 bt stack_panic; \ 771: 78#else 79#define STACK_CHECK() 80#endif /* CONFIG_STACK_DEBUG */ 81 82 .align 2 83 .globl _mcount 84 .type _mcount,@function 85 .globl mcount 86 .type mcount,@function 87_mcount: 88mcount: 89 STACK_CHECK() 90 91#ifndef CONFIG_FUNCTION_TRACER 92 rts 93 nop 94#else 95#ifndef CONFIG_DYNAMIC_FTRACE 96 mov.l .Lfunction_trace_stop, r0 97 mov.l @r0, r0 98 tst r0, r0 99 bf ftrace_stub 100#endif 101 102 MCOUNT_ENTER() 103 104#ifdef CONFIG_DYNAMIC_FTRACE 105 .globl mcount_call 106mcount_call: 107 mov.l .Lftrace_stub, r6 108#else 109 mov.l .Lftrace_trace_function, r6 110 mov.l ftrace_stub, r7 111 cmp/eq r6, r7 112 bt skip_trace 113 mov.l @r6, r6 114#endif 115 116 jsr @r6 117 nop 118 119#ifdef CONFIG_FUNCTION_GRAPH_TRACER 120 mov.l .Lftrace_graph_return, r6 121 mov.l .Lftrace_stub, r7 122 cmp/eq r6, r7 123 bt 1f 124 125 mov.l .Lftrace_graph_caller, r0 126 jmp @r0 127 nop 128 1291: 130 mov.l .Lftrace_graph_entry, r6 131 mov.l .Lftrace_graph_entry_stub, r7 132 cmp/eq r6, r7 133 bt skip_trace 134 135 mov.l .Lftrace_graph_caller, r0 136 jmp @r0 137 nop 138 139 .align 2 140.Lftrace_graph_return: 141 .long ftrace_graph_return 142.Lftrace_graph_entry: 143 .long ftrace_graph_entry 144.Lftrace_graph_entry_stub: 145 .long ftrace_graph_entry_stub 146.Lftrace_graph_caller: 147 .long ftrace_graph_caller 148#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 149 150 .globl skip_trace 151skip_trace: 152 MCOUNT_LEAVE() 153 154 .align 2 155.Lftrace_trace_function: 156 .long ftrace_trace_function 157 158#ifdef CONFIG_DYNAMIC_FTRACE 159#ifdef CONFIG_FUNCTION_GRAPH_TRACER 160/* 161 * NOTE: Do not move either ftrace_graph_call or ftrace_caller 162 * as this will affect the calculation of GRAPH_INSN_OFFSET. 163 */ 164 .globl ftrace_graph_call 165ftrace_graph_call: 166 mov.l .Lskip_trace, r0 167 jmp @r0 168 nop 169 170 .align 2 171.Lskip_trace: 172 .long skip_trace 173#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 174 175 .globl ftrace_caller 176ftrace_caller: 177 mov.l .Lfunction_trace_stop, r0 178 mov.l @r0, r0 179 tst r0, r0 180 bf ftrace_stub 181 182 MCOUNT_ENTER() 183 184 .globl ftrace_call 185ftrace_call: 186 mov.l .Lftrace_stub, r6 187 jsr @r6 188 nop 189 190#ifdef CONFIG_FUNCTION_GRAPH_TRACER 191 bra ftrace_graph_call 192 nop 193#else 194 MCOUNT_LEAVE() 195#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 196#endif /* CONFIG_DYNAMIC_FTRACE */ 197 198 .align 2 199.Lfunction_trace_stop: 200 .long function_trace_stop 201 202/* 203 * NOTE: From here on the locations of the .Lftrace_stub label and 204 * ftrace_stub itself are fixed. Adding additional data here will skew 205 * the displacement for the memory table and break the block replacement. 206 * Place new labels either after the ftrace_stub body, or before 207 * ftrace_caller. You have been warned. 208 */ 209.Lftrace_stub: 210 .long ftrace_stub 211 212 .globl ftrace_stub 213ftrace_stub: 214 rts 215 nop 216 217#ifdef CONFIG_FUNCTION_GRAPH_TRACER 218 .globl ftrace_graph_caller 219ftrace_graph_caller: 220 mov.l 2f, r0 221 mov.l @r0, r0 222 tst r0, r0 223 bt 1f 224 225 mov.l 3f, r1 226 jmp @r1 227 nop 2281: 229 /* 230 * MCOUNT_ENTER() pushed 5 registers onto the stack, so 231 * the stack address containing our return address is 232 * r15 + 20. 233 */ 234 mov #20, r0 235 add r15, r0 236 mov r0, r4 237 238 mov.l .Lprepare_ftrace_return, r0 239 jsr @r0 240 nop 241 242 MCOUNT_LEAVE() 243 244 .align 2 2452: .long function_trace_stop 2463: .long skip_trace 247.Lprepare_ftrace_return: 248 .long prepare_ftrace_return 249 250 .globl return_to_handler 251return_to_handler: 252 /* 253 * Save the return values. 254 */ 255 mov.l r0, @-r15 256 mov.l r1, @-r15 257 258 mov #0, r4 259 260 mov.l .Lftrace_return_to_handler, r0 261 jsr @r0 262 nop 263 264 /* 265 * The return value from ftrace_return_handler has the real 266 * address that we should return to. 267 */ 268 lds r0, pr 269 mov.l @r15+, r1 270 rts 271 mov.l @r15+, r0 272 273 274 .align 2 275.Lftrace_return_to_handler: 276 .long ftrace_return_to_handler 277#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 278#endif /* CONFIG_FUNCTION_TRACER */ 279 280#ifdef CONFIG_STACK_DEBUG 281 .globl stack_panic 282stack_panic: 283 mov.l .Ldump_stack, r0 284 jsr @r0 285 nop 286 287 mov.l .Lpanic, r0 288 jsr @r0 289 mov.l .Lpanic_s, r4 290 291 rts 292 nop 293 294 .align 2 295.L_ebss: 296 .long _ebss 297.L_init_thread_union: 298 .long init_thread_union 299.Lpanic: 300 .long panic 301.Lpanic_s: 302 .long .Lpanic_str 303.Ldump_stack: 304 .long dump_stack 305 306 .section .rodata 307 .align 2 308.Lpanic_str: 309 .string "Stack error" 310#endif /* CONFIG_STACK_DEBUG */ 311