Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Code for replacing ftrace calls with jumps.
  4 *
  5 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
  6 *
  7 * Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box.
  8 *
  9 * Added function graph tracer code, taken from x86 that was written
 10 * by Frederic Weisbecker, and ported to PPC by Steven Rostedt.
 11 *
 12 */
 13
 14#define pr_fmt(fmt) "ftrace-powerpc: " fmt
 15
 16#include <linux/spinlock.h>
 17#include <linux/hardirq.h>
 18#include <linux/uaccess.h>
 19#include <linux/module.h>
 20#include <linux/ftrace.h>
 21#include <linux/percpu.h>
 22#include <linux/init.h>
 23#include <linux/list.h>
 24
 25#include <asm/cacheflush.h>
 26#include <asm/code-patching.h>
 27#include <asm/ftrace.h>
 28#include <asm/syscall.h>
 29#include <asm/inst.h>
 
 30
 31/*
 32 * We generally only have a single long_branch tramp and at most 2 or 3 plt
 33 * tramps generated. But, we don't use the plt tramps currently. We also allot
 34 * 2 tramps after .text and .init.text. So, we only end up with around 3 usable
 35 * tramps in total. Set aside 8 just to be sure.
 36 */
 37#define	NUM_FTRACE_TRAMPS	8
 38static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
 39
 40static ppc_inst_t
 41ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
 42{
 43	ppc_inst_t op;
 
 44
 45	addr = ppc_function_entry((void *)addr);
 
 
 
 
 
 46
 47	/* if (link) set op to 'bl' else 'b' */
 
 
 
 
 
 
 
 48	create_branch(&op, (u32 *)ip, addr, link ? BRANCH_SET_LINK : 0);
 49
 50	return op;
 51}
 52
 53static inline int
 54ftrace_modify_code(unsigned long ip, ppc_inst_t old, ppc_inst_t new)
 55{
 56	ppc_inst_t replaced;
 57
 58	/*
 59	 * Note:
 60	 * We are paranoid about modifying text, as if a bug was to happen, it
 61	 * could cause us to read or write to someplace that could cause harm.
 62	 * Carefully read and modify the code with probe_kernel_*(), and make
 63	 * sure what we read is what we expected it to be before modifying it.
 64	 */
 65
 66	/* read the text we want to modify */
 67	if (copy_inst_from_kernel_nofault(&replaced, (void *)ip))
 68		return -EFAULT;
 69
 70	/* Make sure it is what we expect it to be */
 71	if (!ppc_inst_equal(replaced, old)) {
 72		pr_err("%p: replaced (%08lx) != old (%08lx)", (void *)ip,
 73		       ppc_inst_as_ulong(replaced), ppc_inst_as_ulong(old));
 74		return -EINVAL;
 75	}
 76
 77	/* replace the text with the new text */
 78	return patch_instruction((u32 *)ip, new);
 79}
 80
 81/*
 82 * Helper functions that are the same for both PPC64 and PPC32.
 83 */
 84static int test_24bit_addr(unsigned long ip, unsigned long addr)
 85{
 86	addr = ppc_function_entry((void *)addr);
 87
 88	return is_offset_in_branch_range(addr - ip);
 89}
 90
 91static int is_bl_op(ppc_inst_t op)
 92{
 93	return (ppc_inst_val(op) & ~PPC_LI_MASK) == PPC_RAW_BL(0);
 94}
 
 
 95
 96static int is_b_op(ppc_inst_t op)
 97{
 98	return (ppc_inst_val(op) & ~PPC_LI_MASK) == PPC_RAW_BRANCH(0);
 99}
100
101static unsigned long find_bl_target(unsigned long ip, ppc_inst_t op)
102{
103	int offset;
104
105	offset = PPC_LI(ppc_inst_val(op));
106	/* make it signed */
107	if (offset & 0x02000000)
108		offset |= 0xfe000000;
109
110	return ip + (long)offset;
111}
112
113#ifdef CONFIG_MODULES
114static int
115__ftrace_make_nop(struct module *mod,
116		  struct dyn_ftrace *rec, unsigned long addr)
117{
118	unsigned long entry, ptr, tramp;
119	unsigned long ip = rec->ip;
120	ppc_inst_t op, pop;
121
122	/* read where this goes */
123	if (copy_inst_from_kernel_nofault(&op, (void *)ip)) {
124		pr_err("Fetching opcode failed.\n");
125		return -EFAULT;
126	}
127
128	/* Make sure that this is still a 24bit jump */
129	if (!is_bl_op(op)) {
130		pr_err("Not expected bl: opcode is %08lx\n", ppc_inst_as_ulong(op));
131		return -EINVAL;
132	}
133
134	/* lets find where the pointer goes */
135	tramp = find_bl_target(ip, op);
136
137	pr_devel("ip:%lx jumps to %lx", ip, tramp);
138
139	if (module_trampoline_target(mod, tramp, &ptr)) {
140		pr_err("Failed to get trampoline target\n");
141		return -EFAULT;
142	}
143
144	pr_devel("trampoline target %lx", ptr);
145
146	entry = ppc_global_function_entry((void *)addr);
147	/* This should match what was called */
148	if (ptr != entry) {
149		pr_err("addr %lx does not match expected %lx\n", ptr, entry);
150		return -EINVAL;
151	}
152
153	if (IS_ENABLED(CONFIG_MPROFILE_KERNEL)) {
154		if (copy_inst_from_kernel_nofault(&op, (void *)(ip - 4))) {
155			pr_err("Fetching instruction at %lx failed.\n", ip - 4);
156			return -EFAULT;
157		}
158
159		/* We expect either a mflr r0, or a std r0, LRSAVE(r1) */
160		if (!ppc_inst_equal(op, ppc_inst(PPC_RAW_MFLR(_R0))) &&
161		    !ppc_inst_equal(op, ppc_inst(PPC_INST_STD_LR))) {
162			pr_err("Unexpected instruction %08lx around bl _mcount\n",
163			       ppc_inst_as_ulong(op));
164			return -EINVAL;
165		}
166	} else if (IS_ENABLED(CONFIG_PPC64)) {
167		/*
168		 * Check what is in the next instruction. We can see ld r2,40(r1), but
169		 * on first pass after boot we will see mflr r0.
170		 */
171		if (copy_inst_from_kernel_nofault(&op, (void *)(ip + 4))) {
172			pr_err("Fetching op failed.\n");
173			return -EFAULT;
174		}
175
176		if (!ppc_inst_equal(op,  ppc_inst(PPC_INST_LD_TOC))) {
177			pr_err("Expected %08lx found %08lx\n", PPC_INST_LD_TOC,
178			       ppc_inst_as_ulong(op));
179			return -EINVAL;
180		}
181	}
182
183	/*
184	 * When using -mprofile-kernel or PPC32 there is no load to jump over.
185	 *
186	 * Otherwise our original call site looks like:
187	 *
188	 * bl <tramp>
189	 * ld r2,XX(r1)
190	 *
191	 * Milton Miller pointed out that we can not simply nop the branch.
192	 * If a task was preempted when calling a trace function, the nops
193	 * will remove the way to restore the TOC in r2 and the r2 TOC will
194	 * get corrupted.
195	 *
196	 * Use a b +8 to jump over the load.
197	 */
198	if (IS_ENABLED(CONFIG_MPROFILE_KERNEL) || IS_ENABLED(CONFIG_PPC32))
199		pop = ppc_inst(PPC_RAW_NOP());
200	else
201		pop = ppc_inst(PPC_RAW_BRANCH(8));	/* b +8 */
202
203	if (patch_instruction((u32 *)ip, pop)) {
204		pr_err("Patching NOP failed.\n");
205		return -EPERM;
206	}
207
208	return 0;
209}
210#else
211static int __ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr)
212{
213	return 0;
214}
215#endif /* CONFIG_MODULES */
216
217static unsigned long find_ftrace_tramp(unsigned long ip)
218{
219	int i;
220
221	/*
222	 * We have the compiler generated long_branch tramps at the end
223	 * and we prefer those
224	 */
225	for (i = NUM_FTRACE_TRAMPS - 1; i >= 0; i--)
226		if (!ftrace_tramps[i])
227			continue;
228		else if (is_offset_in_branch_range(ftrace_tramps[i] - ip))
229			return ftrace_tramps[i];
230
231	return 0;
232}
233
234static int add_ftrace_tramp(unsigned long tramp)
 
