| /* |
| * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com) |
| * |
| * This file implements mcount(), which is used to collect profiling data. |
| * This can also be tweaked for kernel stack overflow detection. |
| */ |
| |
| #include <linux/linkage.h> |
| |
| #include <asm/ptrace.h> |
| #include <asm/thread_info.h> |
| |
| /* |
| * This is the main variant and is called by C code. GCC's -pg option |
| * automatically instruments every C function with a call to this. |
| */ |
| |
| #ifdef CONFIG_STACK_DEBUG |
| |
| #define OVSTACKSIZE 4096 /* lets hope this is enough */ |
| |
| .data |
| .align 8 |
| panicstring: |
| .asciz "Stack overflow\n" |
| .align 8 |
| ovstack: |
| .skip OVSTACKSIZE |
| #endif |
| .text |
| .align 32 |
| .globl _mcount |
| .type _mcount,#function |
| .globl mcount |
| .type mcount,#function |
| _mcount: |
| mcount: |
| #ifdef CONFIG_STACK_DEBUG |
| /* |
| * Check whether %sp is dangerously low. |
| */ |
| ldub [%g6 + TI_FPDEPTH], %g1 |
| srl %g1, 1, %g3 |
| add %g3, 1, %g3 |
| sllx %g3, 8, %g3 ! each fpregs frame is 256b |
| add %g3, 192, %g3 |
| add %g6, %g3, %g3 ! where does task_struct+frame end? |
| sub %g3, STACK_BIAS, %g3 |
| cmp %sp, %g3 |
| bg,pt %xcc, 1f |
| nop |
| lduh [%g6 + TI_CPU], %g1 |
| sethi %hi(hardirq_stack), %g3 |
| or %g3, %lo(hardirq_stack), %g3 |
| sllx %g1, 3, %g1 |
| ldx [%g3 + %g1], %g7 |
| sub %g7, STACK_BIAS, %g7 |
| cmp %sp, %g7 |
| bleu,pt %xcc, 2f |
| sethi %hi(THREAD_SIZE), %g3 |
| add %g7, %g3, %g7 |
| cmp %sp, %g7 |
| blu,pn %xcc, 1f |
| 2: sethi %hi(softirq_stack), %g3 |
| or %g3, %lo(softirq_stack), %g3 |
| ldx [%g3 + %g1], %g7 |
| cmp %sp, %g7 |
| bleu,pt %xcc, 2f |
| sethi %hi(THREAD_SIZE), %g3 |
| add %g7, %g3, %g7 |
| cmp %sp, %g7 |
| blu,pn %xcc, 1f |
| nop |
| /* If we are already on ovstack, don't hop onto it |
| * again, we are already trying to output the stack overflow |
| * message. |
| */ |
| sethi %hi(ovstack), %g7 ! cant move to panic stack fast enough |
| or %g7, %lo(ovstack), %g7 |
| add %g7, OVSTACKSIZE, %g3 |
| sub %g3, STACK_BIAS + 192, %g3 |
| sub %g7, STACK_BIAS, %g7 |
| cmp %sp, %g7 |
| blu,pn %xcc, 2f |
| cmp %sp, %g3 |
| bleu,pn %xcc, 1f |
| nop |
| 2: mov %g3, %sp |
| sethi %hi(panicstring), %g3 |
| call prom_printf |
| or %g3, %lo(panicstring), %o0 |
| call prom_halt |
| nop |
| 1: |
| #endif |
| #ifdef CONFIG_FTRACE |
| #ifdef CONFIG_DYNAMIC_FTRACE |
| mov %o7, %o0 |
| .globl mcount_call |
| mcount_call: |
| call ftrace_stub |
| mov %o0, %o7 |
| #else |
| sethi %hi(ftrace_trace_function), %g1 |
| sethi %hi(ftrace_stub), %g2 |
| ldx [%g1 + %lo(ftrace_trace_function)], %g1 |
| or %g2, %lo(ftrace_stub), %g2 |
| cmp %g1, %g2 |
| be,pn %icc, 1f |
| mov %i7, %o1 |
| jmpl %g1, %g0 |
| mov %o7, %o0 |
| /* not reached */ |
| 1: |
| #endif |
| #endif |
| retl |
| nop |
| .size _mcount,.-_mcount |
| .size mcount,.-mcount |
| |
| #ifdef CONFIG_FTRACE |
| .globl ftrace_stub |
| .type ftrace_stub,#function |
| ftrace_stub: |
| retl |
| nop |
| .size ftrace_stub,.-ftrace_stub |
| #ifdef CONFIG_DYNAMIC_FTRACE |
| .globl ftrace_caller |
| .type ftrace_caller,#function |
| ftrace_caller: |
| mov %i7, %o1 |
| mov %o7, %o0 |
| .globl ftrace_call |
| ftrace_call: |
| call ftrace_stub |
| mov %o0, %o7 |
| retl |
| nop |
| .size ftrace_caller,.-ftrace_caller |
| #endif |
| #endif |