ppc64le: dynamic ftrace and kgraft support
Subsystems (7)
cover ppc64le: dynamic ftrace and kgraft support
Here's an initial version of dynamic ftrace for ABIv2 (ppc64le), the code maturity is somewhere between proof of concept and pre-alpha. I have split it into 4 parts, for ftrace and kgraft, a configuration enablement and the actual code, respectively.
Please have a look and tell me whether this is the way to go.
Torsten
Re: [PATCH v0 1/4] ppc64le: dynamic ftrace
I'm pretty sure not everything is ifdef'd properly, and the FIXME needs to be solved in order to disable ftracing again. Built upon some original code by Vojtech Pavlik.
arch/powerpc/include/asm/ftrace.h +5 -0
@@ -46,6 +46,8 @@extern void _mcount (void );#ifdef CONFIG_DYNAMIC_FTRACE +# define FTRACE_ADDR ((unsigned long)ftrace_caller+8) +# define FTRACE_REGS_ADDR FTRACE_ADDRstatic inline unsigned long ftrace_call_adjust (unsigned long addr) {/* reloction of mcount call site is the same as the address */
@@ -57,6 +58,9 @@ struct dyn_arch_ftrace {#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* __ASSEMBLY__ */ +#ifdef CONFIG_DYNAMIC_FTRACE +#define ARCH_SUPPORTS_FTRACE_OPS 1 +#endif #endif #if defined(CONFIG_FTRACE_SYSCALLS ) && defined(CONFIG_PPC64 ) && !defined(__ASSEMBLY__)
arch/powerpc/kernel/entry_64.S +92 -20
144 lines not on this page · raw message
arch/powerpc/kernel/ftrace.c +60 -9
123 lines not on this page · raw message
arch/powerpc/kernel/module_64.c +30 -3
@@ -140,12 +140,22 @@ static u32 ppc64_stub_insns[] = {0x4e800420 /* bctr */ }; +/* In case of _mcount calls or dynamic ftracing, Do not save the +current callee's TOC (in R2) again into the original caller's stack +frame during this trampoline hop. The stack frame already holds +that of the original caller. _mcount and ftrace_caller will take +care of this TOC value themselves. +*/ +#define SQUASH_TOC_SAVE_INSN (trampoline_addr) \ + ((struct ppc64_stub_entry*)(trampoline_addr))-> \ + jump[2] = PPC_INST_NOP; +#ifdef CONFIG_DYNAMIC_FTRACE static u32 ppc64_stub_mask[] = {0xffff0000 ,0xffff0000 , -0xffffffff , +0x00000000 ,0xffffffff , #if !defined(_CALL_ELF) || _CALL_ELF != 2 0xffffffff,
@@ -172,6 +182,9 @@ bool is_module_trampoline(u32 *p)if ((insna & mask) != (insnb & mask))return false; } +if (insns[2 ] != ppc64_stub_insns[2 ] && + insns[2 ] !=PPC_INST_NOP ) +return false;return true; }
@@ -477,6 +490,14 @@ static unsigned long stub_for_addr(Elf64_Shdr *sechdrs,static int restore_r2 (u32 *instruction,struct module *me) {if (*instruction !=PPC_INST_NOP ) { + +/* -mprofile_kernel sequence starting with mflr r0; std r0, LRSAVE(r1) */ +if (instruction[-3 ] ==0x7c0802a6 && instruction[-2 ] ==0xf8010010 ) { +/* Nothing to be done here, it's a _mcount call location +and r2 will have to be restored in the _mcount function */ +return 2 ; + }; +printk ("%s: Expect noop after relocate, got %08x\n" , me->name, *instruction);return 0 ;
@@ -492,7 +513,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,unsigned int relsec, struct module *me) { - unsigned int i; + unsigned int i, r2;Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;Elf64_Sym *sym;unsigned long *location;
@@ -605,8 +626,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, value =stub_for_addr (sechdrs, value, me);if (!value)return -ENOENT ; -if (!restore_r2 ((u32 *)location +1 , me)) +if (!(r2 =restore_r2 ((u32 *)location +1 , me)))return -ENOEXEC ; +/* Squash the TOC saver for profiler calls */ +if (!strcmp ("_mcount" , strtab+sym->st_name)) +SQUASH_TOC_SAVE_INSN (value); }else value +=local_entry_offset (sym);
@@ -667,6 +691,9 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, me->arch.tramp =stub_for_addr (sechdrs, (unsigned long )ftrace_caller, me); +/* ftrace_caller will take care of the TOC; +do not clobber original caller's value. */ +SQUASH_TOC_SAVE_INSN (me->arch.tramp);#endif return 0 ;
PATCH 2/4 ppc64le: dynamic ftrace configuration options
In reply to Torsten DuweSwitch on -mprofile-kernel, and remove it again from directories involved in exception handling. This needs to be done more fine grained, of course.
Makefile +4 -1
@@ -732,7 +732,10 @@ ifdef CONFIG_FUNCTION_TRACER ifdef CONFIG_HAVE_FENTRY CC_USING_FENTRY := $(call cc-option, -mfentry -DCC_USING_FENTRY) endif -KBUILD_CFLAGS += -pg $(CC_USING_FENTRY) +ifdef CONFIG_HAVE_MPROFILE_KERNEL +CC_USING_MPROFILE_KERNEL := $(call cc-option, -mprofile-kernel -DCC_USING_MPROFILE_KERNEL) +endif +KBUILD_CFLAGS += -pg $(CC_USING_FENTRY) $(CC_USING_MPROFILE_KERNEL) KBUILD_AFLAGS += $(CC_USING_FENTRY) ifdef CONFIG_DYNAMIC_FTRACE ifdef CONFIG_HAVE_C_RECORDMCOUNT
arch/powerpc/Kconfig +2 -0
@@ -93,8 +93,10 @@ config PPC select OF_RESERVED_MEM select HAVE_FTRACE_MCOUNT_RECORD select HAVE_DYNAMIC_FTRACE + select HAVE_DYNAMIC_FTRACE_WITH_REGS select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_MPROFILE_KERNEL select SYSCTL_EXCEPTION_TRACE select ARCH_WANT_OPTIONAL_GPIOLIB select VIRT_TO_BUS if !PPC64
arch/powerpc/kernel/Makefile +6 -6
@@ -17,14 +17,14 @@ endif ifdef CONFIG_FUNCTION_TRACER # Do not trace early boot code -CFLAGS_REMOVE_cputable.o = -pg -mno-sched-epilog -CFLAGS_REMOVE_prom_init.o = -pg -mno-sched-epilog -CFLAGS_REMOVE_btext.o = -pg -mno-sched-epilog -CFLAGS_REMOVE_prom.o = -pg -mno-sched-epilog +CFLAGS_REMOVE_cputable.o = -pg -mno-sched-epilog -mprofile-kernel +CFLAGS_REMOVE_prom_init.o = -pg -mno-sched-epilog -mprofile-kernel +CFLAGS_REMOVE_btext.o = -pg -mno-sched-epilog -mprofile-kernel +CFLAGS_REMOVE_prom.o = -pg -mno-sched-epilog -mprofile-kernel # do not trace tracer code -CFLAGS_REMOVE_ftrace.o = -pg -mno-sched-epilog +CFLAGS_REMOVE_ftrace.o = -pg -mno-sched-epilog -mprofile-kernel # timers used by tracing -CFLAGS_REMOVE_time.o = -pg -mno-sched-epilog +CFLAGS_REMOVE_time.o = -pg -mno-sched-epilog -mprofile-kernel endif obj-y := cputable.o ptrace.o syscalls.o \
kernel/Makefile +3 -2
@@ -13,8 +13,9 @@ obj-y = fork.o exec_domain.o panic.o \ ifdef CONFIG_FUNCTION_TRACER # Do not trace debug files and internal ftrace files -CFLAGS_REMOVE_cgroup-debug.o = -pg -CFLAGS_REMOVE_irq_work.o = -pg +CFLAGS_REMOVE_cgroup-debug.o = -pg -mprofile-kernel +CFLAGS_REMOVE_irq_work.o = -pg -mprofile-kernel +CFLAGS_REMOVE_extable.o = -pg -mprofile-kernel endif # cond_syscall is currently not LTO compatible
kernel/locking/Makefile +4 -4
@@ -2,10 +2,10 @@ obj-y += mutex.o semaphore.o rwsem.o mcs_spinlock.o ifdef CONFIG_FUNCTION_TRACER -CFLAGS_REMOVE_lockdep.o = -pg -CFLAGS_REMOVE_lockdep_proc.o = -pg -CFLAGS_REMOVE_mutex-debug.o = -pg -CFLAGS_REMOVE_rtmutex-debug.o = -pg +CFLAGS_REMOVE_lockdep.o = -pg -mprofile-kernel +CFLAGS_REMOVE_lockdep_proc.o = -pg -mprofile-kernel +CFLAGS_REMOVE_mutex-debug.o = -pg -mprofile-kernel +CFLAGS_REMOVE_rtmutex-debug.o = -pg -mprofile-kernel endif obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
kernel/trace/Kconfig +5 -0
@@ -52,6 +52,11 @@ config HAVE_FENTRY help Arch supports the gcc options -pg with -mfentry +config HAVE_MPROFILE_KERNEL + bool + help + Arch supports the gcc options -pg with -mprofile-kernel + config HAVE_C_RECORDMCOUNT bool help
arch/powerpc/lib/Makefile +2 -2
@@ -6,8 +6,8 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) -CFLAGS_REMOVE_code-patching.o = -pg -CFLAGS_REMOVE_feature-fixups.o = -pg +CFLAGS_REMOVE_code-patching.o = -pg -mprofile-kernel +CFLAGS_REMOVE_feature-fixups.o = -pg -mprofile-kernel obj-y := string.o alloc.o \ crtsavres.o
arch/powerpc/mm/Makefile +5 -0
@@ -6,6 +6,11 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) +# needed for do_page_fault in fault.c : +KBUILD_CFLAGS := $(filter-out -mprofile-kernel, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS := $(filter-out -pg, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS := $(filter-out -DCC_USING_MPROFILE_KERNEL, $(KBUILD_CFLAGS)) + obj-y := fault.o mem.o pgtable.o gup.o mmap.o \ init_$(CONFIG_WORD_SIZE).o \ pgtable_$(CONFIG_WORD_SIZE).o
arch/powerpc/kernel/Makefile +3 -0
@@ -26,6 +26,9 @@ CFLAGS_REMOVE_ftrace.o = -pg -mno-sched-epilog -mprofile-kernel # timers used by tracing CFLAGS_REMOVE_time.o = -pg -mno-sched-epilog -mprofile-kernel endif +KBUILD_CFLAGS := $(filter-out -mprofile-kernel, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS := $(filter-out -pg, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS := $(filter-out -DCC_USING_MPROFILE_KERNEL, $(KBUILD_CFLAGS)) obj-y := cputable.o ptrace.o syscalls.o \ irq.o align.o signal_32.o pmc.o vdso.o \
kernel/Makefile +3 -0
@@ -17,6 +17,9 @@ CFLAGS_REMOVE_cgroup-debug.o = -pg -mprofile-kernel CFLAGS_REMOVE_irq_work.o = -pg -mprofile-kernel CFLAGS_REMOVE_extable.o = -pg -mprofile-kernel endif +KBUILD_CFLAGS := $(filter-out -mprofile-kernel, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS := $(filter-out -pg, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS := $(filter-out -DCC_USING_MPROFILE_KERNEL, $(KBUILD_CFLAGS)) # cond_syscall is currently not LTO compatible CFLAGS_sys_ni.o = $(DISABLE_LTO)
lib/Makefile +3 -0
@@ -6,6 +6,9 @@ ifdef CONFIG_FUNCTION_TRACER ORIG_CFLAGS := $(KBUILD_CFLAGS) KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS)) endif +KBUILD_CFLAGS := $(filter-out -mprofile-kernel, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS := $(filter-out -pg, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS := $(filter-out -DCC_USING_MPROFILE_KERNEL, $(KBUILD_CFLAGS)) lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o timerqueue.o\
mm/Makefile +4 -0
@@ -20,6 +20,10 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ interval_tree.o list_lru.o workingset.o \ iov_iter.o $(mmu-y) +KBUILD_CFLAGS := $(filter-out -mprofile-kernel, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS := $(filter-out -pg, $(KBUILD_CFLAGS)) +KBUILD_CFLAGS := $(filter-out -DCC_USING_MPROFILE_KERNEL, $(KBUILD_CFLAGS)) + obj-y += init-mm.o ifdef CONFIG_NO_BOOTMEM
PATCH 3/4 ppc64le: kgraft support
In reply to Torsten DuweThe kgraft hooks for ppc64. Just massaged a bit to get them to compile and not interfere. Feel free to test them if you're daring ;)
arch/powerpc/include/asm/kgraft.h new file +33 -0
@@ -0,0 +1,33 @@ +/* +* kGraft Online Kernel Patching +* +* Copyright (c) 2013-2014 SUSE +* Authors: Jiri Kosina +* Vojtech Pavlik +* Jiri Slaby +*/ + +/* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the Free +* Software Foundation; either version 2 of the License, or (at your option) +* any later version. +*/ + +#ifndef ASM_KGR_H +#define ASM_KGR_H + +#include <asm/ptrace.h> +#include <linux/stacktrace.h> + +static inline void kgr_set_regs_ip (struct pt_regs *regs,unsigned long ip) +{ + regs->link = ip; +} + +static inline bool kgr_needs_lazy_migration (struct task_struct *p) +{ +return true; +} + +#endif
arch/powerpc/include/asm/thread_info.h +6 -2
@@ -92,6 +92,7 @@ static inline struct thread_info *current_thread_info(void)TIF_NEED_RESCHED */ #define TIF_32BIT 4/* 32 bit binary */ #define TIF_RESTORE_TM 5/* need to restore TM FP/VEC/VSX */ +#define TIF_KGR_IN_PROGRESS 6/* kGraft patching in progress */ #define TIF_SYSCALL_AUDIT 7/* syscall auditing active */ #define TIF_SINGLESTEP 8/* singlestepping active */ #define TIF_NOHZ 9/* in adaptive nohz mode */
@@ -115,8 +117,10 @@ static inline struct thread_info *current_thread_info(void)#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)#define _TIF_32BIT (1<<TIF_32BIT)#define _TIF_RESTORE_TM (1<<TIF_RESTORE_TM) +#define _TIF_KGR_IN_PROGRESS (1<<TIF_KGR_IN_PROGRESS)#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) +#define _TIF_NOHZ (1<<TIF_NOHZ)#define _TIF_SECCOMP (1<<TIF_SECCOMP)#define _TIF_RESTOREALL (1<<TIF_RESTOREALL)#define _TIF_NOERROR (1<<TIF_NOERROR)
@@ -124,7 +128,7 @@ static inline struct thread_info *current_thread_info(void)#define _TIF_UPROBE (1<<TIF_UPROBE)#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)#define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE) -#define _TIF_NOHZ (1<<TIF_NOHZ) +#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \ _TIF_NOHZ)
@@ -132,7 +136,8 @@ static inline struct thread_info *current_thread_info(void)#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ _TIF_RESTORE_TM) -#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR) + +#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR|_TIF_KGR_IN_PROGRESS)/* Bits in local_flags */ /* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
arch/powerpc/kernel/entry_64.S +13 -2
@@ -151,8 +151,8 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) #endif CURRENT_THREAD_INFO(r11, r1) ld r10,TI_FLAGS(r11) - andi. r11,r10,_TIF_SYSCALL_T_OR_A - bne syscall_dotrace + andi. r10,r10,(_TIF_SYSCALL_T_OR_A|_TIF_KGR_IN_PROGRESS) + bne- syscall_precall .Lsyscall_dotrace_cont: cmpldi 0,r0,NR_syscalls bge- syscall_enosys
@@ -245,6 +245,17 @@ syscall_error: neg r3,r3 std r5,_CCR(r1) b .Lsyscall_error_cont + +syscall_precall: + andi. r10,r10,(_TIF_KGR_IN_PROGRESS) + beq+ syscall_dotrace + + addi r11,r11,TI_FLAGS +1: ldarx r12,0,r11 + andc r12,r12,r10 + stdcx. r12,0,r11 + bne- 1b + subi r11,r11,TI_FLAGS /* Traced system call support */ syscall_dotrace:
PATCH 4/4 ppc64le: kgraft config options
In reply to Torsten DuweEnable kgraft on ppc, fairly trivial.
arch/powerpc/Kconfig +3 -0
@@ -102,6 +104,7 @@ config PPC select HAVE_IOREMAP_PROT select HAVE_EFFICIENT_UNALIGNED_ACCESS if !CPU_LITTLE_ENDIAN select HAVE_KPROBES + select HAVE_KGRAFT select HAVE_ARCH_KGDB select HAVE_KRETPROBES select HAVE_ARCH_TRACEHOOK
@@ -291,6 +294,8 @@ source "init/Kconfig" source "kernel/Kconfig.freezer" +source "kernel/Kconfig.kgraft" + source "arch/powerpc/sysdev/Kconfig" source "arch/powerpc/platforms/Kconfig"