235{
236	int i;
237
238	for (i = 0; i < NUM_FTRACE_TRAMPS; i++)
239		if (!ftrace_tramps[i]) {
240			ftrace_tramps[i] = tramp;
241			return 0;
242		}
243
244	return -1;
245}
246
247/*
248 * If this is a compiler generated long_branch trampoline (essentially, a
249 * trampoline that has a branch to _mcount()), we re-write the branch to
250 * instead go to ftrace_[regs_]caller() and note down the location of this
251 * trampoline.
252 */
253static int setup_mcount_compiler_tramp(unsigned long tramp)
254{
255	int i;
256	ppc_inst_t op;
257	unsigned long ptr;
258
259	/* Is this a known long jump tramp? */
260	for (i = 0; i < NUM_FTRACE_TRAMPS; i++)
261		if (ftrace_tramps[i] == tramp)
262			return 0;
263
264	/* New trampoline -- read where this goes */
265	if (copy_inst_from_kernel_nofault(&op, (void *)tramp)) {
266		pr_debug("Fetching opcode failed.\n");
267		return -1;
268	}
 
 
 
269
270	/* Is this a 24 bit branch? */
271	if (!is_b_op(op)) {
272		pr_debug("Trampoline is not a long branch tramp.\n");
273		return -1;
274	}
275
276	/* lets find where the pointer goes */
277	ptr = find_bl_target(tramp, op);
 
 
278
279	if (ptr != ppc_global_function_entry((void *)_mcount)) {
280		pr_debug("Trampoline target %p is not _mcount\n", (void *)ptr);
281		return -1;
 
 
 
 
 
 
282	}
283
284	/* Let's re-write the tramp to go to ftrace_[regs_]caller */
285	if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS))
286		ptr = ppc_global_function_entry((void *)ftrace_regs_caller);
 
 
 
287	else
288		ptr = ppc_global_function_entry((void *)ftrace_caller);
289
290	if (patch_branch((u32 *)tramp, ptr, 0)) {
291		pr_debug("REL24 out of range!\n");
292		return -1;
293	}
294
295	if (add_ftrace_tramp(tramp)) {
296		pr_debug("No tramp locations left\n");
297		return -1;
298	}
299
 
300	return 0;
301}
302
303static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
304{
305	unsigned long tramp, ip = rec->ip;
306	ppc_inst_t op;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
308	/* Read where this goes */
309	if (copy_inst_from_kernel_nofault(&op, (void *)ip)) {
310		pr_err("Fetching opcode failed.\n");
311		return -EFAULT;
312	}
313
314	/* Make sure that this is still a 24bit jump */
315	if (!is_bl_op(op)) {
316		pr_err("Not expected bl: opcode is %08lx\n", ppc_inst_as_ulong(op));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317		return -EINVAL;
318	}
319
320	/* Let's find where the pointer goes */
321	tramp = find_bl_target(ip, op);
322
323	pr_devel("ip:%lx jumps to %lx", ip, tramp);
 
324
325	if (setup_mcount_compiler_tramp(tramp)) {
326		/* Are other trampolines reachable? */
327		if (!find_ftrace_tramp(ip)) {
328			pr_err("No ftrace trampolines reachable from %ps\n",
329					(void *)ip);
330			return -EINVAL;
331		}
332	}
333
334	if (patch_instruction((u32 *)ip, ppc_inst(PPC_RAW_NOP()))) {
335		pr_err("Patching NOP failed.\n");
336		return -EPERM;
337	}
338
339	return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340}
341
342int ftrace_make_nop(struct module *mod,
343		    struct dyn_ftrace *rec, unsigned long addr)
344{
345	unsigned long ip = rec->ip;
346	ppc_inst_t old, new;
347
348	/*
349	 * If the calling address is more that 24 bits away,
350	 * then we had to use a trampoline to make the call.
351	 * Otherwise just update the call site.
352	 */
353	if (test_24bit_addr(ip, addr)) {
354		/* within range */
355		old = ftrace_call_replace(ip, addr, 1);
356		new = ppc_inst(PPC_RAW_NOP());
357		return ftrace_modify_code(ip, old, new);
358	} else if (core_kernel_text(ip)) {
359		return __ftrace_make_nop_kernel(rec, addr);
360	} else if (!IS_ENABLED(CONFIG_MODULES)) {
361		return -EINVAL;
362	}
363
364	/*
365	 * Out of range jumps are called from modules.
366	 * We should either already have a pointer to the module
367	 * or it has been passed in.
368	 */
369	if (!rec->arch.mod) {
370		if (!mod) {
371			pr_err("No module loaded addr=%lx\n", addr);
372			return -EFAULT;
373		}
374		rec->arch.mod = mod;
375	} else if (mod) {
376		if (mod != rec->arch.mod) {
377			pr_err("Record mod %p not equal to passed in mod %p\n",
378			       rec->arch.mod, mod);
379			return -EINVAL;
380		}
381		/* nothing to do if mod == rec->arch.mod */
382	} else
383		mod = rec->arch.mod;
384
385	return __ftrace_make_nop(mod, rec, addr);
386}
387
388#ifdef CONFIG_MODULES
389/*
390 * Examine the existing instructions for __ftrace_make_call.
391 * They should effectively be a NOP, and follow formal constraints,
392 * depending on the ABI. Return false if they don't.
393 */
394static bool expected_nop_sequence(void *ip, ppc_inst_t op0, ppc_inst_t op1)
395{
396	if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS))
397		return ppc_inst_equal(op0, ppc_inst(PPC_RAW_NOP()));
 
