Skip to content

Commit e9b78a6

Browse files
committed
Merge: bpf, ftrace: Support BPF trampolines on powerpc
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/988 Backport patches for BPF trampoline support on powerpc. This enables various BPF features such as fentry/fexit probes. JIRA: https://issues.redhat.com/browse/RHEL-24555 Signed-off-by: Viktor Malik <vmalik@redhat.com> Approved-by: Jerome Marchand <jmarchan@redhat.com> Approved-by: Steve Best <sbest@redhat.com> Merged-by: Julio Faracco <jfaracco@redhat.com>
2 parents 5cb9af3 + 2eb31e2 commit e9b78a6

32 files changed

+2113
-218
lines changed

arch/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,4 +1729,10 @@ config CC_HAS_SANE_FUNCTION_ALIGNMENT
17291729
config ARCH_NEED_CMPXCHG_1_EMU
17301730
bool
17311731

1732+
config ARCH_WANTS_PRE_LINK_VMLINUX
1733+
bool
1734+
help
1735+
An architecture can select this if it provides arch/<arch>/tools/Makefile
1736+
with .arch.vmlinux.o target to be linked into vmlinux.
1737+
17321738
endmenu

arch/powerpc/Kbuild

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ obj-$(CONFIG_KEXEC_CORE) += kexec/
1919
obj-$(CONFIG_KEXEC_FILE) += purgatory/
2020

2121
# for cleaning
22-
subdir- += boot
22+
subdir- += boot tools

arch/powerpc/Kconfig

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ config PPC
236236
select HAVE_DEBUG_STACKOVERFLOW
237237
select HAVE_DYNAMIC_FTRACE
238238
select HAVE_DYNAMIC_FTRACE_WITH_ARGS if ARCH_USING_PATCHABLE_FUNCTION_ENTRY || MPROFILE_KERNEL || PPC32
239+
select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if PPC_FTRACE_OUT_OF_LINE || (PPC32 && ARCH_USING_PATCHABLE_FUNCTION_ENTRY)
240+
select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS
239241
select HAVE_DYNAMIC_FTRACE_WITH_REGS if ARCH_USING_PATCHABLE_FUNCTION_ENTRY || MPROFILE_KERNEL || PPC32
240242
select HAVE_EBPF_JIT
241243
select HAVE_EFFICIENT_UNALIGNED_ACCESS
@@ -245,7 +247,7 @@ config PPC
245247
select HAVE_FUNCTION_DESCRIPTORS if PPC64_ELF_ABI_V1
246248
select HAVE_FUNCTION_ERROR_INJECTION
247249
select HAVE_FUNCTION_GRAPH_TRACER
248-
select HAVE_FUNCTION_TRACER if PPC64 || (PPC32 && CC_IS_GCC)
250+
select HAVE_FUNCTION_TRACER if !COMPILE_TEST && (PPC64 || (PPC32 && CC_IS_GCC))
249251
select HAVE_GCC_PLUGINS if GCC_VERSION >= 50200 # plugin support on gcc <= 5.1 is buggy on PPC
250252
select HAVE_GENERIC_VDSO
251253
select HAVE_HARDLOCKUP_DETECTOR_ARCH if PPC_BOOK3S_64 && SMP
@@ -276,6 +278,8 @@ config PPC
276278
select HAVE_REGS_AND_STACK_ACCESS_API
277279
select HAVE_RELIABLE_STACKTRACE
278280
select HAVE_RSEQ
281+
select HAVE_SAMPLE_FTRACE_DIRECT if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
282+
select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
279283
select HAVE_SETUP_PER_CPU_AREA if PPC64
280284
select HAVE_SOFTIRQ_ON_OWN_STACK
281285
select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2)
@@ -572,6 +576,22 @@ config ARCH_USING_PATCHABLE_FUNCTION_ENTRY
572576
def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh $(CC) -mlittle-endian) if PPC64 && CPU_LITTLE_ENDIAN
573577
def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh $(CC) -mbig-endian) if PPC64 && CPU_BIG_ENDIAN
574578

