Skip to content

Commit

Permalink
Merge branches 'tracing/ftrace', 'tracing/markers', 'tracing/mmiotrac…
Browse files Browse the repository at this point in the history
…e', 'tracing/nmisafe', 'tracing/tracepoints' and 'tracing/urgent' into tracing/core
  • Loading branch information
Ingo Molnar committed Nov 3, 2008
6 parents d9e5407 + 5d9881e + fd3fdf1 + a26a2a2 + 127cafb + c2c8052 commit 7a895f5
Show file tree
Hide file tree
Showing 17 changed files with 398 additions and 174 deletions.
5 changes: 5 additions & 0 deletions arch/arm/include/asm/ftrace.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#ifndef _ASM_ARM_FTRACE
#define _ASM_ARM_FTRACE

#ifndef __ASSEMBLY__
static inline void ftrace_nmi_enter(void) { }
static inline void ftrace_nmi_exit(void) { }
#endif

#ifdef CONFIG_FUNCTION_TRACER
#define MCOUNT_ADDR ((long)(mcount))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
Expand Down
5 changes: 5 additions & 0 deletions arch/powerpc/include/asm/ftrace.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#ifndef _ASM_POWERPC_FTRACE
#define _ASM_POWERPC_FTRACE

#ifndef __ASSEMBLY__
static inline void ftrace_nmi_enter(void) { }
static inline void ftrace_nmi_exit(void) { }
#endif

#ifdef CONFIG_FUNCTION_TRACER
#define MCOUNT_ADDR ((long)(_mcount))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
Expand Down
5 changes: 5 additions & 0 deletions arch/sh/include/asm/ftrace.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#ifndef __ASM_SH_FTRACE_H
#define __ASM_SH_FTRACE_H

#ifndef __ASSEMBLY__
static inline void ftrace_nmi_enter(void) { }
static inline void ftrace_nmi_exit(void) { }
#endif

#ifndef __ASSEMBLY__
extern void mcount(void);
#endif
Expand Down
5 changes: 5 additions & 0 deletions arch/sparc/include/asm/ftrace.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#ifndef _ASM_SPARC64_FTRACE
#define _ASM_SPARC64_FTRACE

#ifndef __ASSEMBLY__
static inline void ftrace_nmi_enter(void) { }
static inline void ftrace_nmi_exit(void) { }
#endif

#ifdef CONFIG_MCOUNT
#define MCOUNT_ADDR ((long)(_mcount))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
Expand Down
4 changes: 0 additions & 4 deletions arch/x86/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,10 @@ config IOMMU_LEAK
Add a simple leak tracer to the IOMMU code. This is useful when you
are debugging a buggy device driver that leaks IOMMU mappings.

config MMIOTRACE_HOOKS
bool

config MMIOTRACE
bool "Memory mapped IO tracing"
depends on DEBUG_KERNEL && PCI
select TRACING
select MMIOTRACE_HOOKS
help
Mmiotrace traces Memory Mapped I/O access and is meant for
debugging and reverse engineering. It is called from the ioremap
Expand Down
15 changes: 15 additions & 0 deletions arch/x86/include/asm/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
*/
return addr - 1;
}

#ifdef CONFIG_DYNAMIC_FTRACE
extern void ftrace_nmi_enter(void);
extern void ftrace_nmi_exit(void);
#else
static inline void ftrace_nmi_enter(void) { }
static inline void ftrace_nmi_exit(void) { }
#endif
#endif /* __ASSEMBLY__ */

#else /* CONFIG_FUNCTION_TRACER */

#ifndef __ASSEMBLY__
static inline void ftrace_nmi_enter(void) { }
static inline void ftrace_nmi_exit(void) { }
#endif

#endif /* CONFIG_FUNCTION_TRACER */
Expand Down
129 changes: 128 additions & 1 deletion arch/x86/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,133 @@ unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
return calc.code;
}

/*
* Modifying code must take extra care. On an SMP machine, if
* the code being modified is also being executed on another CPU
* that CPU will have undefined results and possibly take a GPF.
* We use kstop_machine to stop other CPUS from exectuing code.
* But this does not stop NMIs from happening. We still need
* to protect against that. We separate out the modification of
* the code to take care of this.
*
* Two buffers are added: An IP buffer and a "code" buffer.
*
* 1) Put the instruction pointer into the IP buffer
* and the new code into the "code" buffer.
* 2) Set a flag that says we are modifying code
* 3) Wait for any running NMIs to finish.
* 4) Write the code
* 5) clear the flag.
* 6) Wait for any running NMIs to finish.
*
* If an NMI is executed, the first thing it does is to call
* "ftrace_nmi_enter". This will check if the flag is set to write
* and if it is, it will write what is in the IP and "code" buffers.
*
* The trick is, it does not matter if everyone is writing the same
* content to the code location. Also, if a CPU is executing code
* it is OK to write to that code location if the contents being written
* are the same as what exists.
*/

static atomic_t in_nmi = ATOMIC_INIT(0);
static int mod_code_status; /* holds return value of text write */
static int mod_code_write; /* set when NMI should do the write */
static void *mod_code_ip; /* holds the IP to write to */
static void *mod_code_newcode; /* holds the text to write to the IP */