398	else
399		return ppc_inst_equal(op0, ppc_inst(PPC_RAW_BRANCH(8))) &&
400		       ppc_inst_equal(op1, ppc_inst(PPC_INST_LD_TOC));
401}
402
403static int
404__ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
405{
406	ppc_inst_t op[2];
407	void *ip = (void *)rec->ip;
408	unsigned long entry, ptr, tramp;
409	struct module *mod = rec->arch.mod;
410
411	/* read where this goes */
412	if (copy_inst_from_kernel_nofault(op, ip))
413		return -EFAULT;
414
415	if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) &&
416	    copy_inst_from_kernel_nofault(op + 1, ip + 4))
417		return -EFAULT;
418
419	if (!expected_nop_sequence(ip, op[0], op[1])) {
420		pr_err("Unexpected call sequence at %p: %08lx %08lx\n", ip,
421		       ppc_inst_as_ulong(op[0]), ppc_inst_as_ulong(op[1]));
422		return -EINVAL;
423	}
424
425	/* If we never set up ftrace trampoline(s), then bail */
426	if (!mod->arch.tramp ||
427	    (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) && !mod->arch.tramp_regs)) {
428		pr_err("No ftrace trampoline\n");
429		return -EINVAL;
430	}
431
432	if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) && rec->flags & FTRACE_FL_REGS)
433		tramp = mod->arch.tramp_regs;
434	else
435		tramp = mod->arch.tramp;
436
437	if (module_trampoline_target(mod, tramp, &ptr)) {
438		pr_err("Failed to get trampoline target\n");
439		return -EFAULT;
440	}
441
442	pr_devel("trampoline target %lx", ptr);
443
444	entry = ppc_global_function_entry((void *)addr);
445	/* This should match what was called */
446	if (ptr != entry) {
447		pr_err("addr %lx does not match expected %lx\n", ptr, entry);
448		return -EINVAL;
449	}
450
451	if (patch_branch(ip, tramp, BRANCH_SET_LINK)) {
452		pr_err("REL24 out of range!\n");
453		return -EINVAL;
454	}
455
456	return 0;
 
 
457}
458#else
459static int __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 
 
 
 
 
460{
461	return 0;
 
 
462}
463#endif /* CONFIG_MODULES */
464
465static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
466{
467	ppc_inst_t op;
468	void *ip = (void *)rec->ip;
469	unsigned long tramp, entry, ptr;
470
471	/* Make sure we're being asked to patch branch to a known ftrace addr */
472	entry = ppc_global_function_entry((void *)ftrace_caller);
473	ptr = ppc_global_function_entry((void *)addr);
474
475	if (ptr != entry && IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS))
476		entry = ppc_global_function_entry((void *)ftrace_regs_caller);
477
478	if (ptr != entry) {
479		pr_err("Unknown ftrace addr to patch: %ps\n", (void *)ptr);
480		return -EINVAL;
481	}
482
483	/* Make sure we have a nop */
484	if (copy_inst_from_kernel_nofault(&op, ip)) {
485		pr_err("Unable to read ftrace location %p\n", ip);
486		return -EFAULT;
487	}
488
489	if (!ppc_inst_equal(op, ppc_inst(PPC_RAW_NOP()))) {
490		pr_err("Unexpected call sequence at %p: %08lx\n",
491		       ip, ppc_inst_as_ulong(op));
492		return -EINVAL;
493	}
494
495	tramp = find_ftrace_tramp((unsigned long)ip);
496	if (!tramp) {
497		pr_err("No ftrace trampolines reachable from %ps\n", ip);
498		return -EINVAL;
499	}
500
501	if (patch_branch(ip, tramp, BRANCH_SET_LINK)) {
502		pr_err("Error patching branch to ftrace tramp!\n");
503		return -EINVAL;
504	}
 
 
 
