arch/powerpc/kernel/trace/ftrace_entry.S

Source file repositories/reference/linux-study-clean/arch/powerpc/kernel/trace/ftrace_entry.S

File Facts

System
Linux kernel
Corpus path
arch/powerpc/kernel/trace/ftrace_entry.S
Extension
.S
Size
11141 bytes
Lines
480
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

#include <linux/export.h>
#include <linux/magic.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/ftrace.h>
#include <asm/ppc-opcode.h>
#include <asm/thread_info.h>
#include <asm/bug.h>
#include <asm/ptrace.h>

/*
 *
 * ftrace_caller()/ftrace_regs_caller() is the function that replaces _mcount()
 * when ftrace is active.
 *
 * We arrive here after a function A calls function B, and we are the trace
 * function for B. When we enter r1 points to A's stack frame, B has not yet
 * had a chance to allocate one yet.
 *
 * Additionally r2 may point either to the TOC for A, or B, depending on
 * whether B did a TOC setup sequence before calling us.
 *
 * On entry the LR points back to the _mcount() call site, and r0 holds the
 * saved LR as it was on entry to B, ie. the original return address at the
 * call site in A.
 *
 * Our job is to save the register state into a struct pt_regs (on the stack)
 * and then arrange for the ftrace function to be called.
 */
.macro	ftrace_regs_entry allregs
	/* Create a minimal stack frame for representing B */
	PPC_STLU	r1, -STACK_FRAME_MIN_SIZE(r1)

	/* Create our stack frame + pt_regs */
	PPC_STLU	r1,-SWITCH_FRAME_SIZE(r1)

	.if \allregs == 1
	SAVE_GPRS(11, 12, r1)
	.endif

	/* Get the _mcount() call site out of LR */
	mflr	r11

#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
	/* Load the ftrace_op */
	PPC_LL	r12, -(MCOUNT_INSN_SIZE*2 + SZL)(r11)

	/* Load direct_call from the ftrace_op */
	PPC_LL	r12, FTRACE_OPS_DIRECT_CALL(r12)
	PPC_LCMPI r12, 0
	.if \allregs == 1
	bne	.Lftrace_direct_call_regs
	.else
	bne	.Lftrace_direct_call
	.endif
#endif

	/* Save the previous LR in pt_regs->link */
	PPC_STL	r0, _LINK(r1)
	/* Also save it in A's stack frame */
	PPC_STL	r0, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE+LRSAVE(r1)

	/* Save all gprs to pt_regs */
	SAVE_GPR(0, r1)
	SAVE_GPRS(3, 10, r1)

#ifdef CONFIG_PPC64
	/* Ok to continue? */
	lbz	r3, PACA_FTRACE_ENABLED(r13)
	cmpdi	r3, 0

Annotation

Implementation Notes