/* * Ftrace support for Microblaze. * * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> * Copyright (C) 2009 PetaLogix * * Based on MIPS and PowerPC ftrace code * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details.
*/
#ifdef CONFIG_FUNCTION_GRAPH_TRACER /* * Hook the return address and push it in the stack of return addrs * in current thread info.
*/ void prepare_ftrace_return(unsignedlong *parent, unsignedlong self_addr)
{ unsignedlong old; int faulted; unsignedlong return_hooker = (unsignedlong)
&return_to_handler;
if (unlikely(ftrace_graph_is_dead())) return;
if (unlikely(atomic_read(¤t->tracing_graph_pause))) return;
/* * Protect against fault, even if it shouldn't * happen. This tool is too much intrusive to * ignore such a protection.
*/ asmvolatile(" 1: lwi %0, %2, 0;" \ "2: swi %3, %2, 0;" \ " addik %1, r0, 0;" \ "3:" \ " .section .fixup, \"ax\";" \ "4: brid 3b;" \ " addik %1, r0, 1;" \ " .previous;" \ " .section __ex_table,\"a\";" \ " .word 1b,4b;" \ " .word 2b,4b;" \ " .previous;" \
: "=&r" (old), "=r" (faulted)
: "r" (parent), "r" (return_hooker)
);
#ifdef CONFIG_DYNAMIC_FTRACE /* save value to addr - it is save to do it in asm */ staticint ftrace_modify_code(unsignedlong addr, unsignedint value)
{ int faulted = 0;
int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsignedlong addr)
{ /* we have this part of code which we are working with * b000c000 imm -16384 * b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount> * 80000000 or r0, r0, r0 * * The first solution (!USE_FTRACE_NOP-could be called branch solution) * b000c000 bri 12 (0xC - jump to any other instruction) * b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount> * 80000000 or r0, r0, r0 * any other instruction * * The second solution (USE_FTRACE_NOP) - no jump just nops * 80000000 or r0, r0, r0 * 80000000 or r0, r0, r0 * 80000000 or r0, r0, r0
*/ int ret = 0;
#ifdef USE_FTRACE_NOP
ret = ftrace_modify_code(rec->ip, MICROBLAZE_NOP);
ret += ftrace_modify_code(rec->ip + 4, MICROBLAZE_NOP); #else/* USE_FTRACE_NOP */
ret = ftrace_modify_code(rec->ip, MICROBLAZE_BRI); #endif/* USE_FTRACE_NOP */ return ret;
}
/* I believe that first is called ftrace_make_nop before this function */ int ftrace_make_call(struct dyn_ftrace *rec, unsignedlong addr)
{ int ret;
pr_debug("%s: addr:0x%x, rec->ip: 0x%x, imm:0x%x\n",
__func__, (unsignedint)addr, (unsignedint)rec->ip, imm);
ret = ftrace_modify_code(rec->ip, imm); #ifdef USE_FTRACE_NOP
pr_debug("%s: bralid:0x%x\n", __func__, bralid);
ret += ftrace_modify_code(rec->ip + 4, bralid); #endif/* USE_FTRACE_NOP */ return ret;
}
int ftrace_update_ftrace_func(ftrace_func_t func)
{ unsignedlong ip = (unsignedlong)(&ftrace_call); unsignedint upper = (unsignedint)func; unsignedint lower = (unsignedint)func; int ret = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.