505
506	return 0;
507}
508
509int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
510{
511	unsigned long ip = rec->ip;
512	ppc_inst_t old, new;
513
514	/*
515	 * If the calling address is more that 24 bits away,
516	 * then we had to use a trampoline to make the call.
517	 * Otherwise just update the call site.
518	 */
519	if (test_24bit_addr(ip, addr)) {
520		/* within range */
521		old = ppc_inst(PPC_RAW_NOP());
522		new = ftrace_call_replace(ip, addr, 1);
523		return ftrace_modify_code(ip, old, new);
524	} else if (core_kernel_text(ip)) {
525		return __ftrace_make_call_kernel(rec, addr);
526	} else if (!IS_ENABLED(CONFIG_MODULES)) {
527		/* We should not get here without modules */
528		return -EINVAL;
529	}
530
531	/*
532	 * Out of range jumps are called from modules.
533	 * Being that we are converting from nop, it had better
534	 * already have a module defined.
535	 */
536	if (!rec->arch.mod) {
537		pr_err("No module loaded\n");
538		return -EINVAL;
539	}
540
541	return __ftrace_make_call(rec, addr);
542}
543
544#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
545#ifdef CONFIG_MODULES
546static int
547__ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
548					unsigned long addr)
549{
550	ppc_inst_t op;
551	unsigned long ip = rec->ip;
552	unsigned long entry, ptr, tramp;
553	struct module *mod = rec->arch.mod;
 
 
554
555	/* If we never set up ftrace trampolines, then bail */
556	if (!mod->arch.tramp || !mod->arch.tramp_regs) {
557		pr_err("No ftrace trampoline\n");
558		return -EINVAL;
559	}
560
561	/* read where this goes */
562	if (copy_inst_from_kernel_nofault(&op, (void *)ip)) {
563		pr_err("Fetching opcode failed.\n");
564		return -EFAULT;
565	}
566
567	/* Make sure that this is still a 24bit jump */
568	if (!is_bl_op(op)) {
569		pr_err("Not expected bl: opcode is %08lx\n", ppc_inst_as_ulong(op));
570		return -EINVAL;
571	}
572
573	/* lets find where the pointer goes */
574	tramp = find_bl_target(ip, op);
575	entry = ppc_global_function_entry((void *)old_addr);
576
577	pr_devel("ip:%lx jumps to %lx", ip, tramp);
578
579	if (tramp != entry) {
580		/* old_addr is not within range, so we must have used a trampoline */
581		if (module_trampoline_target(mod, tramp, &ptr)) {
582			pr_err("Failed to get trampoline target\n");
583			return -EFAULT;
 
 
 
 
584		}
585
586		pr_devel("trampoline target %lx", ptr);
587
588		/* This should match what was called */
589		if (ptr != entry) {
590			pr_err("addr %lx does not match expected %lx\n", ptr, entry);
591			return -EINVAL;
592		}
593	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
595	/* The new target may be within range */
596	if (test_24bit_addr(ip, addr)) {
597		/* within range */
598		if (patch_branch((u32 *)ip, addr, BRANCH_SET_LINK)) {
599			pr_err("REL24 out of range!\n");
600			return -EINVAL;
601		}
602
603		return 0;
604	}
605
606	if (rec->flags & FTRACE_FL_REGS)
607		tramp = mod->arch.tramp_regs;
608	else
609		tramp = mod->arch.tramp;
610
611	if (module_trampoline_target(mod, tramp, &ptr)) {
612		pr_err("Failed to get trampoline target\n");
613		return -EFAULT;
614	}
615
616	pr_devel("trampoline target %lx", ptr);
617
618	entry = ppc_global_function_entry((void *)addr);
619	/* This should match what was called */
620	if (ptr != entry) {
621		pr_err("addr %lx does not match expected %lx\n", ptr, entry);
622		return -EINVAL;
623	}
624
625	if (patch_branch((u32 *)ip, tramp, BRANCH_SET_LINK)) {
626		pr_err("REL24 out of range!\n");
627		return -EINVAL;
628	}
629
630	return 0;
631}
632#else
633static int __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, unsigned long addr)
634{
635	return 0;
636}
637#endif
638
639int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
640			unsigned long addr)
641{
642	unsigned long ip = rec->ip;
643	ppc_inst_t old, new;
 
644
645	/*
646	 * If the calling address is more that 24 bits away,
647	 * then we had to use a trampoline to make the call.
648	 * Otherwise just update the call site.
649	 */
650	if (test_24bit_addr(ip, addr) && test_24bit_addr(ip, old_addr)) {
651		/* within range */
652		old = ftrace_call_replace(ip, old_addr, 1);
653		new = ftrace_call_replace(ip, addr, 1);
654		return ftrace_modify_code(ip, old, new);
655	} else if (core_kernel_text(ip)) {
656		/*
657		 * We always patch out of range locations to go to the regs
658		 * variant, so there is nothing to do here
659		 */
660		return 0;
661	} else if (!IS_ENABLED(CONFIG_MODULES)) {
662		/* We should not get here without modules */
 
 
 
 
 
 
 
 
663		return -EINVAL;
664	}
665
666	/*
667	 * Out of range jumps are called from modules.
668	 */
669	if (!rec->arch.mod) {
670		pr_err("No module loaded\n");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
671		return -EINVAL;
672	}
673
674	return __ftrace_modify_call(rec, old_addr, addr);
675}
676#endif
677
678int ftrace_update_ftrace_func(ftrace_func_t func)
679{
680	unsigned long ip = (unsigned long)(&ftrace_call);
681	ppc_inst_t old, new;
682	int ret;
683
 
 
 
 
 
 
 
684	old = ppc_inst_read((u32 *)&ftrace_call);
685	new = ftrace_call_replace(ip, (unsigned long)func, 1);
686	ret = ftrace_modify_code(ip, old, new);
687
688	/* Also update the regs callback function */
689	if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) && !ret) {
690		ip = (unsigned long)(&ftrace_regs_call);
691		old = ppc_inst_read((u32 *)&ftrace_regs_call);
692		new = ftrace_call_replace(ip, (unsigned long)func, 1);
693		ret = ftrace_modify_code(ip, old, new);
694	}
695
696	return ret;
697}
698
699/*
700 * Use the default ftrace_modify_all_code, but without
701 * stop_machine().
702 */
703void arch_ftrace_update_code(int command)
704{
705	ftrace_modify_all_code(command);
706}
707
708#ifdef CONFIG_PPC64
709#define PACATOC offsetof(struct paca_struct, kernel_toc)
710
711extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[];
712
713void ftrace_free_init_tramp(void)
714{
715	int i;
716
717	for (i = 0; i < NUM_FTRACE_TRAMPS && ftrace_tramps[i]; i++)
718		if (ftrace_tramps[i] == (unsigned long)ftrace_tramp_init) {
719			ftrace_tramps[i] = 0;
720			return;
721		}
722}
723
724int __init ftrace_dyn_arch_init(void)
725{
726	int i;
 
 
 
 
 
 
 
 
 
 
727	unsigned int *tramp[] = { ftrace_tramp_text, ftrace_tramp_init };
 
 
 
728	u32 stub_insns[] = {
729		PPC_RAW_LD(_R12, _R13, PACATOC),
 
 
 
 
 
 
 
730		PPC_RAW_ADDIS(_R12, _R12, 0),
731		PPC_RAW_ADDI(_R12, _R12, 0),
732		PPC_RAW_MTCTR(_R12),
733		PPC_RAW_BCTR()
 
 
 
 
 
 
734	};
735	unsigned long addr;
736	long reladdr;
737
738	if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS))
739		addr = ppc_global_function_entry((void *)ftrace_regs_caller);
740	else
741		addr = ppc_global_function_entry((void *)ftrace_caller);
742
743	reladdr = addr - kernel_toc_addr();
 
 
 
 
 
 
 
 
 
 
 
