xref: /openbmc/linux/arch/microblaze/kernel/mcount.S (revision e5451c8f8330e03ad3cfa16048b4daf961af434f)
12fd7c761SMichal Simek/*
22fd7c761SMichal Simek * Low-level ftrace handling
32fd7c761SMichal Simek *
42fd7c761SMichal Simek * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
52fd7c761SMichal Simek * Copyright (C) 2009 PetaLogix
62fd7c761SMichal Simek *
72fd7c761SMichal Simek * This file is subject to the terms and conditions of the GNU General
82fd7c761SMichal Simek * Public License. See the file COPYING in the main directory of this
92fd7c761SMichal Simek * archive for more details.
102fd7c761SMichal Simek */
112fd7c761SMichal Simek
122fd7c761SMichal Simek#include <linux/linkage.h>
132fd7c761SMichal Simek
142fd7c761SMichal Simek#define NOALIGN_ENTRY(name)	.globl name; name:
152fd7c761SMichal Simek
162fd7c761SMichal Simek/* FIXME MS: I think that I don't need to save all regs */
172fd7c761SMichal Simek#define SAVE_REGS		\
182fd7c761SMichal Simek	addik	r1, r1, -120;	\
192fd7c761SMichal Simek	swi	r2, r1, 4;	\
202fd7c761SMichal Simek	swi	r3, r1, 8;	\
212fd7c761SMichal Simek	swi	r4, r1, 12;	\
222fd7c761SMichal Simek	swi	r5, r1, 116;	\
232fd7c761SMichal Simek	swi	r6, r1, 16;	\
242fd7c761SMichal Simek	swi	r7, r1, 20;	\
252fd7c761SMichal Simek	swi	r8, r1, 24;	\
262fd7c761SMichal Simek	swi	r9, r1, 28;	\
272fd7c761SMichal Simek	swi	r10, r1, 32;	\
282fd7c761SMichal Simek	swi	r11, r1, 36;	\
292fd7c761SMichal Simek	swi	r12, r1, 40;	\
302fd7c761SMichal Simek	swi	r13, r1, 44;	\
312fd7c761SMichal Simek	swi	r14, r1, 48;	\
322fd7c761SMichal Simek	swi	r16, r1, 52;	\
332fd7c761SMichal Simek	swi	r17, r1, 56;	\
342fd7c761SMichal Simek	swi	r18, r1, 60;	\
352fd7c761SMichal Simek	swi	r19, r1, 64;	\
362fd7c761SMichal Simek	swi	r20, r1, 68;	\
372fd7c761SMichal Simek	swi	r21, r1, 72;	\
382fd7c761SMichal Simek	swi	r22, r1, 76;	\
392fd7c761SMichal Simek	swi	r23, r1, 80;	\
402fd7c761SMichal Simek	swi	r24, r1, 84;	\
412fd7c761SMichal Simek	swi	r25, r1, 88;	\
422fd7c761SMichal Simek	swi	r26, r1, 92;	\
432fd7c761SMichal Simek	swi	r27, r1, 96;	\
442fd7c761SMichal Simek	swi	r28, r1, 100;	\
452fd7c761SMichal Simek	swi	r29, r1, 104;	\
462fd7c761SMichal Simek	swi	r30, r1, 108;	\
472fd7c761SMichal Simek	swi	r31, r1, 112;
482fd7c761SMichal Simek
492fd7c761SMichal Simek#define RESTORE_REGS		\
502fd7c761SMichal Simek	lwi	r2, r1, 4;	\
512fd7c761SMichal Simek	lwi	r3, r1, 8;	\
522fd7c761SMichal Simek	lwi	r4, r1, 12;	\
532fd7c761SMichal Simek	lwi	r5, r1, 116;	\
542fd7c761SMichal Simek	lwi	r6, r1, 16;	\
552fd7c761SMichal Simek	lwi	r7, r1, 20;	\
562fd7c761SMichal Simek	lwi	r8, r1, 24;	\
572fd7c761SMichal Simek	lwi	r9, r1, 28;	\
582fd7c761SMichal Simek	lwi	r10, r1, 32;	\
592fd7c761SMichal Simek	lwi	r11, r1, 36;	\
602fd7c761SMichal Simek	lwi	r12, r1, 40;	\
612fd7c761SMichal Simek	lwi	r13, r1, 44;	\
622fd7c761SMichal Simek	lwi	r14, r1, 48;	\
632fd7c761SMichal Simek	lwi	r16, r1, 52;	\
642fd7c761SMichal Simek	lwi	r17, r1, 56;	\
652fd7c761SMichal Simek	lwi	r18, r1, 60;	\
662fd7c761SMichal Simek	lwi	r19, r1, 64;	\
672fd7c761SMichal Simek	lwi	r20, r1, 68;	\
682fd7c761SMichal Simek	lwi	r21, r1, 72;	\
692fd7c761SMichal Simek	lwi	r22, r1, 76;	\
702fd7c761SMichal Simek	lwi	r23, r1, 80;	\
712fd7c761SMichal Simek	lwi	r24, r1, 84;	\
722fd7c761SMichal Simek	lwi	r25, r1, 88;	\
732fd7c761SMichal Simek	lwi	r26, r1, 92;	\
742fd7c761SMichal Simek	lwi	r27, r1, 96;	\
752fd7c761SMichal Simek	lwi	r28, r1, 100;	\
762fd7c761SMichal Simek	lwi	r29, r1, 104;	\
772fd7c761SMichal Simek	lwi	r30, r1, 108;	\
782fd7c761SMichal Simek	lwi	r31, r1, 112;	\
792fd7c761SMichal Simek	addik	r1, r1, 120;
802fd7c761SMichal Simek
812fd7c761SMichal SimekENTRY(ftrace_stub)
822fd7c761SMichal Simek	rtsd	r15, 8;
832fd7c761SMichal Simek	nop;
842fd7c761SMichal Simek
852fd7c761SMichal SimekENTRY(_mcount)
867d241ff0SMichal Simek#ifdef CONFIG_DYNAMIC_FTRACE
877d241ff0SMichal SimekENTRY(ftrace_caller)
887d241ff0SMichal Simek	/* MS: It is just barrier which is removed from C code */
897d241ff0SMichal Simek	rtsd	r15, 8
907d241ff0SMichal Simek	nop
917d241ff0SMichal Simek#endif /* CONFIG_DYNAMIC_FTRACE */
922fd7c761SMichal Simek	SAVE_REGS
932fd7c761SMichal Simek	swi	r15, r1, 0;
94a0d3e665SMichal Simek#ifdef CONFIG_FUNCTION_GRAPH_TRACER
954f911b0dSMichal Simek#ifndef CONFIG_DYNAMIC_FTRACE
96a0d3e665SMichal Simek	lwi	r5, r0, ftrace_graph_return;
97a0d3e665SMichal Simek	addik	r6, r0, ftrace_stub; /* asm implementation */
98a0d3e665SMichal Simek	cmpu	r5, r5, r6; /* ftrace_graph_return != ftrace_stub */
99a0d3e665SMichal Simek	beqid	r5, end_graph_tracer;
100a0d3e665SMichal Simek	nop;
101a0d3e665SMichal Simek
102a0d3e665SMichal Simek	lwi	r6, r0, ftrace_graph_entry;
103a0d3e665SMichal Simek	addik	r5, r0, ftrace_graph_entry_stub; /* implemented in C */
104a0d3e665SMichal Simek	cmpu	r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */
105a0d3e665SMichal Simek	beqid	r5, end_graph_tracer;
106a0d3e665SMichal Simek	nop;
1074f911b0dSMichal Simek#else /* CONFIG_DYNAMIC_FTRACE */
1084f911b0dSMichal SimekNOALIGN_ENTRY(ftrace_call_graph)
1094f911b0dSMichal Simek	/* MS: jump over graph function - replaced from C code */
1104f911b0dSMichal Simek	bri	end_graph_tracer
1114f911b0dSMichal Simek#endif /* CONFIG_DYNAMIC_FTRACE */
112a0d3e665SMichal Simek	addik	r5, r1, 120; /* MS: load parent addr */
113a0d3e665SMichal Simek	addik	r6, r15, 0; /* MS: load current function addr */
114a0d3e665SMichal Simek	bralid	r15, prepare_ftrace_return;
115a0d3e665SMichal Simek	nop;
116a0d3e665SMichal Simek	/* MS: graph was taken that's why - can jump over function trace */
117a0d3e665SMichal Simek	brid	end;
118a0d3e665SMichal Simek	nop;
119a0d3e665SMichal Simekend_graph_tracer:
120a0d3e665SMichal Simek#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
1217d241ff0SMichal Simek#ifndef CONFIG_DYNAMIC_FTRACE
1222fd7c761SMichal Simek	/* MS: test function trace if is taken or not */
1232fd7c761SMichal Simek	lwi	r20, r0, ftrace_trace_function;
1242fd7c761SMichal Simek	addik	r6, r0, ftrace_stub;
1252fd7c761SMichal Simek	cmpu	r5, r20, r6; /* ftrace_trace_function != ftrace_stub */
1262fd7c761SMichal Simek	beqid	r5, end; /* MS: not taken -> jump over */
1272fd7c761SMichal Simek	nop;
1287d241ff0SMichal Simek#else /* CONFIG_DYNAMIC_FTRACE */
1297d241ff0SMichal SimekNOALIGN_ENTRY(ftrace_call)
1307d241ff0SMichal Simek/* instruction for setup imm FUNC_part1, addik r20, r0, FUNC_part2 */
1317d241ff0SMichal Simek	nop
1327d241ff0SMichal Simek	nop
1337d241ff0SMichal Simek#endif /* CONFIG_DYNAMIC_FTRACE */
1342fd7c761SMichal Simek/* static normal trace */
1352fd7c761SMichal Simek	lwi	r6, r1, 120; /* MS: load parent addr */
136*d65987a8SMichal Simek	addik	r5, r15, -4; /* MS: load current function addr */
1372fd7c761SMichal Simek	/* MS: here is dependency on previous code */
1382fd7c761SMichal Simek	brald	r15, r20; /* MS: jump to ftrace handler */
1392fd7c761SMichal Simek	nop;
1402fd7c761SMichal Simekend:
1412fd7c761SMichal Simek	lwi	r15, r1, 0;
1422fd7c761SMichal Simek	RESTORE_REGS
1432fd7c761SMichal Simek
1442fd7c761SMichal Simek	rtsd	r15, 8; /* MS: jump back */
1452fd7c761SMichal Simek	nop;
146a0d3e665SMichal Simek
147a0d3e665SMichal Simek#ifdef CONFIG_FUNCTION_GRAPH_TRACER
148a0d3e665SMichal SimekENTRY(return_to_handler)
149a0d3e665SMichal Simek	nop; /* MS: just barrier for rtsd r15, 8 */
150a0d3e665SMichal Simek	nop;
151a0d3e665SMichal Simek	SAVE_REGS
152a0d3e665SMichal Simek	swi	r15, r1, 0;
153a0d3e665SMichal Simek
154a0d3e665SMichal Simek	/* MS: find out returning address */
155a0d3e665SMichal Simek	bralid	r15, ftrace_return_to_handler;
156a0d3e665SMichal Simek	nop;
157a0d3e665SMichal Simek
158a0d3e665SMichal Simek	/* MS: return value from ftrace_return_to_handler is my returning addr
159a0d3e665SMichal Simek	 * must be before restore regs because I have to restore r3 content */
160a0d3e665SMichal Simek	addik	r15, r3, 0;
161a0d3e665SMichal Simek	RESTORE_REGS
162a0d3e665SMichal Simek
163a0d3e665SMichal Simek	rtsd	r15, 8; /* MS: jump back */
164a0d3e665SMichal Simek	nop;
165a0d3e665SMichal Simek#endif	/* CONFIG_FUNCTION_TRACER */
166