Skip to contentSkip to conversation

ftrace with regs + live patching for ppc64 LE (ABI v2)

PATCH Superseded Torsten Duwe 2 participants 11 messages Oct 26, 2015 – Oct 27, 2015

Subsystems (4)

v3 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

v3 cover ftrace with regs + live patching for ppc64 LE (ABI v2)

Hi all,

here is the current status of ftrace with regs, trace ops and live patching for ppc64le. It seems I broke the ftrace graph caller and I spent most of last week trying to fix it; Steven, maybe you could have a look? I startet out with -mprofile-kernel and now found that the ordinary -pg is very different. -mprofile-kernel only does the very bare minimal prologue (set TOC, save LR) and then calls _mcount, which poses some problems. I managed to get them resolved up to the point of the graph return ...

I tested intensively with the ftrace self tests, and, without the graph caller, this set passes all of them on ppc64le. I tried not to break BE, but may have missed an ifdef or two.

patch 2 (ftrace_modify_all_code default) is an independent prerequisite, I would even call it a fix -- please consider applying it even if you don't like the rest.

patch 5 has proven to be very useful during development; as mentioned earlier, many of these functions may get called during a recoverable fault. The whole recursion will probably terminate if all goes well, but I'd rather be defensive here.

Torsten Duwe (8):
ppc64le FTRACE_WITH_REGS implementation
ppc use ftrace_modify_all_code default
ppc64 ftrace_with_regs configuration variables
ppc64 ftrace_with_regs: spare early boot and low level ppc64 ftrace: disable profiling for some functions
ppc64 ftrace: disable profiling for some files
Implement kernel live patching for ppc64le (ABIv2)
Enable LIVEPATCH to be configured on ppc64le and add livepatch.o if it
is selected.

 arch/powerpc/Kconfig                 |   7 ++
 arch/powerpc/Makefile                |   7 ++
 arch/powerpc/include/asm/ftrace.h    |   5 ++
 arch/powerpc/include/asm/livepatch.h |  27 +++++++
 arch/powerpc/kernel/Makefile         |  13 +--
 arch/powerpc/kernel/entry_64.S       | 153 ++++++++++++++++++++++++++++++++++-
 arch/powerpc/kernel/ftrace.c         |  88 +++++++++++++++-----
 arch/powerpc/kernel/livepatch.c      |  20 +++++
 arch/powerpc/kernel/module_64.c      |  39 ++++++++-
 arch/powerpc/kernel/process.c        |   2 +-
 arch/powerpc/lib/Makefile            |   4 +-
 arch/powerpc/mm/fault.c              |   2 +-
 arch/powerpc/mm/hash_utils_64.c      |  18 ++---
 arch/powerpc/mm/hugetlbpage-hash64.c |   2 +-
 arch/powerpc/mm/hugetlbpage.c        |   4 +-
 arch/powerpc/mm/mem.c                |   2 +-
 arch/powerpc/mm/pgtable_64.c         |   2 +-
 arch/powerpc/mm/slb.c                |   6 +-
 arch/powerpc/mm/slice.c              |   8 +-
 kernel/trace/Kconfig                 |   5 ++
 20 files changed, 359 insertions(+), 55 deletions(-)
 create mode 100644 arch/powerpc/include/asm/livepatch.h
 create mode 100644 arch/powerpc/kernel/livepatch.c
Signature · 1 line
1.8.5.6
#1 lore raw

PATCH v3 1/8 ppc64le FTRACE_WITH_REGS implementation

Implement FTRACE_WITH_REGS for powerpc64, on ELF ABI v2. Initial work started by Vojtech Pavlik, used with permission.

* arch/powerpc/kernel/entry_64.S:
- enhance _mcount with a stub to support call sites generated by -mprofile-kernel. This is backward-compatible.
- Implement an effective ftrace_caller that works from within the kernel binary as well as from modules.
* arch/powerpc/kernel/ftrace.c:
- be prepared to deal with ppc64 ELF ABI v2, especially calls to _mcount that result from gcc -mprofile-kernel
- a little more error verbosity
* arch/powerpc/kernel/module_64.c:
- do not save the TOC pointer on the trampoline when the destination is ftrace_caller. This trampoline jump happens from a function prologue before a new stack frame is set up, so bad things may happen otherwise...
- relax is_module_trampoline() to recognise the modified trampoline.

