arch/arm64/kernel/entry-ftrace.S

Source file repositories/reference/linux-study-clean/arch/arm64/kernel/entry-ftrace.S

File Facts

System
Linux kernel
Corpus path
arch/arm64/kernel/entry-ftrace.S
Extension
.S
Size
10110 bytes
Lines
358
Domain
Architecture Layer
Bucket
arch/arm64
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/linkage.h>
#include <linux/cfi_types.h>
#include <asm/asm-offsets.h>
#include <asm/assembler.h>
#include <asm/ftrace.h>
#include <asm/insn.h>

#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
/*
 * Due to -fpatchable-function-entry=2, the compiler has placed two NOPs before
 * the regular function prologue. For an enabled callsite, ftrace_init_nop() and
 * ftrace_make_call() have patched those NOPs to:
 *
 * 	MOV	X9, LR
 * 	BL	ftrace_caller
 *
 * Each instrumented function follows the AAPCS, so here x0-x8 and x18-x30 are
 * live (x18 holds the Shadow Call Stack pointer), and x9-x17 are safe to
 * clobber.
 *
 * We save the callsite's context into a struct ftrace_regs before invoking any
 * ftrace callbacks. So that we can get a sensible backtrace, we create frame
 * records for the callsite and the ftrace entry assembly. This is not
 * sufficient for reliable stacktrace: until we create the callsite stack
 * record, its caller is missing from the LR and existing chain of frame
 * records.
 */
SYM_CODE_START(ftrace_caller)
	bti	c

#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
	/*
	 * The literal pointer to the ops is at an 8-byte aligned boundary
	 * which is either 12 or 16 bytes before the BL instruction in the call
	 * site. See ftrace_call_adjust() for details.
	 *
	 * Therefore here the LR points at `literal + 16` or `literal + 20`,
	 * and we can find the address of the literal in either case by
	 * aligning to an 8-byte boundary and subtracting 16. We do the
	 * alignment first as this allows us to fold the subtraction into the
	 * LDR.
	 */
	bic	x11, x30, 0x7
	ldr	x11, [x11, #-(4 * AARCH64_INSN_SIZE)]		// op

#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
	/*
	 * If the op has a direct call, handle it immediately without
	 * saving/restoring registers.
	 */
	ldr	x17, [x11, #FTRACE_OPS_DIRECT_CALL]		// op->direct_call
	cbnz	x17, ftrace_caller_direct
#endif
#endif

	/* Save original SP */
	mov	x10, sp

	/* Make room for ftrace regs, plus two frame records */
	sub	sp, sp, #(FREGS_SIZE + 32)

	/* Save function arguments */
	stp	x0, x1, [sp, #FREGS_X0]
	stp	x2, x3, [sp, #FREGS_X2]
	stp	x4, x5, [sp, #FREGS_X4]
	stp	x6, x7, [sp, #FREGS_X6]
	str	x8,     [sp, #FREGS_X8]

#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
	str	xzr, [sp, #FREGS_DIRECT_TRAMP]

Annotation

Implementation Notes