744
745	if (reladdr >= SZ_2G || reladdr < -(long)SZ_2G) {
746		pr_err("Address of %ps out of range of kernel_toc.\n",
747				(void *)addr);
748		return -1;
749	}
750
751	for (i = 0; i < 2; i++) {
752		memcpy(tramp[i], stub_insns, sizeof(stub_insns));
753		tramp[i][1] |= PPC_HA(reladdr);
754		tramp[i][2] |= PPC_LO(reladdr);
755		add_ftrace_tramp((unsigned long)tramp[i]);
 
 
 
 
 
 
 
 
756	}
757
758	return 0;
759}
760#endif
761
762#ifdef CONFIG_FUNCTION_GRAPH_TRACER
763
764extern void ftrace_graph_call(void);
765extern void ftrace_graph_stub(void);
766
767static int ftrace_modify_ftrace_graph_caller(bool enable)
768{
769	unsigned long ip = (unsigned long)(&ftrace_graph_call);
770	unsigned long addr = (unsigned long)(&ftrace_graph_caller);
771	unsigned long stub = (unsigned long)(&ftrace_graph_stub);
772	ppc_inst_t old, new;
773
774	if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_ARGS))
775		return 0;
776
777	old = ftrace_call_replace(ip, enable ? stub : addr, 0);
778	new = ftrace_call_replace(ip, enable ? addr : stub, 0);
779
780	return ftrace_modify_code(ip, old, new);
781}
782
783int ftrace_enable_ftrace_graph_caller(void)
784{
785	return ftrace_modify_ftrace_graph_caller(true);
786}
787
788int ftrace_disable_ftrace_graph_caller(void)
789{
790	return ftrace_modify_ftrace_graph_caller(false);
791}
792
793/*
794 * Hook the return address and push it in the stack of return addrs
795 * in current thread info. Return the address we want to divert to.
796 */
797static unsigned long
798__prepare_ftrace_return(unsigned long parent, unsigned long ip, unsigned long sp)
799{
800	unsigned long return_hooker;
801	int bit;
802
803	if (unlikely(ftrace_graph_is_dead()))
804		goto out;
805
806	if (unlikely(atomic_read(&current->tracing_graph_pause)))
807		goto out;
808
809	bit = ftrace_test_recursion_trylock(ip, parent);
810	if (bit < 0)
811		goto out;
812
813	return_hooker = ppc_function_entry(return_to_handler);
814
815	if (!function_graph_enter(parent, ip, 0, (unsigned long *)sp))
816		parent = return_hooker;
817
818	ftrace_test_recursion_unlock(bit);
819out:
820	return parent;
821}
822
823#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
824void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
825		       struct ftrace_ops *op, struct ftrace_regs *fregs)
826{
827	fregs->regs.link = __prepare_ftrace_return(parent_ip, ip, fregs->regs.gpr[1]);
828}
829#else
830unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
831				    unsigned long sp)
832{
833	return __prepare_ftrace_return(parent, ip, sp);
834}
835#endif
836#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
837
838#ifdef CONFIG_PPC64_ELF_ABI_V1
839char *arch_ftrace_match_adjust(char *str, const char *search)
840{
841	if (str[0] == '.' && search[0] != '.')
842		return str + 1;
843	else
844		return str;
845}
846#endif /* CONFIG_PPC64_ELF_ABI_V1 */
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Code for replacing ftrace calls with jumps.
  4 *
  5 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
  6 *
  7 * Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box.
  8 *
  9 * Added function graph tracer code, taken from x86 that was written
 10 * by Frederic Weisbecker, and ported to PPC by Steven Rostedt.
 11 *
 12 */
 13
 14#define pr_fmt(fmt) "ftrace-powerpc: " fmt
 15
 16#include <linux/spinlock.h>
 17#include <linux/hardirq.h>
 18#include <linux/uaccess.h>
 19#include <linux/module.h>
 20#include <linux/ftrace.h>
 21#include <linux/percpu.h>
 22#include <linux/init.h>
 23#include <linux/list.h>
 24
 25#include <asm/cacheflush.h>
 26#include <asm/text-patching.h>
 27#include <asm/ftrace.h>
 28#include <asm/syscall.h>
 29#include <asm/inst.h>
 30#include <asm/sections.h>
 31
 32#define	NUM_FTRACE_TRAMPS	2
 
 
 
 
 
 
 33static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS];
 34
 35unsigned long ftrace_call_adjust(unsigned long addr)
 
 36{
 37	if (addr >= (unsigned long)__exittext_begin && addr < (unsigned long)__exittext_end)
 38		return 0;
 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))
 44			addr += MCOUNT_INSN_SIZE;
 45	}
 46
 47	return addr;
 48}
 49
 50static ppc_inst_t ftrace_create_branch_inst(unsigned long ip, unsigned long addr, int link)
 51{
 52	ppc_inst_t op;
 53
 54	WARN_ON(!is_offset_in_branch_range(addr - ip));
 55	create_branch(&op, (u32 *)ip, addr, link ? BRANCH_SET_LINK : 0);
 56
 57	return op;
 58}
 59
 60static inline int ftrace_read_inst(unsigned long ip, ppc_inst_t *op)
 
 61{
 62	if (copy_inst_from_kernel_nofault(op, (void *)ip)) {
 63		pr_err("0x%lx: fetching instruction failed\n", ip);
 
 
 
 
 
 
 
 
 
 
 64		return -EFAULT;
 
 
 
 
 
 
 65	}
 66
 67	return 0;
 
 68}
 69
 70static inline int ftrace_validate_inst(unsigned long ip, ppc_inst_t inst)
 
 
 
 71{
 72	ppc_inst_t op;
 73	int ret;
 
 
 74
 75	ret = ftrace_read_inst(ip, &op);
 76	if (!ret && !ppc_inst_equal(op, inst)) {
 77		pr_err("0x%lx: expected (%08lx) != found (%08lx)\n",
 78		       ip, ppc_inst_as_ulong(inst), ppc_inst_as_ulong(op));
 79		ret = -EINVAL;
 80	}
 81
 82	return ret;
 
 
 83}
 84
 85static inline int ftrace_modify_code(unsigned long ip, ppc_inst_t old, ppc_inst_t new)
 86{
 87	int ret = ftrace_validate_inst(ip, old);
 88
 89	if (!ret && !ppc_inst_equal(old, new))
 90		ret = patch_instruction((u32 *)ip, new);
 
 
 91
 92	return ret;
 93}
 94
 95static int is_bl_op(ppc_inst_t op)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 96{
 97	return (ppc_inst_val(op) & ~PPC_LI_MASK) == PPC_RAW_BL(0);
 98}
 
 99
100static unsigned long find_ftrace_tramp(unsigned long ip)
101{
102	int i;
103
104	for (i = 0; i < NUM_FTRACE_TRAMPS; i++)
 
 
 
 
105		if (!ftrace_tramps[i])
106			continue;
107		else if (is_offset_in_branch_range(ftrace_tramps[i] - ip))
108			return ftrace_tramps[i];
109
110	return 0;
111}
112
113#ifdef CONFIG_MODULES
114static unsigned long ftrace_lookup_module_stub(unsigned long ip, unsigned long addr)
115{
116	struct module *mod = NULL;
117
118	preempt_disable();
119	mod = __module_text_address(ip);
120	preempt_enable();
 
 
121
122	if (!mod)
123		pr_err("No module loaded at addr=%lx\n", ip);
124
125	return (addr == (unsigned long)ftrace_caller ? mod->arch.tramp : mod->arch.tramp_regs);
126}
127#else
128static unsigned long ftrace_lookup_module_stub(unsigned long ip, unsigned long addr)
 
 
 
129{
130	return 0;
131}
132#endif
 
 
 
 
 