---
 arch/powerpc/include/asm/ftrace.h |   5 ++
 arch/powerpc/kernel/entry_64.S    | 113 +++++++++++++++++++++++++++++++++++++-
 arch/powerpc/kernel/ftrace.c      |  72 +++++++++++++++++++++---
 arch/powerpc/kernel/module_64.c   |  39 ++++++++++++-
 4 files changed, 217 insertions(+), 12 deletions(-)
arch/powerpc/include/asm/ftrace.h +5 -0
index ef89b14..6eb9fbc 100644
@@ -46,6 +46,8 @@
 extern void _mcount(void);
 
 #ifdef CONFIG_DYNAMIC_FTRACE
+# define FTRACE_ADDR ((unsigned long)ftrace_caller)
+# define FTRACE_REGS_ADDR FTRACE_ADDR
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
        /* reloction of mcount call site is the same as the address */
@@ -58,6 +60,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 +112 -1

142 lines not on this page · raw message

arch/powerpc/kernel/ftrace.c +64 -8

120 lines not on this page · raw message

arch/powerpc/kernel/module_64.c +36 -3
index 6838451..e62c41f 100644
@@ -138,12 +138,21 @@ 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,
@@ -170,6 +179,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;
 }
@@ -475,6 +487,19 @@ 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 an _mcount
+			 * call location and r2 will have to be
+			 * restored in the _mcount function.
+			 */
+			return 2;
+		};
+
 		pr_err("%s: Expect noop after relocate, got %08x\n",
 		       me->name, *instruction);
 		return 0;
@@ -490,7 +515,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;
@@ -603,8 +628,12 @@ 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))
+				r2 = restore_r2((u32 *)location + 1, me);
+				if (!r2)
 					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);
 
@@ -665,6 +694,10 @@ 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;
Signature · 1 line
1.8.5.6
#2 lore raw
In reply to Torsten Duwe

* Makefile:
- globally use -mprofile-kernel in case it's configured.
* arch/powerpc/Kconfig / kernel/trace/Kconfig:
- declare that ppc64 HAVE_MPROFILE_KERNEL and HAVE_DYNAMIC_FTRACE_WITH_REGS, and use it.

---
 arch/powerpc/Kconfig  | 2 ++
 arch/powerpc/Makefile | 7 +++++++
 kernel/trace/Kconfig  | 5 +++++
 3 files changed, 14 insertions(+)
arch/powerpc/Kconfig +2 -0
index 9a7057e..0e6011c 100644
@@ -97,8 +97,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/Makefile +7 -0
index b9b4af2..25d0034 100644
@@ -133,6 +133,13 @@ else
 CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64
 endif
 
+ifeq ($(CONFIG_PPC64),y)
+ifdef CONFIG_HAVE_MPROFILE_KERNEL
+CC_FLAGS_FTRACE	:= -pg $(call cc-option,-mprofile-kernel)
+KBUILD_CPPFLAGS	+= -DCC_USING_MPROFILE_KERNEL
+endif
+endif
+
 CFLAGS-$(CONFIG_CELL_CPU) += $(call cc-option,-mcpu=cell)
 CFLAGS-$(CONFIG_POWER4_CPU) += $(call cc-option,-mcpu=power4)
 CFLAGS-$(CONFIG_POWER5_CPU) += $(call cc-option,-mcpu=power5)
kernel/trace/Kconfig +5 -0
index 1153c43..dbcb635 100644
@@ -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
Signature · 1 line
1.8.5.6
#3 lore raw
reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree…

Hi Torsten,

