/* SPDX-License-Identifier: GPL-2.01*2* arch/sh/lib/mcount.S3*4* Copyright (C) 2008, 2009 Paul Mundt5* Copyright (C) 2008, 2009 Matt Fleming6*/7#include <asm/ftrace.h>8#include <asm/thread_info.h>9#include <asm/asm-offsets.h>1011#define MCOUNT_ENTER() \12mov.l r4, @-r15; \13mov.l r5, @-r15; \14mov.l r6, @-r15; \15mov.l r7, @-r15; \16sts.l pr, @-r15; \17\18mov.l @(20,r15),r4; \19sts pr, r52021#define MCOUNT_LEAVE() \22lds.l @r15+, pr; \23mov.l @r15+, r7; \24mov.l @r15+, r6; \25mov.l @r15+, r5; \26rts; \27mov.l @r15+, r42829#ifdef CONFIG_STACK_DEBUG30/*31* Perform diagnostic checks on the state of the kernel stack.32*33* Check for stack overflow. If there is less than 1KB free34* then it has overflowed.35*36* Make sure the stack pointer contains a valid address. Valid37* addresses for kernel stacks are anywhere after the bss38* (after __bss_stop) and anywhere in init_thread_union (init_stack).39*/40#define STACK_CHECK() \41mov #(THREAD_SIZE >> 10), r0; \42shll8 r0; \43shll2 r0; \44\45/* r1 = sp & (THREAD_SIZE - 1) */ \46mov #-1, r1; \47add r0, r1; \48and r15, r1; \49\50mov #TI_SIZE, r3; \51mov #(STACK_WARN >> 8), r2; \52shll8 r2; \53add r3, r2; \54\55/* Is the stack overflowing? */ \56cmp/hi r2, r1; \57bf stack_panic; \58\59/* If sp > __bss_stop then we're OK. */ \60mov.l .L_ebss, r1; \61cmp/hi r1, r15; \62bt 1f; \63\64/* If sp < init_stack, we're not OK. */ \65mov.l .L_init_thread_union, r1; \66cmp/hs r1, r15; \67bf stack_panic; \68\69/* If sp > init_stack && sp < __bss_stop, not OK. */ \70add r0, r1; \71cmp/hs r1, r15; \72bt stack_panic; \731:74#else75#define STACK_CHECK()76#endif /* CONFIG_STACK_DEBUG */7778.align 279.globl _mcount80.type _mcount,@function81.globl mcount82.type mcount,@function83_mcount:84mcount:85STACK_CHECK()8687#ifndef CONFIG_FUNCTION_TRACER88rts89nop90#else91MCOUNT_ENTER()9293#ifdef CONFIG_DYNAMIC_FTRACE94.globl mcount_call95mcount_call:96mov.l .Lftrace_stub, r697#else98mov.l .Lftrace_trace_function, r699mov.l ftrace_stub, r7100cmp/eq r6, r7101bt skip_trace102mov.l @r6, r6103#endif104105jsr @r6106nop107108#ifdef CONFIG_FUNCTION_GRAPH_TRACER109mov.l .Lftrace_graph_return, r6110mov.l .Lftrace_stub, r7111cmp/eq r6, r7112bt 1f113114mov.l .Lftrace_graph_caller, r0115jmp @r0116nop1171181:119mov.l .Lftrace_graph_entry, r6120mov.l .Lftrace_graph_entry_stub, r7121cmp/eq r6, r7122bt skip_trace123124mov.l .Lftrace_graph_caller, r0125jmp @r0126nop127128.align 2129.Lftrace_graph_return:130.long ftrace_graph_return131.Lftrace_graph_entry:132.long ftrace_graph_entry133.Lftrace_graph_entry_stub:134.long ftrace_graph_entry_stub135.Lftrace_graph_caller:136.long ftrace_graph_caller137#endif /* CONFIG_FUNCTION_GRAPH_TRACER */138139.globl skip_trace140skip_trace:141MCOUNT_LEAVE()142143.align 2144.Lftrace_trace_function:145.long ftrace_trace_function146147#ifdef CONFIG_DYNAMIC_FTRACE148#ifdef CONFIG_FUNCTION_GRAPH_TRACER149/*150* NOTE: Do not move either ftrace_graph_call or ftrace_caller151* as this will affect the calculation of GRAPH_INSN_OFFSET.152*/153.globl ftrace_graph_call154ftrace_graph_call:155mov.l .Lskip_trace, r0156jmp @r0157nop158159.align 2160.Lskip_trace:161.long skip_trace162#endif /* CONFIG_FUNCTION_GRAPH_TRACER */163164.globl ftrace_caller165ftrace_caller:166MCOUNT_ENTER()167168.globl ftrace_call169ftrace_call:170mov.l .Lftrace_stub, r6171jsr @r6172nop173174#ifdef CONFIG_FUNCTION_GRAPH_TRACER175bra ftrace_graph_call176nop177#else178MCOUNT_LEAVE()179#endif /* CONFIG_FUNCTION_GRAPH_TRACER */180#endif /* CONFIG_DYNAMIC_FTRACE */181182.align 2183184/*185* NOTE: From here on the locations of the .Lftrace_stub label and186* ftrace_stub itself are fixed. Adding additional data here will skew187* the displacement for the memory table and break the block replacement.188* Place new labels either after the ftrace_stub body, or before189* ftrace_caller. You have been warned.190*/191.Lftrace_stub:192.long ftrace_stub193194.globl ftrace_stub195ftrace_stub:196rts197nop198199#ifdef CONFIG_FUNCTION_GRAPH_TRACER200.globl ftrace_graph_caller201ftrace_graph_caller:202mov.l 2f, r1203jmp @r1204nop2051:206/*207* MCOUNT_ENTER() pushed 5 registers onto the stack, so208* the stack address containing our return address is209* r15 + 20.210*/211mov #20, r0212add r15, r0213mov r0, r4214215mov.l .Lprepare_ftrace_return, r0216jsr @r0217nop218219MCOUNT_LEAVE()220221.align 22222: .long skip_trace223.Lprepare_ftrace_return:224.long prepare_ftrace_return225226.globl return_to_handler227return_to_handler:228/*229* Save the return values.230*/231mov.l r0, @-r15232mov.l r1, @-r15233234mov #0, r4235236mov.l .Lftrace_return_to_handler, r0237jsr @r0238nop239240/*241* The return value from ftrace_return_handler has the real242* address that we should return to.243*/244lds r0, pr245mov.l @r15+, r1246rts247mov.l @r15+, r0248249250.align 2251.Lftrace_return_to_handler:252.long ftrace_return_to_handler253#endif /* CONFIG_FUNCTION_GRAPH_TRACER */254#endif /* CONFIG_FUNCTION_TRACER */255256#ifdef CONFIG_STACK_DEBUG257.globl stack_panic258stack_panic:259mov.l .Ldump_stack, r0260jsr @r0261nop262263mov.l .Lpanic, r0264jsr @r0265mov.l .Lpanic_s, r4266267rts268nop269270.align 2271.L_init_thread_union:272.long init_thread_union273.L_ebss:274.long __bss_stop275.Lpanic:276.long panic277.Lpanic_s:278.long .Lpanic_str279.Ldump_stack:280.long dump_stack281282.section .rodata283.align 2284.Lpanic_str:285.string "Stack error"286#endif /* CONFIG_STACK_DEBUG */287288289