Skip to content

Commit db54c28

Browse files
hbathinimaddy-kerneldev
authored andcommitted
powerpc64/ftrace: workaround clang recording GEP in __patchable_function_entries
Support for -fpatchable-function-entry on ppc64le was added in Clang with [1]. However, when no prefix NOPs are specified - as is the case with CONFIG_PPC_FTRACE_OUT_OF_LINE - the first NOP is emitted at LEP, but Clang records the Global Entry Point (GEP) unlike GCC which does record the Local Entry Point (LEP). Issue [2] has been raised to align Clang's behavior with GCC. As a temporary workaround to ensure ftrace initialization works as expected with Clang, derive the LEP using ppc_function_entry() for kernel symbols and by looking for the below module GEP sequence for module addresses, until [2] is resolved: ld r2, -8(r12) add r2, r2, r12 [1] llvm/llvm-project#151569 [2] llvm/llvm-project#163706 Signed-off-by: Hari Bathini <hbathini@linux.ibm.com> Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com> Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com> Link: https://patch.msgid.link/20260127084926.34497-4-hbathini@linux.ibm.com
1 parent 875612a commit db54c28

1 file changed

Lines changed: 22 additions & 4 deletions

File tree

arch/powerpc/kernel/trace/ftrace.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,29 @@ unsigned long ftrace_call_adjust(unsigned long addr)
3737
if (addr >= (unsigned long)__exittext_begin && addr < (unsigned long)__exittext_end)
3838
return 0;
3939

40-
if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY) &&
41-
!IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE)) {
42-
addr += MCOUNT_INSN_SIZE;
43-
if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
40+
if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY)) {
41+
if (!IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE)) {
4442
addr += MCOUNT_INSN_SIZE;
43+
if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
44+
addr += MCOUNT_INSN_SIZE;
45+
} else if (IS_ENABLED(CONFIG_CC_IS_CLANG) && IS_ENABLED(CONFIG_PPC64)) {
46+
/*
47+
* addr points to global entry point though the NOP was emitted at local
48+
* entry point due to https://github.com/llvm/llvm-project/issues/163706
49+
* Handle that here with ppc_function_entry() for kernel symbols while
50+
* adjusting module addresses in the else case, by looking for the below
51+
* module global entry point sequence:
52+
* ld r2, -8(r12)
53+
* add r2, r2, r12
54+
*/
55+
if (is_kernel_text(addr) || is_kernel_inittext(addr))
56+
addr = ppc_function_entry((void *)addr);
57+
else if ((ppc_inst_val(ppc_inst_read((u32 *)addr)) ==
58+
PPC_RAW_LD(_R2, _R12, -8)) &&
59+
(ppc_inst_val(ppc_inst_read((u32 *)(addr+4))) ==
60+
PPC_RAW_ADD(_R2, _R2, _R12)))
61+
addr += 8;
62+
}
4563
}
4664

4765
return addr;

0 commit comments

Comments
 (0)