133
134static unsigned long ftrace_get_ool_stub(struct dyn_ftrace *rec)
135{
136#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
137	return rec->arch.ool_stub;
138#else
139	BUILD_BUG();
140#endif
141}
142
143static int ftrace_get_call_inst(struct dyn_ftrace *rec, unsigned long addr, ppc_inst_t *call_inst)
144{
145	unsigned long ip;
146	unsigned long stub;
 
147
148	if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
149		ip = ftrace_get_ool_stub(rec) + MCOUNT_INSN_SIZE; /* second instruction in stub */
150	else
151		ip = rec->ip;
152
153	if (!is_offset_in_branch_range(addr - ip) && addr != FTRACE_ADDR &&
154	    addr != FTRACE_REGS_ADDR) {
155		/* This can only happen with ftrace direct */
156		if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS)) {
157			pr_err("0x%lx (0x%lx): Unexpected target address 0x%lx\n",
158			       ip, rec->ip, addr);
159			return -EINVAL;
160		}
161		addr = FTRACE_ADDR;
162	}
163
164	if (is_offset_in_branch_range(addr - ip))
165		/* Within range */
166		stub = addr;
167	else if (core_kernel_text(ip))
168		/* We would be branching to one of our ftrace stubs */
169		stub = find_ftrace_tramp(ip);
170	else
171		stub = ftrace_lookup_module_stub(ip, addr);
172
173	if (!stub) {
174		pr_err("0x%lx (0x%lx): No ftrace stubs reachable\n", ip, rec->ip);
175		return -EINVAL;
 
 
 
 
 
176	}
177
178	*call_inst = ftrace_create_branch_inst(ip, stub, 1);
179	return 0;
180}
181
182static int ftrace_init_ool_stub(struct module *mod, struct dyn_ftrace *rec)
183{
184#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
185	static int ool_stub_text_index, ool_stub_text_end_index, ool_stub_inittext_index;
186	int ret = 0, ool_stub_count, *ool_stub_index;
187	ppc_inst_t inst;
188	/*
189	 * See ftrace_entry.S if changing the below instruction sequence, as we rely on
190	 * decoding the last branch instruction here to recover the correct function ip.
191	 */
192	struct ftrace_ool_stub *ool_stub, ool_stub_template = {
193		.insn = {
194			PPC_RAW_MFLR(_R0),
195			PPC_RAW_NOP(),		/* bl ftrace_caller */
196			PPC_RAW_MTLR(_R0),
197			PPC_RAW_NOP()		/* b rec->ip + 4 */
198		}
199	};
200
201	WARN_ON(rec->arch.ool_stub);
 
 
 
 
202
203	if (is_kernel_inittext(rec->ip)) {
204		ool_stub = ftrace_ool_stub_inittext;
205		ool_stub_index = &ool_stub_inittext_index;
206		ool_stub_count = ftrace_ool_stub_inittext_count;
207	} else if (is_kernel_text(rec->ip)) {
208		/*
209		 * ftrace records are sorted, so we first use up the stub area within .text
210		 * (ftrace_ool_stub_text) before using the area at the end of .text
211		 * (ftrace_ool_stub_text_end), unless the stub is out of range of the record.
212		 */
213		if (ool_stub_text_index >= ftrace_ool_stub_text_count ||
214		    !is_offset_in_branch_range((long)rec->ip -
215					       (long)&ftrace_ool_stub_text[ool_stub_text_index])) {
216			ool_stub = ftrace_ool_stub_text_end;
217			ool_stub_index = &ool_stub_text_end_index;
218			ool_stub_count = ftrace_ool_stub_text_end_count;
219		} else {
220			ool_stub = ftrace_ool_stub_text;
221			ool_stub_index = &ool_stub_text_index;
222			ool_stub_count = ftrace_ool_stub_text_count;
223		}
224#ifdef CONFIG_MODULES
225	} else if (mod) {
226		ool_stub = mod->arch.ool_stubs;
227		ool_stub_index = &mod->arch.ool_stub_index;
228		ool_stub_count = mod->arch.ool_stub_count;
229#endif
230	} else {
231		return -EINVAL;
232	}
233
234	ool_stub += (*ool_stub_index)++;
 
235
236	if (WARN_ON(*ool_stub_index > ool_stub_count))
237		return -EINVAL;
238
239	if (!is_offset_in_branch_range((long)rec->ip - (long)&ool_stub->insn[0]) ||
240	    !is_offset_in_branch_range((long)(rec->ip + MCOUNT_INSN_SIZE) -
241				       (long)&ool_stub->insn[3])) {
242		pr_err("%s: ftrace ool stub out of range (%p -> %p).\n",
243					__func__, (void *)rec->ip, (void *)&ool_stub->insn[0]);
244		return -EINVAL;
 
245	}
246
247	rec->arch.ool_stub = (unsigned long)&ool_stub->insn[0];
 
 
 
248
249	/* bl ftrace_caller */
250	if (!mod)
251		ret = ftrace_get_call_inst(rec, (unsigned long)ftrace_caller, &inst);
252#ifdef CONFIG_MODULES
253	else
254		/*
255		 * We can't use ftrace_get_call_inst() since that uses
256		 * __module_text_address(rec->ip) to look up the module.
257		 * But, since the module is not fully formed at this stage,
258		 * the lookup fails. We know the target though, so generate
259		 * the branch inst directly.
260		 */
261		inst = ftrace_create_branch_inst(ftrace_get_ool_stub(rec) + MCOUNT_INSN_SIZE,
262						 mod->arch.tramp, 1);
263#endif
264	ool_stub_template.insn[1] = ppc_inst_val(inst);
265
266	/* b rec->ip + 4 */
267	if (!ret && create_branch(&inst, &ool_stub->insn[3], rec->ip + MCOUNT_INSN_SIZE, 0))
268		return -EINVAL;
269	ool_stub_template.insn[3] = ppc_inst_val(inst);
270
271	if (!ret)
272		ret = patch_instructions((u32 *)ool_stub, (u32 *)&ool_stub_template,
273					 sizeof(ool_stub_template), false);
274
275	return ret;
276#else /* !CONFIG_PPC_FTRACE_OUT_OF_LINE */
277	BUILD_BUG();
278#endif
279}
280
281#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
282static const struct ftrace_ops *powerpc_rec_get_ops(struct dyn_ftrace *rec)
283{
284	const struct ftrace_ops *ops = NULL;
 
285
286	if (rec->flags & FTRACE_FL_CALL_OPS_EN) {
287		ops = ftrace_find_unique_ops(rec);
288		WARN_ON_ONCE(!ops);
 
 
 
 
 
 
 
 
 
 
 
289	}
290
291	if (!ops)
292		ops = &ftrace_list_ops;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
294	return ops;
295}
296
297static int ftrace_rec_set_ops(struct dyn_ftrace *rec, const struct ftrace_ops *ops)
 
 
 
 
 
 
298{
299	if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
300		return patch_ulong((void *)(ftrace_get_ool_stub(rec) - sizeof(unsigned long)),
301				   (unsigned long)ops);
302	else
303		return patch_ulong((void *)(rec->ip - MCOUNT_INSN_SIZE - sizeof(unsigned long)),
304				   (unsigned long)ops);
305}
306
307static int ftrace_rec_set_nop_ops(struct dyn_ftrace *rec)
 
308{
309	return ftrace_rec_set_ops(rec, &ftrace_nop_ops);
310}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
312static int ftrace_rec_update_ops(struct dyn_ftrace *rec)
313{
314	return ftrace_rec_set_ops(rec, powerpc_rec_get_ops(rec));
315}
316#else
317static int ftrace_rec_set_nop_ops(struct dyn_ftrace *rec) { return 0; }
318static int ftrace_rec_update_ops(struct dyn_ftrace *rec) { return 0; }
319#endif
320
321#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
322int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, unsigned long addr)
323{
324	/* This should never be called since we override ftrace_replace_code() */
325	WARN_ON(1);
326	return -EINVAL;
327}
328#endif
329
330int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
331{
332	ppc_inst_t old, new;
333	unsigned long ip = rec->ip;
334	int ret = 0;
 
 
 
 
 
 
 
335
336	/* This can only ever be called during module load */
337	if (WARN_ON(!IS_ENABLED(CONFIG_MODULES) || core_kernel_text(ip)))
338		return -EINVAL;
 
339
340	old = ppc_inst(PPC_RAW_NOP());
341	if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE)) {
342		ip = ftrace_get_ool_stub(rec) + MCOUNT_INSN_SIZE; /* second instruction in stub */
343		ret = ftrace_get_call_inst(rec, (unsigned long)ftrace_caller, &old);
344	}
345
346	ret |= ftrace_get_call_inst(rec, addr, &new);
 
 
 
 
347
348	if (!ret)
349		ret = ftrace_modify_code(ip, old, new);
 
 
 
