Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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] https://github.com/llvm/llvm-project/pull/151569
[2] https://github.com/llvm/llvm-project/issues/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

authored by

Hari Bathini and committed by
Madhavan Srinivasan
db54c287 875612a7

+22 -4
+22 -4
arch/powerpc/kernel/trace/ftrace.c
··· 37 37 if (addr >= (unsigned long)__exittext_begin && addr < (unsigned long)__exittext_end) 38 38 return 0; 39 39 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)) { 44 42 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 + } 45 63 } 46 64 47 65 return addr;