579+
config PPC_FTRACE_OUT_OF_LINE
580+
def_bool PPC64 && ARCH_USING_PATCHABLE_FUNCTION_ENTRY
581+
select ARCH_WANTS_PRE_LINK_VMLINUX
582+
583+
config PPC_FTRACE_OUT_OF_LINE_NUM_RESERVE
584+
int "Number of ftrace out-of-line stubs to reserve within .text"
585+
depends on PPC_FTRACE_OUT_OF_LINE
586+
default 32768
587+
help
588+
Number of stubs to reserve for use by ftrace. This space is
589+
reserved within .text, and is distinct from any additional space
590+
added at the end of .text before the final vmlinux link. Set to
591+
zero to have stubs only be generated at the end of vmlinux (only
592+
if the size of vmlinux is less than 32MB). Set to a higher value
593+
if building vmlinux larger than 48MB.
594+
575595
config HOTPLUG_CPU
576596
bool "Support for enabling/disabling CPUs"
577597
depends on SMP && (PPC_PSERIES || \

arch/powerpc/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,15 @@ CC_FLAGS_NO_FPU := $(call cc-option,-msoft-float)
155155
ifdef CONFIG_FUNCTION_TRACER
156156
ifdef CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY
157157
KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
158+
ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
159+
CC_FLAGS_FTRACE := -fpatchable-function-entry=1
160+
else
161+
ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS # PPC32 only
162+
CC_FLAGS_FTRACE := -fpatchable-function-entry=3,1
163+
else
158164
CC_FLAGS_FTRACE := -fpatchable-function-entry=2
165+
endif
166+
endif
159167
else
160168
CC_FLAGS_FTRACE := -pg
161169
ifdef CONFIG_MPROFILE_KERNEL

arch/powerpc/Makefile.postlink

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ else
2424
$(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/relocs_check.sh "$(OBJDUMP)" "$(NM)" "$@"
2525
endif
2626

27+
quiet_cmd_ftrace_check = CHKFTRC $@
28+
cmd_ftrace_check = $(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/ftrace_check.sh "$(NM)" "$@"
29+
2730
# `@true` prevents complaint when there is nothing to be done
2831

2932
vmlinux: FORCE
@@ -34,6 +37,11 @@ endif
3437
ifdef CONFIG_RELOCATABLE
3538
$(call if_changed,relocs_check)
3639
endif
40+
ifdef CONFIG_FUNCTION_TRACER
41+
ifndef CONFIG_PPC64_ELF_ABI_V1
42+
$(call cmd,ftrace_check)
43+
endif
44+
endif
3745

3846
clean:
3947
rm -f .tmp_symbols.txt

arch/powerpc/include/asm/ftrace.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
2424
struct module;
2525
struct dyn_ftrace;
2626
struct dyn_arch_ftrace {
27-
struct module *mod;
27+
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
28+
/* pointer to the associated out-of-line stub */
29+
unsigned long ool_stub;
30+
#endif
2831
};
2932

3033
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
@@ -131,8 +134,36 @@ static inline u8 this_cpu_get_ftrace_enabled(void) { return 1; }
131134

132135
#ifdef CONFIG_FUNCTION_TRACER
133136
extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[];
137+
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
138+
struct ftrace_ool_stub {
139+
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
140+
struct ftrace_ops *ftrace_op;
141+
#endif
142+
u32 insn[4];
143+
} __aligned(sizeof(unsigned long));
144+
extern struct ftrace_ool_stub ftrace_ool_stub_text_end[], ftrace_ool_stub_text[],
145+
ftrace_ool_stub_inittext[];
146+
extern unsigned int ftrace_ool_stub_text_end_count, ftrace_ool_stub_text_count,
147+
ftrace_ool_stub_inittext_count;
148+
#endif
134149
void ftrace_free_init_tramp(void);
135150
unsigned long ftrace_call_adjust(unsigned long addr);
151+
152+
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
153+
/*
154+
* When an ftrace registered caller is tracing a function that is also set by a
155+
* register_ftrace_direct() call, it needs to be differentiated in the
156+
* ftrace_caller trampoline so that the direct call can be invoked after the
157+
* other ftrace ops. To do this, place the direct caller in the orig_gpr3 field
158+
* of pt_regs. This tells ftrace_caller that there's a direct caller.
159+
*/
160+
static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr)
161+
{
162+
struct pt_regs *regs = &fregs->regs;
163+
164+
regs->orig_gpr3 = addr;
165+
}
166+
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
136167
#else
137168
static inline void ftrace_free_init_tramp(void) { }
138169
static inline unsigned long ftrace_call_adjust(unsigned long addr) { return addr; }

arch/powerpc/include/asm/module.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ struct mod_arch_specific {
4747
#ifdef CONFIG_DYNAMIC_FTRACE
4848
unsigned long tramp;
4949
unsigned long tramp_regs;
50+
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
51+
struct ftrace_ool_stub *ool_stubs;
52+
unsigned int ool_stub_count;
53+
unsigned int ool_stub_index;
54+
#endif
5055
#endif
5156
};
5257

arch/powerpc/include/asm/ppc-opcode.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,12 +587,26 @@
587587
#define PPC_RAW_MTSPR(spr, d) (0x7c0003a6 | ___PPC_RS(d) | __PPC_SPR(spr))
588588
#define PPC_RAW_EIEIO() (0x7c0006ac)
589589

590+
/* bcl 20,31,$+4 */
591+
#define PPC_RAW_BCL4() (0x429f0005)
590592
#define PPC_RAW_BRANCH(offset) (0x48000000 | PPC_LI(offset))
591593
#define PPC_RAW_BL(offset) (0x48000001 | PPC_LI(offset))
592594
#define PPC_RAW_TW(t0, a, b) (0x7c000008 | ___PPC_RS(t0) | ___PPC_RA(a) | ___PPC_RB(b))
593595
#define PPC_RAW_TRAP() PPC_RAW_TW(31, 0, 0)
594596
#define PPC_RAW_SETB(t, bfa) (0x7c000100 | ___PPC_RT(t) | ___PPC_RA((bfa) << 2))
595597

598+
#ifdef CONFIG_PPC32
599+
#define PPC_RAW_STL PPC_RAW_STW
600+
#define PPC_RAW_STLU PPC_RAW_STWU
601+
#define PPC_RAW_LL PPC_RAW_LWZ
602+
#define PPC_RAW_CMPLI PPC_RAW_CMPWI
603+
#else
604+
#define PPC_RAW_STL PPC_RAW_STD
605+
#define PPC_RAW_STLU PPC_RAW_STDU
606+
#define PPC_RAW_LL PPC_RAW_LD
607+
#define PPC_RAW_CMPLI PPC_RAW_CMPDI
608+
#endif
609+
596610
/* Deal with instructions that older assemblers aren't aware of */
597611
#define PPC_BCCTR_FLUSH stringify_in_c(.long PPC_INST_BCCTR_FLUSH)
598612
#define PPC_CP_ABORT stringify_in_c(.long PPC_RAW_CP_ABORT)

arch/powerpc/kernel/asm-offsets.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,5 +677,16 @@ int main(void)
677677
DEFINE(BPT_SIZE, BPT_SIZE);
678678
#endif
679679

680+
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
681+
DEFINE(FTRACE_OOL_STUB_SIZE, sizeof(struct ftrace_ool_stub));
682+
#endif
683+
684+
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
685+
OFFSET(FTRACE_OPS_FUNC, ftrace_ops, func);
686+
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
687+
OFFSET(FTRACE_OPS_DIRECT_CALL, ftrace_ops, direct_call);
688+
#endif
689+
#endif
690+
680691
return 0;
681692
}

arch/powerpc/kernel/kprobes.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,24 +105,22 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
105105
return addr;
106106
}
107107

108-
static bool arch_kprobe_on_func_entry(unsigned long offset)
108+
static bool arch_kprobe_on_func_entry(unsigned long addr, unsigned long offset)
109109
{
110-
#ifdef CONFIG_PPC64_ELF_ABI_V2
111-
#ifdef CONFIG_KPROBES_ON_FTRACE
112-
return offset <= 16;
113-
#else
114-
return offset <= 8;
115-
#endif
116-
#else
110+
unsigned long ip = ftrace_location(addr);
111+
112+
if (ip)
113+
return offset <= (ip - addr);
114+
if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2) && !IS_ENABLED(CONFIG_PPC_KERNEL_PCREL))
115+
return offset <= 8;
117116
return !offset;
118-
#endif
119117
}
120118

121119
/* XXX try and fold the magic of kprobe_lookup_name() in this */
122120
kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset,
123121
bool *on_func_entry)
124122
{
125-
*on_func_entry = arch_kprobe_on_func_entry(offset);
123+
*on_func_entry = arch_kprobe_on_func_entry(addr, offset);
126124
return (kprobe_opcode_t *)(addr + offset);
127125
}
128126

0 commit comments

Comments
 (0)