static unsigned nmi_wait_count;
static atomic_t nmi_update_count = ATOMIC_INIT(0);

int ftrace_arch_read_dyn_info(char *buf, int size)
{
int r;

r = snprintf(buf, size, "%u %u",
nmi_wait_count,
atomic_read(&nmi_update_count));
return r;
}

static void ftrace_mod_code(void)
{
/*
* Yes, more than one CPU process can be writing to mod_code_status.
* (and the code itself)
* But if one were to fail, then they all should, and if one were
* to succeed, then they all should.
*/
mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
MCOUNT_INSN_SIZE);

}

void ftrace_nmi_enter(void)
{
atomic_inc(&in_nmi);
/* Must have in_nmi seen before reading write flag */
smp_mb();
if (mod_code_write) {
ftrace_mod_code();
atomic_inc(&nmi_update_count);
}
}

void ftrace_nmi_exit(void)
{
/* Finish all executions before clearing in_nmi */
smp_wmb();
atomic_dec(&in_nmi);
}

static void wait_for_nmi(void)
{
int waited = 0;

while (atomic_read(&in_nmi)) {
waited = 1;
cpu_relax();
}

if (waited)
nmi_wait_count++;
}

static int
do_ftrace_mod_code(unsigned long ip, void *new_code)
{
mod_code_ip = (void *)ip;
mod_code_newcode = new_code;

/* The buffers need to be visible before we let NMIs write them */
smp_wmb();

mod_code_write = 1;

/* Make sure write bit is visible before we wait on NMIs */
smp_mb();

wait_for_nmi();

/* Make sure all running NMIs have finished before we write the code */
smp_mb();

ftrace_mod_code();

/* Make sure the write happens before clearing the bit */
smp_wmb();

mod_code_write = 0;

/* make sure NMIs see the cleared bit */
smp_mb();

wait_for_nmi();

return mod_code_status;
}


int
ftrace_modify_code(unsigned long ip, unsigned char *old_code,
unsigned char *new_code)
Expand All @@ -81,7 +208,7 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
return -EINVAL;

/* replace the text with the new text */
if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE))
if (do_ftrace_mod_code(ip, new_code))
return -EPERM;

sync_core();
Expand Down
3 changes: 1 addition & 2 deletions arch/x86/mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ obj-$(CONFIG_X86_PTDUMP) += dump_pagetables.o

obj-$(CONFIG_HIGHMEM) += highmem_32.o

obj-$(CONFIG_MMIOTRACE_HOOKS) += kmmio.o
obj-$(CONFIG_MMIOTRACE) += mmiotrace.o
mmiotrace-y := pf_in.o mmio-mod.o
mmiotrace-y := kmmio.o pf_in.o mmio-mod.o
obj-$(CONFIG_MMIOTRACE_TEST) += testmmiotrace.o

obj-$(CONFIG_NUMA) += numa_$(BITS).o
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr)
{
#ifdef CONFIG_MMIOTRACE_HOOKS
#ifdef CONFIG_MMIOTRACE
if (unlikely(is_kmmio_active()))
if (kmmio_handler(regs, addr) == 1)
return -1;
Expand Down
3 changes: 3 additions & 0 deletions include/linux/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ extern void ftrace_caller(void);
extern void ftrace_call(void);
extern void mcount_call(void);

/* May be defined in arch */
extern int ftrace_arch_read_dyn_info(char *buf, int size);

/**
* ftrace_modify_code - modify code segment
* @ip: the address of the code segment
Expand Down
15 changes: 13 additions & 2 deletions include/linux/hardirq.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <linux/smp_lock.h>
#include <linux/lockdep.h>
#include <asm/hardirq.h>
#include <asm/ftrace.h>
#include <asm/system.h>

/*
Expand Down Expand Up @@ -161,7 +162,17 @@ extern void irq_enter(void);
*/
extern void irq_exit(void);

#define nmi_enter() do { lockdep_off(); __irq_enter(); } while (0)
#define nmi_exit() do { __irq_exit(); lockdep_on(); } while (0)
#define nmi_enter() \
do { \
ftrace_nmi_enter(); \
lockdep_off(); \
__irq_enter(); \
} while (0)
#define nmi_exit() \
do { \
__irq_exit(); \
lockdep_on(); \
ftrace_nmi_exit(); \
} while (0)

#endif /* LINUX_HARDIRQ_H */
2 changes: 0 additions & 2 deletions include/linux/marker.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,6 @@ extern marker_probe_func __mark_empty_function;

extern void marker_probe_cb(const struct marker *mdata,
void *call_private, ...);
extern void marker_probe_cb_noarg(const struct marker *mdata,
void *call_private, ...);

/*
* Connect a probe to a marker.
Expand Down
4 changes: 4 additions & 0 deletions include/linux/tracepoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ extern int tracepoint_probe_register(const char *name, void *probe);
*/
extern int tracepoint_probe_unregister(const char *name, void *probe);

extern int tracepoint_probe_register_noupdate(const char *name, void *probe);
extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe);
extern void tracepoint_probe_update_all(void);

struct tracepoint_iter {
struct module *module;
struct tracepoint *tracepoint;
Expand Down
Loading

0 comments on commit 7a895f5

Please sign in to comment.