350
351	ret = ftrace_rec_update_ops(rec);
352	if (ret)
353		return ret;
354
355	if (!ret && IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
356		ret = ftrace_modify_code(rec->ip, ppc_inst(PPC_RAW_NOP()),
357			 ppc_inst(PPC_RAW_BRANCH((long)ftrace_get_ool_stub(rec) - (long)rec->ip)));
358
359	return ret;
360}
361
362int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr)
363{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364	/*
365	 * This should never be called since we override ftrace_replace_code(),
366	 * as well as ftrace_init_nop()
 
367	 */
368	WARN_ON(1);
369	return -EINVAL;
 
 
 
 
370}
371
372void ftrace_replace_code(int enable)
 
 
 
 
373{
374	ppc_inst_t old, new, call_inst, new_call_inst;
375	ppc_inst_t nop_inst = ppc_inst(PPC_RAW_NOP());
376	unsigned long ip, new_addr, addr;
377	struct ftrace_rec_iter *iter;
378	struct dyn_ftrace *rec;
379	int ret = 0, update;
380
381	for_ftrace_rec_iter(iter) {
382		rec = ftrace_rec_iter_record(iter);
383		ip = rec->ip;
 
 
384
385		if (rec->flags & FTRACE_FL_DISABLED && !(rec->flags & FTRACE_FL_ENABLED))
386			continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
388		addr = ftrace_get_addr_curr(rec);
389		new_addr = ftrace_get_addr_new(rec);
390		update = ftrace_update_record(rec, enable);
391
392		if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE) && update != FTRACE_UPDATE_IGNORE) {
393			ip = ftrace_get_ool_stub(rec) + MCOUNT_INSN_SIZE;
394			ret = ftrace_get_call_inst(rec, (unsigned long)ftrace_caller, &nop_inst);
395			if (ret)
396				goto out;
397		}
398
399		switch (update) {
400		case FTRACE_UPDATE_IGNORE:
401		default:
402			continue;
403		case FTRACE_UPDATE_MODIFY_CALL:
404			ret = ftrace_get_call_inst(rec, new_addr, &new_call_inst);
405			ret |= ftrace_get_call_inst(rec, addr, &call_inst);
406			ret |= ftrace_rec_update_ops(rec);
407			old = call_inst;
408			new = new_call_inst;
409			break;
410		case FTRACE_UPDATE_MAKE_NOP:
411			ret = ftrace_get_call_inst(rec, addr, &call_inst);
412			ret |= ftrace_rec_set_nop_ops(rec);
413			old = call_inst;
414			new = nop_inst;
415			break;
416		case FTRACE_UPDATE_MAKE_CALL:
417			ret = ftrace_get_call_inst(rec, new_addr, &call_inst);
418			ret |= ftrace_rec_update_ops(rec);
419			old = nop_inst;
420			new = call_inst;
421			break;
422		}
423
424		if (!ret)
425			ret = ftrace_modify_code(ip, old, new);
426
427		if (!ret && IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE) &&
428		    (update == FTRACE_UPDATE_MAKE_NOP || update == FTRACE_UPDATE_MAKE_CALL)) {
429			/* Update the actual ftrace location */
430			call_inst = ppc_inst(PPC_RAW_BRANCH((long)ftrace_get_ool_stub(rec) -
431							    (long)rec->ip));
432			nop_inst = ppc_inst(PPC_RAW_NOP());
433			ip = rec->ip;
434
435			if (update == FTRACE_UPDATE_MAKE_NOP)
436				ret = ftrace_modify_code(ip, call_inst, nop_inst);
437			else
438				ret = ftrace_modify_code(ip, nop_inst, call_inst);
439
440			if (ret)
441				goto out;
 
 
 
 
442		}
443
444		if (ret)
445			goto out;
 
 
 
 
 
 
 
 
 
446	}
447
448out:
449	if (ret)
450		ftrace_bug(ret, rec);
451	return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452}
 
453
454int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
 
455{
456	unsigned long addr, ip = rec->ip;
457	ppc_inst_t old, new;
458	int ret = 0;
459
460	/* Verify instructions surrounding the ftrace location */
461	if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY)) {
462		/* Expect nops */
463		if (!IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
464			ret = ftrace_validate_inst(ip - 4, ppc_inst(PPC_RAW_NOP()));
465		if (!ret)
466			ret = ftrace_validate_inst(ip, ppc_inst(PPC_RAW_NOP()));
467	} else if (IS_ENABLED(CONFIG_PPC32)) {
468		/* Expected sequence: 'mflr r0', 'stw r0,4(r1)', 'bl _mcount' */
469		ret = ftrace_validate_inst(ip - 8, ppc_inst(PPC_RAW_MFLR(_R0)));
470		if (ret)
471			return ret;
472		ret = ftrace_modify_code(ip - 4, ppc_inst(PPC_RAW_STW(_R0, _R1, 4)),
473					 ppc_inst(PPC_RAW_NOP()));
474	} else if (IS_ENABLED(CONFIG_MPROFILE_KERNEL)) {
475		/* Expected sequence: 'mflr r0', ['std r0,16(r1)'], 'bl _mcount' */
476		ret = ftrace_read_inst(ip - 4, &old);
477		if (!ret && !ppc_inst_equal(old, ppc_inst(PPC_RAW_MFLR(_R0)))) {
478			/* Gcc v5.x emit the additional 'std' instruction, gcc v6.x don't */
479			ret = ftrace_validate_inst(ip - 8, ppc_inst(PPC_RAW_MFLR(_R0)));
480			if (ret)
481				return ret;
482			ret = ftrace_modify_code(ip - 4, ppc_inst(PPC_RAW_STD(_R0, _R1, 16)),
483						 ppc_inst(PPC_RAW_NOP()));
484		}
485	} else {
486		return -EINVAL;
487	}
488
489	if (ret)
490		return ret;
491
492	/* Set up out-of-line stub */
493	if (IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
494		return ftrace_init_ool_stub(mod, rec);
495
496	/* Nop-out the ftrace location */
497	new = ppc_inst(PPC_RAW_NOP());
498	addr = MCOUNT_ADDR;
499	if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY)) {
500		/* we instead patch-in the 'mflr r0' */
501		old = ppc_inst(PPC_RAW_NOP());
502		new = ppc_inst(PPC_RAW_MFLR(_R0));
503		ret = ftrace_modify_code(ip - 4, old, new);
504	} else if (is_offset_in_branch_range(addr - ip)) {
505		/* Within range */
506		old = ftrace_create_branch_inst(ip, addr, 1);
507		ret = ftrace_modify_code(ip, old, new);
508	} else if (core_kernel_text(ip) || (IS_ENABLED(CONFIG_MODULES) && mod)) {
509		/*
510		 * We would be branching to a linker-generated stub, or to the module _mcount
511		 * stub. Let's just confirm we have a 'bl' here.
512		 */
513		ret = ftrace_read_inst(ip, &old);
514		if (ret)
515			return ret;
516		if (!is_bl_op(old)) {
517			pr_err("0x%lx: expected (bl) != found (%08lx)\n", ip, ppc_inst_as_ulong(old));
518			return -EINVAL;
519		}
520		ret = patch_instruction((u32 *)ip, new);
521	} else {
522		return -EINVAL;
523	}
524
525	return ret;
526}
 
