Skip to content

Commit 6e7c18f

Browse files
author
Fox Snowpatch
committed
1 parent 56e2adc commit 6e7c18f

30 files changed

+2098
-200
lines changed

arch/Kconfig

+6
Original file line numberDiff line numberDiff line change
@@ -1643,4 +1643,10 @@ config CC_HAS_SANE_FUNCTION_ALIGNMENT
16431643
config ARCH_NEED_CMPXCHG_1_EMU
16441644
bool
16451645

1646+
config ARCH_WANTS_PRE_LINK_VMLINUX
1647+
def_bool n
1648+
help
1649+
An architecture can select this if it provides arch/<arch>/tools/Makefile
1650+
with .arch.vmlinux.o target to be linked into vmlinux.
1651+
16461652
endmenu

arch/powerpc/Kbuild

+1-1
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

+22-1
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ config PPC
234234
select HAVE_DEBUG_STACKOVERFLOW
235235
select HAVE_DYNAMIC_FTRACE
236236
select HAVE_DYNAMIC_FTRACE_WITH_ARGS if ARCH_USING_PATCHABLE_FUNCTION_ENTRY || MPROFILE_KERNEL || PPC32
237+
select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if PPC_FTRACE_OUT_OF_LINE || (PPC32 && ARCH_USING_PATCHABLE_FUNCTION_ENTRY)
238+
select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS
237239
select HAVE_DYNAMIC_FTRACE_WITH_REGS if ARCH_USING_PATCHABLE_FUNCTION_ENTRY || MPROFILE_KERNEL || PPC32
238240
select HAVE_EBPF_JIT
239241
select HAVE_EFFICIENT_UNALIGNED_ACCESS
@@ -243,7 +245,7 @@ config PPC
243245
select HAVE_FUNCTION_DESCRIPTORS if PPC64_ELF_ABI_V1
244246
select HAVE_FUNCTION_ERROR_INJECTION
245247
select HAVE_FUNCTION_GRAPH_TRACER
246-
select HAVE_FUNCTION_TRACER if PPC64 || (PPC32 && CC_IS_GCC)
248+
select HAVE_FUNCTION_TRACER if !COMPILE_TEST && (PPC64 || (PPC32 && CC_IS_GCC))
247249
select HAVE_GCC_PLUGINS if GCC_VERSION >= 50200 # plugin support on gcc <= 5.1 is buggy on PPC
248250
select HAVE_GENERIC_VDSO
249251
select HAVE_HARDLOCKUP_DETECTOR_ARCH if PPC_BOOK3S_64 && SMP
@@ -272,6 +274,8 @@ config PPC
272274
select HAVE_REGS_AND_STACK_ACCESS_API
273275
select HAVE_RELIABLE_STACKTRACE
274276
select HAVE_RSEQ
277+
select HAVE_SAMPLE_FTRACE_DIRECT if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
278+
select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
275279
select HAVE_SETUP_PER_CPU_AREA if PPC64
276280
select HAVE_SOFTIRQ_ON_OWN_STACK
277281
select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2)
@@ -567,6 +571,23 @@ config ARCH_USING_PATCHABLE_FUNCTION_ENTRY
567571
def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh $(CC) -mlittle-endian) if PPC64 && CPU_LITTLE_ENDIAN
568572
def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh $(CC) -mbig-endian) if PPC64 && CPU_BIG_ENDIAN
569573

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

arch/powerpc/Makefile

+8
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

+8
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

+32-1
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

+5
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

+14
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

+11
Original file line numberDiff line numberDiff line change
@@ -674,5 +674,16 @@ int main(void)
674674
DEFINE(BPT_SIZE, BPT_SIZE);
675675
#endif
676676

677+
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
678+
DEFINE(FTRACE_OOL_STUB_SIZE, sizeof(struct ftrace_ool_stub));
679+
#endif
680+
681+
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
682+
OFFSET(FTRACE_OPS_FUNC, ftrace_ops, func);
683+
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
684+
OFFSET(FTRACE_OPS_DIRECT_CALL, ftrace_ops, direct_call);
685+
#endif
686+
#endif
687+
677688
return 0;
678689
}

arch/powerpc/kernel/kprobes.c

+8-10
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

arch/powerpc/kernel/module_64.c

+57-9
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,9 @@ static int relacmp(const void *_x, const void *_y)
205205

206206
/* Get size of potential trampolines required. */
207207
static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
208-
const Elf64_Shdr *sechdrs)
208+
const Elf64_Shdr *sechdrs,
209+
char *secstrings,
210+
struct module *me)
209211
{
210212
/* One extra reloc so it's always 0-addr terminated */
211213
unsigned long relocs = 1;
@@ -241,13 +243,25 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
241243
}
242244
}
243245

