arch/arm64/kernel/ftrace.c

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

File Facts

System
Linux kernel
Corpus path
arch/arm64/kernel/ftrace.c
Extension
.c
Size
16268 bytes
Lines
600
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: implementation source
Status
source 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

struct fregs_offset {
	const char *name;
	int offset;
};

#define FREGS_OFFSET(n, field)					\
{								\
	.name = n,						\
	.offset = offsetof(struct __arch_ftrace_regs, field),	\
}

static const struct fregs_offset fregs_offsets[] = {
	FREGS_OFFSET("x0", regs[0]),
	FREGS_OFFSET("x1", regs[1]),
	FREGS_OFFSET("x2", regs[2]),
	FREGS_OFFSET("x3", regs[3]),
	FREGS_OFFSET("x4", regs[4]),
	FREGS_OFFSET("x5", regs[5]),
	FREGS_OFFSET("x6", regs[6]),
	FREGS_OFFSET("x7", regs[7]),
	FREGS_OFFSET("x8", regs[8]),

	FREGS_OFFSET("x29", fp),
	FREGS_OFFSET("x30", lr),
	FREGS_OFFSET("lr", lr),

	FREGS_OFFSET("sp", sp),
	FREGS_OFFSET("pc", pc),
};

int ftrace_regs_query_register_offset(const char *name)
{
	for (int i = 0; i < ARRAY_SIZE(fregs_offsets); i++) {
		const struct fregs_offset *roff = &fregs_offsets[i];
		if (!strcmp(roff->name, name))
			return roff->offset;
	}

	return -EINVAL;
}
#endif

unsigned long ftrace_call_adjust(unsigned long addr)
{
	/*
	 * When using mcount, addr is the address of the mcount call
	 * instruction, and no adjustment is necessary.
	 */
	if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_ARGS))
		return addr;

	/*
	 * When using patchable-function-entry without pre-function NOPS, addr
	 * is the address of the first NOP after the function entry point.
	 *
	 * The compiler has either generated:
	 *
	 * addr+00:	func:	NOP		// To be patched to MOV X9, LR
	 * addr+04:		NOP		// To be patched to BL <caller>
	 *
	 * Or:
	 *
	 * addr-04:		BTI	C
	 * addr+00:	func:	NOP		// To be patched to MOV X9, LR
	 * addr+04:		NOP		// To be patched to BL <caller>
	 *
	 * We must adjust addr to the address of the NOP which will be patched
	 * to `BL <caller>`, which is at `addr + 4` bytes in either case.
	 *
	 */
	if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
		return addr + AARCH64_INSN_SIZE;

	/*
	 * When using patchable-function-entry with pre-function NOPs, addr is
	 * the address of the first pre-function NOP.
	 *
	 * Starting from an 8-byte aligned base, the compiler has either
	 * generated:
	 *
	 * addr+00:		NOP		// Literal (first 32 bits)
	 * addr+04:		NOP		// Literal (last 32 bits)
	 * addr+08:	func:	NOP		// To be patched to MOV X9, LR
	 * addr+12:		NOP		// To be patched to BL <caller>
	 *
	 * Or:
	 *
	 * addr+00:		NOP		// Literal (first 32 bits)
	 * addr+04:		NOP		// Literal (last 32 bits)
	 * addr+08:	func:	BTI	C

Annotation

Implementation Notes