527
528int ftrace_update_ftrace_func(ftrace_func_t func)
529{
530	unsigned long ip = (unsigned long)(&ftrace_call);
531	ppc_inst_t old, new;
532	int ret;
533
534	/*
535	 * When using CALL_OPS, the function to call is associated with the
536	 * call site, and we don't have a global function pointer to update.
537	 */
538	if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
539		return 0;
540
541	old = ppc_inst_read((u32 *)&ftrace_call);
542	new = ftrace_create_branch_inst(ip, ppc_function_entry(func), 1);
543	ret = ftrace_modify_code(ip, old, new);
544
545	/* Also update the regs callback function */
546	if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) && !ret) {
547		ip = (unsigned long)(&ftrace_regs_call);
548		old = ppc_inst_read((u32 *)&ftrace_regs_call);
549		new = ftrace_create_branch_inst(ip, ppc_function_entry(func), 1);
550		ret = ftrace_modify_code(ip, old, new);
551	}
552
553	return ret;
554}
555
556/*
557 * Use the default ftrace_modify_all_code, but without
558 * stop_machine().
559 */
560void arch_ftrace_update_code(int command)
561{
562	ftrace_modify_all_code(command);
563}
564
 
 
 
 
 
565void ftrace_free_init_tramp(void)
566{
567	int i;
568
569	for (i = 0; i < NUM_FTRACE_TRAMPS && ftrace_tramps[i]; i++)
570		if (ftrace_tramps[i] == (unsigned long)ftrace_tramp_init) {
571			ftrace_tramps[i] = 0;
572			return;
573		}
574}
575
576static void __init add_ftrace_tramp(unsigned long tramp)
577{
578	int i;
579
580	for (i = 0; i < NUM_FTRACE_TRAMPS; i++)
581		if (!ftrace_tramps[i]) {
582			ftrace_tramps[i] = tramp;
583			return;
584		}
585}
586
587int __init ftrace_dyn_arch_init(void)
588{
589	unsigned int *tramp[] = { ftrace_tramp_text, ftrace_tramp_init };
590	unsigned long addr = FTRACE_REGS_ADDR;
591	long reladdr;
592	int i;
593	u32 stub_insns[] = {
594#ifdef CONFIG_PPC_KERNEL_PCREL
595		/* pla r12,addr */
596		PPC_PREFIX_MLS | __PPC_PRFX_R(1),
597		PPC_INST_PADDI | ___PPC_RT(_R12),
598		PPC_RAW_MTCTR(_R12),
599		PPC_RAW_BCTR()
600#elif defined(CONFIG_PPC64)
601		PPC_RAW_LD(_R12, _R13, offsetof(struct paca_struct, kernel_toc)),
602		PPC_RAW_ADDIS(_R12, _R12, 0),
603		PPC_RAW_ADDI(_R12, _R12, 0),
604		PPC_RAW_MTCTR(_R12),
605		PPC_RAW_BCTR()
606#else
607		PPC_RAW_LIS(_R12, 0),
608		PPC_RAW_ADDI(_R12, _R12, 0),
609		PPC_RAW_MTCTR(_R12),
610		PPC_RAW_BCTR()
611#endif
612	};
 
 
613
614	if (IS_ENABLED(CONFIG_PPC_KERNEL_PCREL)) {
615		for (i = 0; i < 2; i++) {
616			reladdr = addr - (unsigned long)tramp[i];
617
618			if (reladdr >= (long)SZ_8G || reladdr < -(long)SZ_8G) {
619				pr_err("Address of %ps out of range of pcrel address.\n",
620					(void *)addr);
621				return -1;
622			}
623
624			memcpy(tramp[i], stub_insns, sizeof(stub_insns));
625			tramp[i][0] |= IMM_H18(reladdr);
626			tramp[i][1] |= IMM_L(reladdr);
627			add_ftrace_tramp((unsigned long)tramp[i]);
628		}
629	} else if (IS_ENABLED(CONFIG_PPC64)) {
630		reladdr = addr - kernel_toc_addr();
631
632		if (reladdr >= (long)SZ_2G || reladdr < -(long long)SZ_2G) {
633			pr_err("Address of %ps out of range of kernel_toc.\n",
634				(void *)addr);
635			return -1;
636		}
637
638		for (i = 0; i < 2; i++) {
639			memcpy(tramp[i], stub_insns, sizeof(stub_insns));
640			tramp[i][1] |= PPC_HA(reladdr);
641			tramp[i][2] |= PPC_LO(reladdr);
642			add_ftrace_tramp((unsigned long)tramp[i]);
643		}
644	} else {
645		for (i = 0; i < 2; i++) {
646			memcpy(tramp[i], stub_insns, sizeof(stub_insns));
647			tramp[i][0] |= PPC_HA(addr);
648			tramp[i][1] |= PPC_LO(addr);
649			add_ftrace_tramp((unsigned long)tramp[i]);
650		}
651	}
652
653	return 0;
654}
 
655
656#ifdef CONFIG_FUNCTION_GRAPH_TRACER
657void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
658		       struct ftrace_ops *op, struct ftrace_regs *fregs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
659{
660	unsigned long sp = arch_ftrace_regs(fregs)->regs.gpr[1];
661	int bit;
662
663	if (unlikely(ftrace_graph_is_dead()))
664		goto out;
665
666	if (unlikely(atomic_read(&current->tracing_graph_pause)))
667		goto out;
668
669	bit = ftrace_test_recursion_trylock(ip, parent_ip);
670	if (bit < 0)
671		goto out;
672
673	if (!function_graph_enter(parent_ip, ip, 0, (unsigned long *)sp))
674		parent_ip = ppc_function_entry(return_to_handler);
 
 
675
676	ftrace_test_recursion_unlock(bit);
677out:
678	arch_ftrace_regs(fregs)->regs.link = parent_ip;
679}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
680#endif /* CONFIG_FUNCTION_GRAPH_TRACER */