244-
#ifdef CONFIG_DYNAMIC_FTRACE
245-
/* make the trampoline to the ftrace_caller */
246-
relocs++;
247-
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
248-
/* an additional one for ftrace_regs_caller */
249-
relocs++;
250-
#endif
246+
/* stubs for ftrace_caller and ftrace_regs_caller */
247+
relocs += IS_ENABLED(CONFIG_DYNAMIC_FTRACE) + IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS);
248+
249+
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
250+
/* stubs for the function tracer */
251+
for (i = 1; i < hdr->e_shnum; i++) {
252+
if (!strcmp(secstrings + sechdrs[i].sh_name, "__patchable_function_entries")) {
253+
me->arch.ool_stub_count = sechdrs[i].sh_size / sizeof(unsigned long);
254+
me->arch.ool_stub_index = 0;
255+
relocs += roundup(me->arch.ool_stub_count * sizeof(struct ftrace_ool_stub),
256+
sizeof(struct ppc64_stub_entry)) /
257+
sizeof(struct ppc64_stub_entry);
258+
break;
259+
}
260+
}
261+
if (i == hdr->e_shnum) {
262+
pr_err("%s: doesn't contain __patchable_function_entries.\n", me->name);
263+
return -ENOEXEC;
264+
}
251265
#endif
252266

253267
pr_debug("Looks like a total of %lu stubs, max\n", relocs);
@@ -460,7 +474,7 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
460474
#endif
461475

462476
/* Override the stubs size */
463-
sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs);
477+
sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs, secstrings, me);
464478

465479
return 0;
466480
}
@@ -1085,6 +1099,37 @@ int module_trampoline_target(struct module *mod, unsigned long addr,
10851099
return 0;
10861100
}
10871101

1102+
static int setup_ftrace_ool_stubs(const Elf64_Shdr *sechdrs, unsigned long addr, struct module *me)
1103+
{
1104+
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
1105+
unsigned int i, total_stubs, num_stubs;
1106+
struct ppc64_stub_entry *stub;
1107+
1108+
total_stubs = sechdrs[me->arch.stubs_section].sh_size / sizeof(*stub);
1109+
num_stubs = roundup(me->arch.ool_stub_count * sizeof(struct ftrace_ool_stub),
1110+
sizeof(struct ppc64_stub_entry)) / sizeof(struct ppc64_stub_entry);
1111+
1112+
/* Find the next available entry */
1113+
stub = (void *)sechdrs[me->arch.stubs_section].sh_addr;
1114+
for (i = 0; stub_func_addr(stub[i].funcdata); i++)
1115+
if (WARN_ON(i >= total_stubs))
1116+
return -1;
1117+
1118+
if (WARN_ON(i + num_stubs > total_stubs))
1119+
return -1;
1120+
1121+
stub += i;
1122+
me->arch.ool_stubs = (struct ftrace_ool_stub *)stub;
1123+
1124+
/* reserve stubs */
1125+
for (i = 0; i < num_stubs; i++)
1126+
if (patch_u32((void *)&stub->funcdata, PPC_RAW_NOP()))
1127+
return -1;
1128+
#endif
1129+
1130+
return 0;
1131+
}
1132+
10881133
int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
10891134
{
10901135
mod->arch.tramp = stub_for_addr(sechdrs,
@@ -1103,6 +1148,9 @@ int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
11031148
if (!mod->arch.tramp)
11041149
return -ENOENT;
11051150

1151+
if (setup_ftrace_ool_stubs(sechdrs, mod->arch.tramp, mod))
1152+
return -ENOENT;
1153+
11061154
return 0;
11071155
}
11081156
#endif

arch/powerpc/kernel/trace/Makefile

+7-4
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
99
CFLAGS_REMOVE_ftrace_64_pg.o = $(CC_FLAGS_FTRACE)
1010
endif
1111

12-
obj32-$(CONFIG_FUNCTION_TRACER) += ftrace.o ftrace_entry.o
13-
ifdef CONFIG_MPROFILE_KERNEL
14-
obj64-$(CONFIG_FUNCTION_TRACER) += ftrace.o ftrace_entry.o
12+
ifdef CONFIG_FUNCTION_TRACER
13+
obj32-y += ftrace.o ftrace_entry.o
14+
ifeq ($(CONFIG_MPROFILE_KERNEL)$(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY),)
15+
obj64-y += ftrace_64_pg.o ftrace_64_pg_entry.o
1516
else
16-
obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_64_pg.o ftrace_64_pg_entry.o
17+
obj64-y += ftrace.o ftrace_entry.o
18+
endif
1719
endif
20+
1821
obj-$(CONFIG_TRACING) += trace_clock.o
1922

2023
obj-$(CONFIG_PPC64) += $(obj64-y)

0 commit comments

Comments
 (0)