You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'tracing/ftrace' into auto-ftrace-next
This commit is contained in:
@@ -528,6 +528,10 @@ KBUILD_CFLAGS += -g
|
||||
KBUILD_AFLAGS += -gdwarf-2
|
||||
endif
|
||||
|
||||
ifdef CONFIG_FTRACE
|
||||
KBUILD_CFLAGS += -pg
|
||||
endif
|
||||
|
||||
# We trigger additional mismatches with less inlining
|
||||
ifdef CONFIG_DEBUG_SECTION_MISMATCH
|
||||
KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
|
||||
|
||||
@@ -14,6 +14,8 @@ config ARM
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_KPROBES if (!XIP_KERNEL)
|
||||
select HAVE_KRETPROBES if (HAVE_KPROBES)
|
||||
select HAVE_FTRACE if (!XIP_KERNEL)
|
||||
select HAVE_DYNAMIC_FTRACE if (HAVE_FTRACE)
|
||||
help
|
||||
The ARM series is a line of low-power-consumption RISC chip designs
|
||||
licensed by ARM Ltd and targeted at embedded applications and
|
||||
|
||||
@@ -69,6 +69,12 @@ SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
|
||||
|
||||
targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
|
||||
head.o misc.o $(OBJS)
|
||||
|
||||
ifeq ($(CONFIG_FTRACE),y)
|
||||
ORIG_CFLAGS := $(KBUILD_CFLAGS)
|
||||
KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
|
||||
endif
|
||||
|
||||
EXTRA_CFLAGS := -fpic -fno-builtin
|
||||
EXTRA_AFLAGS :=
|
||||
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
|
||||
AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
|
||||
|
||||
ifdef CONFIG_DYNAMIC_FTRACE
|
||||
CFLAGS_REMOVE_ftrace.o = -pg
|
||||
endif
|
||||
|
||||
# Object file lists.
|
||||
|
||||
obj-y := compat.o entry-armv.o entry-common.o irq.o \
|
||||
@@ -18,6 +22,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
|
||||
obj-$(CONFIG_ISA_DMA) += dma-isa.o
|
||||
obj-$(CONFIG_PCI) += bios32.o isa.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
|
||||
obj-$(CONFIG_ATAGS_PROC) += atags.o
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
||||
/*
|
||||
* libgcc functions - functions that are used internally by the
|
||||
@@ -181,3 +182,7 @@ EXPORT_SYMBOL(_find_next_bit_be);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(copy_page);
|
||||
|
||||
#ifdef CONFIG_FTRACE
|
||||
EXPORT_SYMBOL(mcount);
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/arch/entry-macro.S>
|
||||
|
||||
#include "entry-header.S"
|
||||
@@ -99,6 +100,56 @@ ENTRY(ret_from_fork)
|
||||
#undef CALL
|
||||
#define CALL(x) .long x
|
||||
|
||||
#ifdef CONFIG_FTRACE
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
ENTRY(mcount)
|
||||
stmdb sp!, {r0-r3, lr}
|
||||
mov r0, lr
|
||||
sub r0, r0, #MCOUNT_INSN_SIZE
|
||||
|
||||
.globl mcount_call
|
||||
mcount_call:
|
||||
bl ftrace_stub
|
||||
ldmia sp!, {r0-r3, pc}
|
||||
|
||||
ENTRY(ftrace_caller)
|
||||
stmdb sp!, {r0-r3, lr}
|
||||
ldr r1, [fp, #-4]
|
||||
mov r0, lr
|
||||
sub r0, r0, #MCOUNT_INSN_SIZE
|
||||
|
||||
.globl ftrace_call
|
||||
ftrace_call:
|
||||
bl ftrace_stub
|
||||
ldmia sp!, {r0-r3, pc}
|
||||
|
||||
#else
|
||||
|
||||
ENTRY(mcount)
|
||||
stmdb sp!, {r0-r3, lr}
|
||||
ldr r0, =ftrace_trace_function
|
||||
ldr r2, [r0]
|
||||
adr r0, ftrace_stub
|
||||
cmp r0, r2
|
||||
bne trace
|
||||
ldmia sp!, {r0-r3, pc}
|
||||
|
||||
trace:
|
||||
ldr r1, [fp, #-4]
|
||||
mov r0, lr
|
||||
sub r0, r0, #MCOUNT_INSN_SIZE
|
||||
mov lr, pc
|
||||
mov pc, r2
|
||||
ldmia sp!, {r0-r3, pc}
|
||||
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
.globl ftrace_stub
|
||||
ftrace_stub:
|
||||
mov pc, lr
|
||||
|
||||
#endif /* CONFIG_FTRACE */
|
||||
|
||||
/*=============================================================================
|
||||
* SWI handler
|
||||
*-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Dynamic function tracing support.
|
||||
*
|
||||
* Copyright (C) 2008 Abhishek Sagar <sagar.abhishek@gmail.com>
|
||||
*
|
||||
* For licencing details, see COPYING.
|
||||
*
|
||||
* Defines low-level handling of mcount calls when the kernel
|
||||
* is compiled with the -pg flag. When using dynamic ftrace, the
|
||||
* mcount call-sites get patched lazily with NOP till they are
|
||||
* enabled. All code mutation routines here take effect atomically.
|
||||
*/
|
||||
|
||||
#include <linux/ftrace.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
||||
#define PC_OFFSET 8
|
||||
#define BL_OPCODE 0xeb000000
|
||||
#define BL_OFFSET_MASK 0x00ffffff
|
||||
|
||||
static unsigned long bl_insn;
|
||||
static const unsigned long NOP = 0xe1a00000; /* mov r0, r0 */
|
||||
|
||||
unsigned char *ftrace_nop_replace(void)
|
||||
{
|
||||
return (char *)&NOP;
|
||||
}
|
||||
|
||||
/* construct a branch (BL) instruction to addr */
|
||||
unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr)
|
||||
{
|
||||
long offset;
|
||||
|
||||
offset = (long)addr - (long)(pc + PC_OFFSET);
|
||||
if (unlikely(offset < -33554432 || offset > 33554428)) {
|
||||
/* Can't generate branches that far (from ARM ARM). Ftrace
|
||||
* doesn't generate branches outside of kernel text.
|
||||
*/
|
||||
WARN_ON_ONCE(1);
|
||||
return NULL;
|
||||
}
|
||||
offset = (offset >> 2) & BL_OFFSET_MASK;
|
||||
bl_insn = BL_OPCODE | offset;
|
||||
return (unsigned char *)&bl_insn;
|
||||
}
|
||||
|
||||
int ftrace_modify_code(unsigned long pc, unsigned char *old_code,
|
||||
unsigned char *new_code)
|
||||
{
|
||||
unsigned long err = 0, replaced = 0, old, new;
|
||||
|
||||
old = *(unsigned long *)old_code;
|
||||
new = *(unsigned long *)new_code;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"1: ldr %1, [%2] \n"
|
||||
" cmp %1, %4 \n"
|
||||
"2: streq %3, [%2] \n"
|
||||
" cmpne %1, %3 \n"
|
||||
" movne %0, #2 \n"
|
||||
"3:\n"
|
||||
|
||||
".section .fixup, \"ax\"\n"
|
||||
"4: mov %0, #1 \n"
|
||||
" b 3b \n"
|
||||
".previous\n"
|
||||
|
||||
".section __ex_table, \"a\"\n"
|
||||
" .long 1b, 4b \n"
|
||||
" .long 2b, 4b \n"
|
||||
".previous\n"
|
||||
|
||||
: "=r"(err), "=r"(replaced)
|
||||
: "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced)
|
||||
: "memory");
|
||||
|
||||
if (!err && (replaced == old))
|
||||
flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int ftrace_update_ftrace_func(ftrace_func_t func)
|
||||
{
|
||||
int ret;
|
||||
unsigned long pc, old;
|
||||
unsigned char *new;
|
||||
|
||||
pc = (unsigned long)&ftrace_call;
|
||||
memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
|
||||
new = ftrace_call_replace(pc, (unsigned long)func);
|
||||
ret = ftrace_modify_code(pc, (unsigned char *)&old, new);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ftrace_mcount_set(unsigned long *data)
|
||||
{
|
||||
unsigned long pc, old;
|
||||
unsigned long *addr = data;
|
||||
unsigned char *new;
|
||||
|
||||
pc = (unsigned long)&mcount_call;
|
||||
memcpy(&old, &mcount_call, MCOUNT_INSN_SIZE);
|
||||
new = ftrace_call_replace(pc, *addr);
|
||||
*addr = ftrace_modify_code(pc, (unsigned char *)&old, new);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* run from kstop_machine */
|
||||
int __init ftrace_dyn_arch_init(void *data)
|
||||
{
|
||||
ftrace_mcount_set(data);
|
||||
return 0;
|
||||
}
|
||||
@@ -274,7 +274,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
|
||||
* for kretprobe handlers which should normally be interested in r0 only
|
||||
* anyway.
|
||||
*/
|
||||
static void __attribute__((naked)) __kprobes kretprobe_trampoline(void)
|
||||
void __naked __kprobes kretprobe_trampoline(void)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"stmdb sp!, {r0 - r11} \n\t"
|
||||
|
||||
@@ -105,11 +105,13 @@ config ARCH_NO_VIRT_TO_BUS
|
||||
config PPC
|
||||
bool
|
||||
default y
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_FTRACE
|
||||
select HAVE_IDE
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KRETPROBES
|
||||
select HAVE_LMB
|
||||
select HAVE_OPROFILE
|
||||
|
||||
config EARLY_PRINTK
|
||||
bool
|
||||
|
||||
@@ -12,6 +12,18 @@ CFLAGS_prom_init.o += -fPIC
|
||||
CFLAGS_btext.o += -fPIC
|
||||
endif
|
||||
|
||||
ifdef CONFIG_FTRACE
|
||||
# Do not trace early boot code
|
||||
CFLAGS_REMOVE_cputable.o = -pg
|
||||
CFLAGS_REMOVE_prom_init.o = -pg
|
||||
|
||||
ifdef CONFIG_DYNAMIC_FTRACE
|
||||
# dynamic ftrace setup.
|
||||
CFLAGS_REMOVE_ftrace.o = -pg
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
obj-y := cputable.o ptrace.o syscalls.o \
|
||||
irq.o align.o signal_32.o pmc.o vdso.o \
|
||||
init_task.o process.o systbl.o idle.o \
|
||||
@@ -78,6 +90,8 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \
|
||||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
obj64-$(CONFIG_AUDIT) += compat_audit.o
|
||||
|
||||
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
||||
|
||||
obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
|
||||
|
||||
ifneq ($(CONFIG_PPC_INDIRECT_IO),y)
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
||||
#undef SHOW_SYSCALLS
|
||||
#undef SHOW_SYSCALLS_TASK
|
||||
@@ -1035,3 +1036,129 @@ machine_check_in_rtas:
|
||||
/* XXX load up BATs and panic */
|
||||
|
||||
#endif /* CONFIG_PPC_RTAS */
|
||||
|
||||
#ifdef CONFIG_FTRACE
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
_GLOBAL(mcount)
|
||||
_GLOBAL(_mcount)
|
||||
stwu r1,-48(r1)
|
||||
stw r3, 12(r1)
|
||||
stw r4, 16(r1)
|
||||
stw r5, 20(r1)
|
||||
stw r6, 24(r1)
|
||||
mflr r3
|
||||
stw r7, 28(r1)
|
||||
mfcr r5
|
||||
stw r8, 32(r1)
|
||||
stw r9, 36(r1)
|
||||
stw r10,40(r1)
|
||||
stw r3, 44(r1)
|
||||
stw r5, 8(r1)
|
||||
subi r3, r3, MCOUNT_INSN_SIZE
|
||||
.globl mcount_call
|
||||
mcount_call:
|
||||
bl ftrace_stub
|
||||
nop
|
||||
lwz r6, 8(r1)
|
||||
lwz r0, 44(r1)
|
||||
lwz r3, 12(r1)
|
||||
mtctr r0
|
||||
lwz r4, 16(r1)
|
||||
mtcr r6
|
||||
lwz r5, 20(r1)
|
||||
lwz r6, 24(r1)
|
||||
lwz r0, 52(r1)
|
||||
lwz r7, 28(r1)
|
||||
lwz r8, 32(r1)
|
||||
mtlr r0
|
||||
lwz r9, 36(r1)
|
||||
lwz r10,40(r1)
|
||||
addi r1, r1, 48
|
||||
bctr
|
||||
|
||||
_GLOBAL(ftrace_caller)
|
||||
/* Based off of objdump optput from glibc */
|
||||
stwu r1,-48(r1)
|
||||
stw r3, 12(r1)
|
||||
stw r4, 16(r1)
|
||||
stw r5, 20(r1)
|
||||
stw r6, 24(r1)
|
||||
mflr r3
|
||||
lwz r4, 52(r1)
|
||||
mfcr r5
|
||||
stw r7, 28(r1)
|
||||
stw r8, 32(r1)
|
||||
stw r9, 36(r1)
|
||||
stw r10,40(r1)
|
||||
stw r3, 44(r1)
|
||||
stw r5, 8(r1)
|
||||
subi r3, r3, MCOUNT_INSN_SIZE
|
||||
.globl ftrace_call
|
||||
ftrace_call:
|
||||
bl ftrace_stub
|
||||
nop
|
||||
lwz r6, 8(r1)
|
||||
lwz r0, 44(r1)
|
||||
lwz r3, 12(r1)
|
||||
mtctr r0
|
||||
lwz r4, 16(r1)
|
||||
mtcr r6
|
||||
lwz r5, 20(r1)
|
||||
lwz r6, 24(r1)
|
||||
lwz r0, 52(r1)
|
||||
lwz r7, 28(r1)
|
||||
lwz r8, 32(r1)
|
||||
mtlr r0
|
||||
lwz r9, 36(r1)
|
||||
lwz r10,40(r1)
|
||||
addi r1, r1, 48
|
||||
bctr
|
||||
#else
|
||||
_GLOBAL(mcount)
|
||||
_GLOBAL(_mcount)
|
||||
stwu r1,-48(r1)
|
||||
stw r3, 12(r1)
|
||||
stw r4, 16(r1)
|
||||
stw r5, 20(r1)
|
||||
stw r6, 24(r1)
|
||||
mflr r3
|
||||
lwz r4, 52(r1)
|
||||
mfcr r5
|
||||
stw r7, 28(r1)
|
||||
stw r8, 32(r1)
|
||||
stw r9, 36(r1)
|
||||
stw r10,40(r1)
|
||||
stw r3, 44(r1)
|
||||
stw r5, 8(r1)
|
||||
|
||||
subi r3, r3, MCOUNT_INSN_SIZE
|
||||
LOAD_REG_ADDR(r5, ftrace_trace_function)
|
||||
lwz r5,0(r5)
|
||||
|
||||
mtctr r5
|
||||
bctrl
|
||||
|
||||
nop
|
||||
|
||||
lwz r6, 8(r1)
|
||||
lwz r0, 44(r1)
|
||||
lwz r3, 12(r1)
|
||||
mtctr r0
|
||||
lwz r4, 16(r1)
|
||||
mtcr r6
|
||||
lwz r5, 20(r1)
|
||||
lwz r6, 24(r1)
|
||||
lwz r0, 52(r1)
|
||||
lwz r7, 28(r1)
|
||||
lwz r8, 32(r1)
|
||||
mtlr r0
|
||||
lwz r9, 36(r1)
|
||||
lwz r10,40(r1)
|
||||
addi r1, r1, 48
|
||||
bctr
|
||||
#endif
|
||||
|
||||
_GLOBAL(ftrace_stub)
|
||||
blr
|
||||
|
||||
#endif /* CONFIG_MCOUNT */
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <asm/bug.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
||||
/*
|
||||
* System calls.
|
||||
@@ -870,3 +871,67 @@ _GLOBAL(enter_prom)
|
||||
ld r0,16(r1)
|
||||
mtlr r0
|
||||
blr
|
||||
|
||||
#ifdef CONFIG_FTRACE
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
_GLOBAL(mcount)
|
||||
_GLOBAL(_mcount)
|
||||
/* Taken from output of objdump from lib64/glibc */
|
||||
mflr r3
|
||||
stdu r1, -112(r1)
|
||||
std r3, 128(r1)
|
||||
subi r3, r3, MCOUNT_INSN_SIZE
|
||||
.globl mcount_call
|
||||
mcount_call:
|
||||
bl ftrace_stub
|
||||
nop
|
||||
ld r0, 128(r1)
|
||||
mtlr r0
|
||||
addi r1, r1, 112
|
||||
blr
|
||||
|
||||
_GLOBAL(ftrace_caller)
|
||||
/* Taken from output of objdump from lib64/glibc */
|
||||
mflr r3
|
||||
ld r11, 0(r1)
|
||||
stdu r1, -112(r1)
|
||||
std r3, 128(r1)
|
||||
ld r4, 16(r11)
|
||||
subi r3, r3, MCOUNT_INSN_SIZE
|
||||
.globl ftrace_call
|
||||
ftrace_call:
|
||||
bl ftrace_stub
|
||||
nop
|
||||
ld r0, 128(r1)
|
||||
mtlr r0
|
||||
addi r1, r1, 112
|
||||
_GLOBAL(ftrace_stub)
|
||||
blr
|
||||
#else
|
||||
_GLOBAL(mcount)
|
||||
blr
|
||||
|
||||
_GLOBAL(_mcount)
|
||||
/* Taken from output of objdump from lib64/glibc */
|
||||
mflr r3
|
||||
ld r11, 0(r1)
|
||||
stdu r1, -112(r1)
|
||||
std r3, 128(r1)
|
||||
ld r4, 16(r11)
|
||||
|
||||
subi r3, r3, MCOUNT_INSN_SIZE
|
||||
LOAD_REG_ADDR(r5,ftrace_trace_function)
|
||||
ld r5,0(r5)
|
||||
ld r5,0(r5)
|
||||
mtctr r5
|
||||
bctrl
|
||||
|
||||
nop
|
||||
ld r0, 128(r1)
|
||||
mtlr r0
|
||||
addi r1, r1, 112
|
||||
_GLOBAL(ftrace_stub)
|
||||
blr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Code for replacing ftrace calls with jumps.
|
||||
*
|
||||
* Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
|
||||
*
|
||||
* Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
||||
|
||||
static unsigned int ftrace_nop = 0x60000000;
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
# define GET_ADDR(addr) addr
|
||||
#else
|
||||
/* PowerPC64's functions are data that points to the functions */
|
||||
# define GET_ADDR(addr) *(unsigned long *)addr
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned int notrace ftrace_calc_offset(long ip, long addr)
|
||||
{
|
||||
return (int)(addr - ip);
|
||||
}
|
||||
|
||||
notrace unsigned char *ftrace_nop_replace(void)
|
||||
{
|
||||
return (char *)&ftrace_nop;
|
||||
}
|
||||
|
||||
notrace unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
|
||||
{
|
||||
static unsigned int op;
|
||||
|
||||
/*
|
||||
* It would be nice to just use create_function_call, but that will
|
||||
* update the code itself. Here we need to just return the
|
||||
* instruction that is going to be modified, without modifying the
|
||||
* code.
|
||||
*/
|
||||
addr = GET_ADDR(addr);
|
||||
|
||||
/* Set to "bl addr" */
|
||||
op = 0x48000001 | (ftrace_calc_offset(ip, addr) & 0x03fffffc);
|
||||
|
||||
/*
|
||||
* No locking needed, this must be called via kstop_machine
|
||||
* which in essence is like running on a uniprocessor machine.
|
||||
*/
|
||||
return (unsigned char *)&op;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
# define _ASM_ALIGN " .align 3 "
|
||||
# define _ASM_PTR " .llong "
|
||||
#else
|
||||
# define _ASM_ALIGN " .align 2 "
|
||||
# define _ASM_PTR " .long "
|
||||
#endif
|
||||
|
||||
notrace int
|
||||
ftrace_modify_code(unsigned long ip, unsigned char *old_code,
|
||||
unsigned char *new_code)
|
||||
{
|
||||
unsigned replaced;
|
||||
unsigned old = *(unsigned *)old_code;
|
||||
unsigned new = *(unsigned *)new_code;
|
||||
int faulted = 0;
|
||||
|
||||
/*
|
||||
* Note: Due to modules and __init, code can
|
||||
* disappear and change, we need to protect against faulting
|
||||
* as well as code changing.
|
||||
*
|
||||
* No real locking needed, this code is run through
|
||||
* kstop_machine.
|
||||
*/
|
||||
asm volatile (
|
||||
"1: lwz %1, 0(%2)\n"
|
||||
" cmpw %1, %5\n"
|
||||
" bne 2f\n"
|
||||
" stwu %3, 0(%2)\n"
|
||||
"2:\n"
|
||||
".section .fixup, \"ax\"\n"
|
||||
"3: li %0, 1\n"
|
||||
" b 2b\n"
|
||||
".previous\n"
|
||||
".section __ex_table,\"a\"\n"
|
||||
_ASM_ALIGN "\n"
|
||||
_ASM_PTR "1b, 3b\n"
|
||||
".previous"
|
||||
: "=r"(faulted), "=r"(replaced)
|
||||
: "r"(ip), "r"(new),
|
||||
"0"(faulted), "r"(old)
|
||||
: "memory");
|
||||
|
||||
if (replaced != old && replaced != new)
|
||||
faulted = 2;
|
||||
|
||||
if (!faulted)
|
||||
flush_icache_range(ip, ip + 8);
|
||||
|
||||
return faulted;
|
||||
}
|
||||
|
||||
notrace int ftrace_update_ftrace_func(ftrace_func_t func)
|
||||
{
|
||||
unsigned long ip = (unsigned long)(&ftrace_call);
|
||||
unsigned char old[MCOUNT_INSN_SIZE], *new;
|
||||
int ret;
|
||||
|
||||
memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
|
||||
new = ftrace_call_replace(ip, (unsigned long)func);
|
||||
ret = ftrace_modify_code(ip, old, new);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
notrace int ftrace_mcount_set(unsigned long *data)
|
||||
{
|
||||
unsigned long ip = (long)(&mcount_call);
|
||||
unsigned long *addr = data;
|
||||
unsigned char old[MCOUNT_INSN_SIZE], *new;
|
||||
|
||||
/*
|
||||
* Replace the mcount stub with a pointer to the
|
||||
* ip recorder function.
|
||||
*/
|
||||
memcpy(old, &mcount_call, MCOUNT_INSN_SIZE);
|
||||
new = ftrace_call_replace(ip, *addr);
|
||||
*addr = ftrace_modify_code(ip, old, new);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init ftrace_dyn_arch_init(void *data)
|
||||
{
|
||||
/* This is running in kstop_machine */
|
||||
|
||||
ftrace_mcount_set(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,8 @@ EXPORT_SYMBOL(_outsl_ns);
|
||||
|
||||
#define IO_CHECK_ALIGN(v,a) ((((unsigned long)(v)) & ((a) - 1)) == 0)
|
||||
|
||||
void _memset_io(volatile void __iomem *addr, int c, unsigned long n)
|
||||
notrace void
|
||||
_memset_io(volatile void __iomem *addr, int c, unsigned long n)
|
||||
{
|
||||
void *p = (void __force *)addr;
|
||||
u32 lc = c;
|
||||
|
||||
@@ -98,7 +98,7 @@ EXPORT_SYMBOL(irq_desc);
|
||||
|
||||
int distribute_irqs = 1;
|
||||
|
||||
static inline unsigned long get_hard_enabled(void)
|
||||
static inline notrace unsigned long get_hard_enabled(void)
|
||||
{
|
||||
unsigned long enabled;
|
||||
|
||||
@@ -108,13 +108,13 @@ static inline unsigned long get_hard_enabled(void)
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline void set_soft_enabled(unsigned long enable)
|
||||
static inline notrace void set_soft_enabled(unsigned long enable)
|
||||
{
|
||||
__asm__ __volatile__("stb %0,%1(13)"
|
||||
: : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
|
||||
}
|
||||
|
||||
void raw_local_irq_restore(unsigned long en)
|
||||
notrace void raw_local_irq_restore(unsigned long en)
|
||||
{
|
||||
/*
|
||||
* get_paca()->soft_enabled = en;
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <asm/div64.h>
|
||||
#include <asm/signal.h>
|
||||
#include <asm/dcr.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
extern void transfer_to_handler(void);
|
||||
@@ -67,6 +68,10 @@ EXPORT_SYMBOL(single_step_exception);
|
||||
EXPORT_SYMBOL(sys_sigreturn);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FTRACE
|
||||
EXPORT_SYMBOL(_mcount);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(strcpy);
|
||||
EXPORT_SYMBOL(strncpy);
|
||||
EXPORT_SYMBOL(strcat);
|
||||
|
||||
@@ -81,7 +81,7 @@ int ucache_bsize;
|
||||
* from the address that it was linked at, so we must use RELOC/PTRRELOC
|
||||
* to access static data (including strings). -- paulus
|
||||
*/
|
||||
unsigned long __init early_init(unsigned long dt_ptr)
|
||||
notrace unsigned long __init early_init(unsigned long dt_ptr)
|
||||
{
|
||||
unsigned long offset = reloc_offset();
|
||||
struct cpu_spec *spec;
|
||||
@@ -111,7 +111,7 @@ unsigned long __init early_init(unsigned long dt_ptr)
|
||||
* This is called very early on the boot process, after a minimal
|
||||
* MMU environment has been set up but before MMU_init is called.
|
||||
*/
|
||||
void __init machine_init(unsigned long dt_ptr, unsigned long phys)
|
||||
notrace void __init machine_init(unsigned long dt_ptr, unsigned long phys)
|
||||
{
|
||||
/* Enable early debugging if any specified (see udbg.h) */
|
||||
udbg_early_init();
|
||||
@@ -133,7 +133,7 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys)
|
||||
|
||||
#ifdef CONFIG_BOOKE_WDT
|
||||
/* Checks wdt=x and wdt_period=xx command-line option */
|
||||
int __init early_parse_wdt(char *p)
|
||||
notrace int __init early_parse_wdt(char *p)
|
||||
{
|
||||
if (p && strncmp(p, "0", 1) != 0)
|
||||
booke_wdt_enabled = 1;
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
CFLAGS_bootx_init.o += -fPIC
|
||||
|
||||
ifdef CONFIG_FTRACE
|
||||
# Do not trace early boot code
|
||||
CFLAGS_REMOVE_bootx_init.o = -pg
|
||||
endif
|
||||
|
||||
obj-y += pic.o setup.o time.o feature.o pci.o \
|
||||
sleep.o low_i2c.o cache.o pfunc_core.o \
|
||||
pfunc_base.o
|
||||
|
||||
@@ -11,6 +11,8 @@ config SPARC
|
||||
config SPARC64
|
||||
bool
|
||||
default y
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_FTRACE
|
||||
select HAVE_IDE
|
||||
select HAVE_LMB
|
||||
select HAVE_ARCH_KGDB
|
||||
|
||||
@@ -33,7 +33,7 @@ config DEBUG_PAGEALLOC
|
||||
|
||||
config MCOUNT
|
||||
bool
|
||||
depends on STACK_DEBUG
|
||||
depends on STACK_DEBUG || FTRACE
|
||||
default y
|
||||
|
||||
config FRAME_POINTER
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user