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