arch/powerpc/kernel/trace/ftrace_64_pg.c
Source file repositories/reference/linux-study-clean/arch/powerpc/kernel/trace/ftrace_64_pg.c
File Facts
- System
- Linux kernel
- Corpus path
arch/powerpc/kernel/trace/ftrace_64_pg.c- Extension
.c- Size
- 20999 bytes
- Lines
- 833
- 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.h
Detected Declarations
function ftrace_call_adjustfunction ftrace_call_replacefunction ftrace_modify_codefunction test_24bit_addrfunction is_bl_opfunction is_b_opfunction find_bl_targetfunction __ftrace_make_nopfunction __ftrace_make_nopfunction find_ftrace_trampfunction add_ftrace_trampfunction trampolinefunction __ftrace_make_nop_kernelfunction ftrace_make_nopfunction expected_nop_sequencefunction __ftrace_make_callfunction __ftrace_make_callfunction __ftrace_make_call_kernelfunction ftrace_make_callfunction __ftrace_modify_callfunction __ftrace_modify_callfunction ftrace_modify_callfunction ftrace_update_ftrace_funcfunction stop_machinefunction ftrace_free_init_trampfunction ftrace_dyn_arch_initfunction ftrace_modify_ftrace_graph_callerfunction ftrace_enable_ftrace_graph_callerfunction ftrace_disable_ftrace_graph_callerfunction __prepare_ftrace_returnfunction ftrace_graph_funcfunction prepare_ftrace_return
Annotated Snippet
if (copy_inst_from_kernel_nofault(&op, (void *)(ip - 4))) {
pr_err("Fetching instruction at %lx failed.\n", ip - 4);
return -EFAULT;
}
/* We expect either a mflr r0, or a std r0, LRSAVE(r1) */
if (!ppc_inst_equal(op, ppc_inst(PPC_RAW_MFLR(_R0))) &&
!ppc_inst_equal(op, ppc_inst(PPC_INST_STD_LR))) {
pr_err("Unexpected instruction %08lx around bl _mcount\n",
ppc_inst_as_ulong(op));
return -EINVAL;
}
} else if (IS_ENABLED(CONFIG_PPC64)) {
/*
* Check what is in the next instruction. We can see ld r2,40(r1), but
* on first pass after boot we will see mflr r0.
*/
if (copy_inst_from_kernel_nofault(&op, (void *)(ip + 4))) {
pr_err("Fetching op failed.\n");
return -EFAULT;
}
if (!ppc_inst_equal(op, ppc_inst(PPC_INST_LD_TOC))) {
pr_err("Expected %08lx found %08lx\n", PPC_INST_LD_TOC,
ppc_inst_as_ulong(op));
return -EINVAL;
}
}
/*
* When using -mprofile-kernel or PPC32 there is no load to jump over.
*
* Otherwise our original call site looks like:
*
* bl <tramp>
* ld r2,XX(r1)
*
* Milton Miller pointed out that we can not simply nop the branch.
* If a task was preempted when calling a trace function, the nops
* will remove the way to restore the TOC in r2 and the r2 TOC will
* get corrupted.
*
* Use a b +8 to jump over the load.
*/
if (IS_ENABLED(CONFIG_MPROFILE_KERNEL) || IS_ENABLED(CONFIG_PPC32))
pop = ppc_inst(PPC_RAW_NOP());
else
pop = ppc_inst(PPC_RAW_BRANCH(8)); /* b +8 */
if (patch_instruction((u32 *)ip, pop)) {
pr_err("Patching NOP failed.\n");
return -EPERM;
}
return 0;
}
#else
static int __ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr)
{
return 0;
}
#endif /* CONFIG_MODULES */
static unsigned long find_ftrace_tramp(unsigned long ip)
{
int i;
/*
* We have the compiler generated long_branch tramps at the end
* and we prefer those
*/
for (i = NUM_FTRACE_TRAMPS - 1; i >= 0; i--)
if (!ftrace_tramps[i])
continue;
else if (is_offset_in_branch_range(ftrace_tramps[i] - ip))
return ftrace_tramps[i];
return 0;
}
static int add_ftrace_tramp(unsigned long tramp)
{
int i;
for (i = 0; i < NUM_FTRACE_TRAMPS; i++)
if (!ftrace_tramps[i]) {
ftrace_tramps[i] = tramp;
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_call_replace`, `function ftrace_modify_code`, `function test_24bit_addr`, `function is_bl_op`, `function is_b_op`, `function find_bl_target`, `function __ftrace_make_nop`, `function __ftrace_make_nop`, `function find_ftrace_tramp`.
- 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.