arch/powerpc/kernel/trace/ftrace.c
Source file repositories/reference/linux-study-clean/arch/powerpc/kernel/trace/ftrace.c
File Facts
- System
- Linux kernel
- Corpus path
arch/powerpc/kernel/trace/ftrace.c- Extension
.c- Size
- 19160 bytes
- Lines
- 697
- Domain
- Architecture Layer
- Bucket
- arch/powerpc
- 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.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/spinlock.hlinux/hardirq.hlinux/uaccess.hlinux/module.hlinux/ftrace.hlinux/percpu.hlinux/init.hlinux/list.hasm/cacheflush.hasm/text-patching.hasm/ftrace.hasm/syscall.hasm/inst.hasm/sections.h
Detected Declarations
function ftrace_call_adjustfunction ftrace_create_branch_instfunction ftrace_read_instfunction ftrace_validate_instfunction ftrace_modify_codefunction is_bl_opfunction find_ftrace_trampfunction ftrace_lookup_module_stubfunction ftrace_lookup_module_stubfunction ftrace_get_ool_stubfunction ftrace_get_call_instfunction ftrace_init_ool_stubfunction ftrace_rec_set_opsfunction ftrace_rec_set_nop_opsfunction ftrace_rec_update_opsfunction ftrace_rec_set_nop_opsfunction ftrace_rec_update_opsfunction ftrace_modify_callfunction ftrace_make_callfunction ftrace_make_nopfunction ftrace_replace_codefunction for_ftrace_rec_iterfunction ftrace_init_nopfunction ftrace_update_ftrace_funcfunction stop_machinefunction ftrace_free_init_trampfunction add_ftrace_trampfunction ftrace_dyn_arch_initfunction ftrace_graph_func
Annotated Snippet
if (!IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE)) {
addr += MCOUNT_INSN_SIZE;
if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
addr += MCOUNT_INSN_SIZE;
} else if (IS_ENABLED(CONFIG_CC_IS_CLANG) && IS_ENABLED(CONFIG_PPC64)) {
/*
* addr points to global entry point though the NOP was emitted at local
* entry point due to https://github.com/llvm/llvm-project/issues/163706
* Handle that here with ppc_function_entry() for kernel symbols while
* adjusting module addresses in the else case, by looking for the below
* module global entry point sequence:
* ld r2, -8(r12)
* add r2, r2, r12
*/
if (is_kernel_text(addr) || is_kernel_inittext(addr))
addr = ppc_function_entry((void *)addr);
else if ((ppc_inst_val(ppc_inst_read((u32 *)addr)) ==
PPC_RAW_LD(_R2, _R12, -8)) &&
(ppc_inst_val(ppc_inst_read((u32 *)(addr+4))) ==
PPC_RAW_ADD(_R2, _R2, _R12)))
addr += 8;
}
}
return addr;
}
static ppc_inst_t ftrace_create_branch_inst(unsigned long ip, unsigned long addr, int link)
{
ppc_inst_t op;
WARN_ON(!is_offset_in_branch_range(addr - ip));
create_branch(&op, (u32 *)ip, addr, link ? BRANCH_SET_LINK : 0);
return op;
}
static inline int ftrace_read_inst(unsigned long ip, ppc_inst_t *op)
{
if (copy_inst_from_kernel_nofault(op, (void *)ip)) {
pr_err("0x%lx: fetching instruction failed\n", ip);
return -EFAULT;
}
return 0;
}
static inline int ftrace_validate_inst(unsigned long ip, ppc_inst_t inst)
{
ppc_inst_t op;
int ret;
ret = ftrace_read_inst(ip, &op);
if (!ret && !ppc_inst_equal(op, inst)) {
pr_err("0x%lx: expected (%08lx) != found (%08lx)\n",
ip, ppc_inst_as_ulong(inst), ppc_inst_as_ulong(op));
ret = -EINVAL;
}
return ret;
}
static inline int ftrace_modify_code(unsigned long ip, ppc_inst_t old, ppc_inst_t new)
{
int ret = ftrace_validate_inst(ip, old);
if (!ret && !ppc_inst_equal(old, new))
ret = patch_instruction((u32 *)ip, new);
return ret;
}
static int is_bl_op(ppc_inst_t op)
{
return (ppc_inst_val(op) & ~PPC_LI_MASK) == PPC_RAW_BL(0);
}
static unsigned long find_ftrace_tramp(unsigned long ip)
{
int i;
for (i = 0; i < NUM_FTRACE_TRAMPS; i++)
if (!ftrace_tramps[i])
continue;
else if (is_offset_in_branch_range(ftrace_tramps[i] - ip))
return ftrace_tramps[i];
return 0;
}
Annotation
- Immediate include surface: `linux/spinlock.h`, `linux/hardirq.h`, `linux/uaccess.h`, `linux/module.h`, `linux/ftrace.h`, `linux/percpu.h`, `linux/init.h`, `linux/list.h`.
- Detected declarations: `function ftrace_call_adjust`, `function ftrace_create_branch_inst`, `function ftrace_read_inst`, `function ftrace_validate_inst`, `function ftrace_modify_code`, `function is_bl_op`, `function find_ftrace_tramp`, `function ftrace_lookup_module_stub`, `function ftrace_lookup_module_stub`, `function ftrace_get_ool_stub`.
- Atlas domain: Architecture Layer / arch/powerpc.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.