[auto build test ERROR on powerpc/next -- if it's inappropriate base, please suggest rules for selecting the more suitable base]

url:    https://github.com/0day-ci/linux/commits/Torsten-Duwe/Re-PATCH-v3-0-8-ftrace-with-regs-live-patching-for-ppc64-LE-ABI-v2/20151027-020058
config: powerpc-ppc6xx_defconfig (attached as .config)

reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=powerpc

All errors (new ones prefixed by >>):

kernel/built-in.o: In function `ftrace_get_addr_curr':

>> kernel/trace/ftrace.c:2286: undefined reference to `ftrace_regs_caller'
>> kernel/trace/ftrace.c:2286: undefined reference to `ftrace_regs_caller'
   kernel/built-in.o: In function `ftrace_get_addr_new':
   kernel/trace/ftrace.c:2254: undefined reference to `ftrace_regs_caller'
   kernel/trace/ftrace.c:2254: undefined reference to `ftrace_regs_caller'
   kernel/built-in.o: In function `__ftrace_replace_code':
>> kernel/trace/ftrace.c:2316: undefined reference to `ftrace_modify_call'
   kernel/built-in.o: In function `ftrace_get_addr_curr':
>> kernel/trace/ftrace.c:2286: undefined reference to `ftrace_regs_caller'
>> kernel/trace/ftrace.c:2286: undefined reference to `ftrace_regs_caller'
   kernel/built-in.o: In function `ftrace_get_addr_new':
   kernel/trace/ftrace.c:2254: undefined reference to `ftrace_regs_caller'
   kernel/trace/ftrace.c:2254: undefined reference to `ftrace_regs_caller'
   kernel/built-in.o: In function `ftrace_get_addr_curr':
>> kernel/trace/ftrace.c:2286: undefined reference to `ftrace_regs_caller'

kernel/built-in.o:kernel/trace/ftrace.c:2286: more undefined references to `ftrace_regs_caller' follow

vim +2286 kernel/trace/ftrace.c

79922b80 Steven Rostedt (Red Hat  2014-05-06  2280) 			return (unsigned long)FTRACE_ADDR;
79922b80 Steven Rostedt (Red Hat  2014-05-06  2281) 		}
79922b80 Steven Rostedt (Red Hat  2014-05-06  2282) 		return ops->trampoline;
79922b80 Steven Rostedt (Red Hat  2014-05-06  2283) 	}
79922b80 Steven Rostedt (Red Hat  2014-05-06  2284) 
7413af1f Steven Rostedt (Red Hat  2014-05-06  2285) 	if (rec->flags & FTRACE_FL_REGS_EN)
7413af1f Steven Rostedt (Red Hat  2014-05-06 @2286) 		return (unsigned long)FTRACE_REGS_ADDR;
7413af1f Steven Rostedt (Red Hat  2014-05-06  2287) 	else
7413af1f Steven Rostedt (Red Hat  2014-05-06  2288) 		return (unsigned long)FTRACE_ADDR;
7413af1f Steven Rostedt (Red Hat  2014-05-06  2289) }
7413af1f Steven Rostedt (Red Hat  2014-05-06  2290) 
c88fd863 Steven Rostedt           2011-08-16  2291  static int
c88fd863 Steven Rostedt           2011-08-16  2292  __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
c88fd863 Steven Rostedt           2011-08-16  2293  {
08f6fba5 Steven Rostedt           2012-04-30  2294  	unsigned long ftrace_old_addr;
c88fd863 Steven Rostedt           2011-08-16  2295  	unsigned long ftrace_addr;
c88fd863 Steven Rostedt           2011-08-16  2296  	int ret;
c88fd863 Steven Rostedt           2011-08-16  2297  
7c0868e0 Steven Rostedt (Red Hat  2014-05-08  2298) 	ftrace_addr = ftrace_get_addr_new(rec);
c88fd863 Steven Rostedt           2011-08-16  2299  
7c0868e0 Steven Rostedt (Red Hat  2014-05-08  2300) 	/* This needs to be done before we call ftrace_update_record */
7c0868e0 Steven Rostedt (Red Hat  2014-05-08  2301) 	ftrace_old_addr = ftrace_get_addr_curr(rec);
7c0868e0 Steven Rostedt (Red Hat  2014-05-08  2302) 
7c0868e0 Steven Rostedt (Red Hat  2014-05-08  2303) 	ret = ftrace_update_record(rec, enable);
08f6fba5 Steven Rostedt           2012-04-30  2304  
c88fd863 Steven Rostedt           2011-08-16  2305  	switch (ret) {
c88fd863 Steven Rostedt           2011-08-16  2306  	case FTRACE_UPDATE_IGNORE:
c88fd863 Steven Rostedt           2011-08-16  2307  		return 0;
c88fd863 Steven Rostedt           2011-08-16  2308  
c88fd863 Steven Rostedt           2011-08-16  2309  	case FTRACE_UPDATE_MAKE_CALL:
c88fd863 Steven Rostedt           2011-08-16  2310  		return ftrace_make_call(rec, ftrace_addr);
c88fd863 Steven Rostedt           2011-08-16  2311  
c88fd863 Steven Rostedt           2011-08-16  2312  	case FTRACE_UPDATE_MAKE_NOP:
39b5552c Steven Rostedt (Red Hat  2014-08-17  2313) 		return ftrace_make_nop(NULL, rec, ftrace_old_addr);
08f6fba5 Steven Rostedt           2012-04-30  2314  
08f6fba5 Steven Rostedt           2012-04-30  2315  	case FTRACE_UPDATE_MODIFY_CALL:
08f6fba5 Steven Rostedt           2012-04-30 @2316  		return ftrace_modify_call(rec, ftrace_old_addr, ftrace_addr);
5072c59f Steven Rostedt           2008-05-12  2317  	}
5072c59f Steven Rostedt           2008-05-12  2318  
c88fd863 Steven Rostedt           2011-08-16  2319  	return -1; /* unknow ftrace bug */

:::::: The code at line 2286 was first introduced by commit
:::::: 7413af1fb70e7efa6dbc7f27663e7a5126b3aa33 ftrace: Make get_ftrace_addr() and get_ftrace_addr_old() global

:::::: TO: Steven Rostedt (Red Hat) <[email protected]> :::::: CC: Steven Rostedt <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#4 lore raw

PATCH v3 2/8 ppc use ftrace_modify_all_code default

In reply to Torsten Duwe

Convert ppc's arch_ftrace_update_code from its own function copy to use the generic default functionality (without stop_machine -- our instructions are properly aligned and the replacements atomic ;)

With this we gain error checking and the much-needed function_trace_op handling.

---
 arch/powerpc/kernel/ftrace.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)
arch/powerpc/kernel/ftrace.c +4 -12
index 310137f..e419c7b 100644
@@ -511,20 +511,12 @@ void ftrace_replace_code(int enable)
 	}
 }
 
+/* Use the default ftrace_modify_all_code, but without
+ * stop_machine().
+ */
 void arch_ftrace_update_code(int command)
 {
-	if (command & FTRACE_UPDATE_CALLS)
-		ftrace_replace_code(1);
-	else if (command & FTRACE_DISABLE_CALLS)
-		ftrace_replace_code(0);
-
-	if (command & FTRACE_UPDATE_TRACE_FUNC)
-		ftrace_update_ftrace_func(ftrace_trace_function);
-
-	if (command & FTRACE_START_FUNC_RET)
-		ftrace_enable_ftrace_graph_caller();
-	else if (command & FTRACE_STOP_FUNC_RET)
-		ftrace_disable_ftrace_graph_caller();
+	ftrace_modify_all_code(command);
 }
 
 int __init ftrace_dyn_arch_init(void)
Signature · 1 line
1.8.5.6
#5 lore raw

PATCH v3 3/8 ppc64 ftrace_with_regs configuration variables

In reply to Torsten Duwe

* Makefile:
- globally use -mprofile-kernel in case it's configured.
* arch/powerpc/Kconfig / kernel/trace/Kconfig:
- declare that ppc64 HAVE_MPROFILE_KERNEL and HAVE_DYNAMIC_FTRACE_WITH_REGS, and use it.

---
 arch/powerpc/Kconfig  | 2 ++
 arch/powerpc/Makefile | 7 +++++++
 kernel/trace/Kconfig  | 5 +++++
 3 files changed, 14 insertions(+)
arch/powerpc/Kconfig +2 -0
index 9a7057e..0e6011c 100644
@@ -97,8 +97,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/Makefile +7 -0
index b9b4af2..25d0034 100644
@@ -133,6 +133,13 @@ else
 CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64
 endif
 
+ifeq ($(CONFIG_PPC64),y)
+ifdef CONFIG_HAVE_MPROFILE_KERNEL
+CC_FLAGS_FTRACE	:= -pg $(call cc-option,-mprofile-kernel)
+KBUILD_CPPFLAGS	+= -DCC_USING_MPROFILE_KERNEL
+endif
+endif
+
 CFLAGS-$(CONFIG_CELL_CPU) += $(call cc-option,-mcpu=cell)
 CFLAGS-$(CONFIG_POWER4_CPU) += $(call cc-option,-mcpu=power4)
 CFLAGS-$(CONFIG_POWER5_CPU) += $(call cc-option,-mcpu=power5)
kernel/trace/Kconfig +5 -0
index 1153c43..dbcb635 100644
@@ -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
Signature · 1 line
1.8.5.6
#6 lore raw

PATCH v3 4/8 ppc64 ftrace_with_regs: spare early boot and low level

In reply to Torsten Duwe

Using -mprofile-kernel on early boot code not only confuses the checker but is also useless, as the infrastructure is not yet in place. Proceed like with -pg (remove it from CFLAGS), equally with time.o and ftrace itself.

* arch/powerpc/kernel/Makefile:
- remove -mprofile-kernel from low level and boot code objects' CFLAGS for FUNCTION_TRACER configurations.

---
 arch/powerpc/kernel/Makefile | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
arch/powerpc/kernel/Makefile +6 -6
index ba33693..0f417d5 100644
@@ -16,14 +16,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 \
Signature · 1 line
1.8.5.6
#7 lore raw

PATCH v3 5/8 ppc64 ftrace: disable profiling for some functions

In reply to Torsten Duwe

At least POWER7/8 have MMUs that don't completely autoload; a normal, recoverable memory fault might pass through these functions. If a dynamic tracer function causes such a fault, any of these functions being traced with -mprofile-kernel may cause an endless recursion.

---
 arch/powerpc/kernel/process.c        |  2 +-
 arch/powerpc/mm/fault.c              |  2 +-
 arch/powerpc/mm/hash_utils_64.c      | 18 +++++++++---------
 arch/powerpc/mm/hugetlbpage-hash64.c |  2 +-
 arch/powerpc/mm/hugetlbpage.c        |  4 ++--
 arch/powerpc/mm/mem.c                |  2 +-
 arch/powerpc/mm/pgtable_64.c         |  2 +-
 arch/powerpc/mm/slb.c                |  6 +++---
 arch/powerpc/mm/slice.c              |  8 ++++----
 9 files changed, 23 insertions(+), 23 deletions(-)
arch/powerpc/kernel/process.c +1 -1
index 75b6676..c2900b9 100644
@@ -715,7 +715,7 @@ static inline void __switch_to_tm(struct task_struct *prev)
  * don't know which of the checkpointed state and the transactional
  * state to use.
  */
-void restore_tm_state(struct pt_regs *regs)
+notrace void restore_tm_state(struct pt_regs *regs)
 {
 	unsigned long msr_diff;
 
arch/powerpc/mm/fault.c +1 -1
index a67c6d7..125be37 100644
@@ -205,7 +205,7 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault)
  * The return value is 0 if the fault was handled, or the signal
  * number if this is a kernel fault that can't be handled here.
  */
-int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
+notrace int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
 			    unsigned long error_code)
 {
 	enum ctx_state prev_state = exception_enter();
arch/powerpc/mm/hash_utils_64.c +9 -9
index aee7017..90e89e7 100644
@@ -849,7 +849,7 @@ void early_init_mmu_secondary(void)
 /*
  * Called by asm hashtable.S for doing lazy icache flush
  */
-unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
+notrace unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
 {
 	struct page *page;
 
@@ -870,7 +870,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
 }
 
 #ifdef CONFIG_PPC_MM_SLICES
-static unsigned int get_paca_psize(unsigned long addr)
+static notrace unsigned int get_paca_psize(unsigned long addr)
 {
 	u64 lpsizes;
 	unsigned char *hpsizes;
@@ -899,7 +899,7 @@ unsigned int get_paca_psize(unsigned long addr)
  * For now this makes the whole process use 4k pages.
  */
 #ifdef CONFIG_PPC_64K_PAGES
-void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
+notrace void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
 {
 	if (get_slice_psize(mm, addr) == MMU_PAGE_4K)
 		return;
@@ -920,7 +920,7 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
  * Result is 0: full permissions, _PAGE_RW: read-only,
  * _PAGE_USER or _PAGE_USER|_PAGE_RW: no access.
  */
-static int subpage_protection(struct mm_struct *mm, unsigned long ea)
+static notrace int subpage_protection(struct mm_struct *mm, unsigned long ea)
 {
 	struct subpage_prot_table *spt = &mm->context.spt;
 	u32 spp = 0;
@@ -968,7 +968,7 @@ void hash_failure_debug(unsigned long ea, unsigned long access,
 		trap, vsid, ssize, psize, lpsize, pte);
 }
 
-static void check_paca_psize(unsigned long ea, struct mm_struct *mm,
+static notrace void check_paca_psize(unsigned long ea, struct mm_struct *mm,
 			     int psize, bool user_region)
 {
 	if (user_region) {
@@ -990,7 +990,7 @@ static void check_paca_psize(unsigned long ea, struct mm_struct *mm,
  * -1 - critical hash insertion error
  * -2 - access not permitted by subpage protection mechanism
  */
-int hash_page_mm(struct mm_struct *mm, unsigned long ea,
+notrace int hash_page_mm(struct mm_struct *mm, unsigned long ea,
 		 unsigned long access, unsigned long trap,
 		 unsigned long flags)
 {
@@ -1186,7 +1186,7 @@ bail:
 }
 EXPORT_SYMBOL_GPL(hash_page_mm);
 
-int hash_page(unsigned long ea, unsigned long access, unsigned long trap,
+notrace int hash_page(unsigned long ea, unsigned long access, unsigned long trap,
 	      unsigned long dsisr)
 {
 	unsigned long flags = 0;
@@ -1288,7 +1288,7 @@ out_exit:
 /* WARNING: This is called from hash_low_64.S, if you change this prototype,
  *          do not forget to update the assembly call site !
  */
-void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
+notrace void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
 		     unsigned long flags)
 {
 	unsigned long hash, index, shift, hidx, slot;
@@ -1436,7 +1436,7 @@ void low_hash_fault(struct pt_regs *regs, unsigned long address, int rc)
 	exception_exit(prev_state);
 }
 
-long hpte_insert_repeating(unsigned long hash, unsigned long vpn,
+notrace long hpte_insert_repeating(unsigned long hash, unsigned long vpn,
 			   unsigned long pa, unsigned long rflags,
 			   unsigned long vflags, int psize, int ssize)
 {
arch/powerpc/mm/hugetlbpage-hash64.c +1 -1
index d94b1af..50b8c6f 100644
@@ -18,7 +18,7 @@ extern long hpte_insert_repeating(unsigned long hash, unsigned long vpn,
 				  unsigned long pa, unsigned long rlags,
 				  unsigned long vflags, int psize, int ssize);
 
-int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
+notrace int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
 		     pte_t *ptep, unsigned long trap, unsigned long flags,
 		     int ssize, unsigned int shift, unsigned int mmu_psize)
 {
arch/powerpc/mm/hugetlbpage.c +2 -2
index 06c1452..bc2f459 100644
@@ -922,7 +922,7 @@ static int __init hugetlbpage_init(void)
 #endif
 arch_initcall(hugetlbpage_init);
 
-void flush_dcache_icache_hugepage(struct page *page)
+notrace void flush_dcache_icache_hugepage(struct page *page)
 {
 	int i;
 	void *start;
@@ -955,7 +955,7 @@ void flush_dcache_icache_hugepage(struct page *page)
  * when we have MSR[EE] = 0 but the paca->soft_enabled = 1
  */
 
-pte_t *__find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
+notrace pte_t *__find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
 				   unsigned *shift)
 {
 	pgd_t pgd, *pgdp;
arch/powerpc/mm/mem.c +1 -1
index 22d94c3..f690e8a 100644
@@ -406,7 +406,7 @@ void flush_dcache_page(struct page *page)
 }
 EXPORT_SYMBOL(flush_dcache_page);
 
-void flush_dcache_icache_page(struct page *page)
+notrace void flush_dcache_icache_page(struct page *page)
 {
 #ifdef CONFIG_HUGETLB_PAGE
 	if (PageCompound(page)) {
arch/powerpc/mm/pgtable_64.c +1 -1
index e92cb21..c74050b 100644
@@ -442,7 +442,7 @@ static void page_table_free_rcu(void *table)
 	}
 }
 
-void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
+notrace void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
 {
 	unsigned long pgf = (unsigned long)table;
 
arch/powerpc/mm/slb.c +3 -3
index 8a32a2b..5b05754 100644
@@ -91,7 +91,7 @@ static inline void create_shadowed_slbe(unsigned long ea, int ssize,
 		     : "memory" );
 }
 
-static void __slb_flush_and_rebolt(void)
+static notrace void __slb_flush_and_rebolt(void)
 {
 	/* If you change this make sure you change SLB_NUM_BOLTED
 	 * and PR KVM appropriately too. */
@@ -131,7 +131,7 @@ static void __slb_flush_and_rebolt(void)
 		     : "memory");
 }
 
-void slb_flush_and_rebolt(void)
+notrace void slb_flush_and_rebolt(void)
 {
 
 	WARN_ON(!irqs_disabled());
@@ -146,7 +146,7 @@ void slb_flush_and_rebolt(void)
 	get_paca()->slb_cache_ptr = 0;
 }
 
-void slb_vmalloc_update(void)
+notrace void slb_vmalloc_update(void)
 {
 	unsigned long vflags;
 
arch/powerpc/mm/slice.c +4 -4
index 0f432a7..f92f0f0 100644
@@ -76,8 +76,8 @@ static void slice_print_mask(const char *label, struct slice_mask mask) {}
 
 #endif
 
-static struct slice_mask slice_range_to_mask(unsigned long start,
-					     unsigned long len)
+static notrace struct slice_mask slice_range_to_mask(unsigned long start,
+						     unsigned long len)
 {
 	unsigned long end = start + len - 1;
 	struct slice_mask ret = { 0, 0 };
@@ -564,7 +564,7 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
 				       current->mm->context.user_psize, 1);
 }
 
-unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
+notrace unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
 {
 	unsigned char *hpsizes;
 	int index, mask_index;
@@ -645,7 +645,7 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 	spin_unlock_irqrestore(&slice_convert_lock, flags);
 }
 
-void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
+notrace void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
 			   unsigned long len, unsigned int psize)
 {
 	struct slice_mask mask = slice_range_to_mask(start, len);
Signature · 1 line
1.8.5.6
#8 lore raw

PATCH v3 6/8 ppc64 ftrace: disable profiling for some files

In reply to Torsten Duwe

This adds -mprofile-kernel to the cc flags to be stripped from the command line for code-patching.o and feature-fixups.o, in addition to "-pg"

---
 arch/powerpc/lib/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/lib/Makefile +2 -2
index a47e142..98e22b2 100644
@@ -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 ppc_ksyms.o code-patching.o \
 	 feature-fixups.o
Signature · 1 line
1.8.5.6
#9 lore raw

PATCH v3 7/8 Implement kernel live patching for ppc64le (ABIv2)

In reply to Torsten Duwe

* create the appropriate files+functions arch/powerpc/include/asm/livepatch.h klp_check_compiler_support,
klp_arch_set_pc
arch/powerpc/kernel/livepatch.c with a stub for
klp_write_module_reloc
This is architecture-independent work in progress.
* introduce a fixup in arch/powerpc/kernel/entry_64.S for local calls that are becoming global due to live patching. And of course do the main KLP thing: return to a maybe different address, possibly altered by the live patching ftrace op.

---
 arch/powerpc/include/asm/livepatch.h | 27 ++++++++++++++++++++
 arch/powerpc/kernel/entry_64.S       | 48 +++++++++++++++++++++++++++++++++---
 arch/powerpc/kernel/livepatch.c      | 20 +++++++++++++++
 3 files changed, 91 insertions(+), 4 deletions(-)
 create mode 100644 arch/powerpc/include/asm/livepatch.h
 create mode 100644 arch/powerpc/kernel/livepatch.c
arch/powerpc/include/asm/livepatch.h new file +27 -0
new file mode 100644
index 0000000..334eb55
@@ -0,0 +1,27 @@
+#ifndef _ASM_POWERPC64_LIVEPATCH_H
+#define _ASM_POWERPC64_LIVEPATCH_H
+
+#include <linux/module.h>
+#include <linux/ftrace.h>
+
+#ifdef CONFIG_LIVEPATCH
+static inline int klp_check_compiler_support(void)
+{
+#if !defined(_CALL_ELF) || _CALL_ELF != 2
+	return 1;
+#endif
+	return 0;
+}
+
+extern int klp_write_module_reloc(struct module *mod, unsigned long type,
+				   unsigned long loc, unsigned long value);
+
+static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
+{
+	regs->nip = ip;
+}
+#else
+#error Live patching support is disabled; check CONFIG_LIVEPATCH
+#endif
+
+#endif /* _ASM_POWERPC64_LIVEPATCH_H */
arch/powerpc/kernel/entry_64.S +44 -4

78 lines not on this page · raw message

arch/powerpc/kernel/livepatch.c new file +20 -0
new file mode 100644
index 0000000..9dace38
@@ -0,0 +1,20 @@
+#include <linux/module.h>
+#include <asm/livepatch.h>
+
+/**
+ * klp_write_module_reloc() - write a relocation in a module
+ * @mod:       module in which the section to be modified is found
+ * @type:      ELF relocation type (see asm/elf.h)
+ * @loc:       address that the relocation should be written to
+ * @value:     relocation value (sym address + addend)
+ *
+ * This function writes a relocation to the specified location for
+ * a particular module.
+ */
+int klp_write_module_reloc(struct module *mod, unsigned long type,
+			    unsigned long loc, unsigned long value)
+{
+	/* This requires infrastructure changes; we need the loadinfos. */
+	pr_err("lpc_write_module_reloc not yet supported\n");
+	return -ENOSYS;
+}
Signature · 1 line
1.8.5.6
#10 lore raw

PATCH v3 8/8 Enable LIVEPATCH to be configured on ppc64le and add livepatch.o if it is selected.

In reply to Torsten Duwe
---
 arch/powerpc/Kconfig         | 5 +++++
 arch/powerpc/kernel/Makefile | 1 +
 2 files changed, 6 insertions(+)
arch/powerpc/Kconfig +5 -0
index 0e6011c..341ebe9 100644
@@ -163,6 +163,9 @@ config PPC
 	select ARCH_HAS_DMA_SET_COHERENT_MASK
 	select HAVE_ARCH_SECCOMP_FILTER
 
+config HAVE_LIVEPATCH
+       def_bool PPC64 && CPU_LITTLE_ENDIAN
+
 config GENERIC_CSUM
 	def_bool CPU_LITTLE_ENDIAN
 
@@ -1095,3 +1098,5 @@ config PPC_LIB_RHEAP
 	bool
 
 source "arch/powerpc/kvm/Kconfig"
+
+source "kernel/livepatch/Kconfig"
arch/powerpc/kernel/Makefile +1 -0
index 0f417d5..f9a2925 100644
@@ -119,6 +119,7 @@ obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
 obj-$(CONFIG_FTRACE_SYSCALLS)	+= ftrace.o
 obj-$(CONFIG_TRACING)		+= trace_clock.o
+obj-$(CONFIG_LIVEPATCH)		+= livepatch.o
 
 ifneq ($(CONFIG_PPC_INDIRECT_PIO),y)
 obj-y				+= iomap.o
Signature · 1 line
1.8.5.6