Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 142771
b: refs/heads/master
c: a053958
h: refs/heads/master
i:
  142769: 3f326f0
  142767: bf2b500
v: v3
  • Loading branch information
Ingo Molnar committed Apr 7, 2009
1 parent 22c7d6a commit adde71e
Show file tree
Hide file tree
Showing 37 changed files with 1,561 additions and 356 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e2494e1b42ebac402324105d57646489d19e2b01
refs/heads/master: a053958f073740219df1da596b42bfefdab634c4
13 changes: 7 additions & 6 deletions trunk/Documentation/tracepoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,14 @@ used to export the defined tracepoints.

* Probe / tracepoint example

See the example provided in samples/tracepoints/src
See the example provided in samples/tracepoints

Compile them with your kernel.
Compile them with your kernel. They are built during 'make' (not
'make modules') when CONFIG_SAMPLE_TRACEPOINTS=m.

Run, as root :
modprobe tracepoint-example (insmod order is not important)
modprobe tracepoint-probe-example
cat /proc/tracepoint-example (returns an expected error)
rmmod tracepoint-example tracepoint-probe-example
modprobe tracepoint-sample (insmod order is not important)
modprobe tracepoint-probe-sample
cat /proc/tracepoint-sample (returns an expected error)
rmmod tracepoint-sample tracepoint-probe-sample
dmesg
69 changes: 41 additions & 28 deletions trunk/arch/x86/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
*
* 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.
* 2) Wait for any running NMIs to finish and set a flag that says
* we are modifying code, it is done in an atomic operation.
* 3) Write the code
* 4) clear the flag.
* 5) 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
Expand All @@ -95,9 +95,9 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
* are the same as what exists.
*/

#define MOD_CODE_WRITE_FLAG (1 << 31) /* set when NMI should do the write */
static atomic_t nmi_running = 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 */

Expand All @@ -114,6 +114,20 @@ int ftrace_arch_read_dyn_info(char *buf, int size)
return r;
}

static void clear_mod_flag(void)
{
int old = atomic_read(&nmi_running);

for (;;) {
int new = old & ~MOD_CODE_WRITE_FLAG;

if (old == new)
break;

old = atomic_cmpxchg(&nmi_running, old, new);
}
}

static void ftrace_mod_code(void)
{
/*
Expand All @@ -127,27 +141,39 @@ static void ftrace_mod_code(void)

/* if we fail, then kill any new writers */
if (mod_code_status)
mod_code_write = 0;
clear_mod_flag();
}

void ftrace_nmi_enter(void)
{
atomic_inc(&nmi_running);
/* Must have nmi_running seen before reading write flag */
smp_mb();
if (mod_code_write) {
if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) {
smp_rmb();
ftrace_mod_code();
atomic_inc(&nmi_update_count);
}
/* Must have previous changes seen before executions */
smp_mb();
}

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

static void wait_for_nmi_and_set_mod_flag(void)
{
if (!atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG))
return;

do {
cpu_relax();
} while (atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG));

nmi_wait_count++;
}

static void wait_for_nmi(void)
{
if (!atomic_read(&nmi_running))
Expand All @@ -167,28 +193,19 @@ do_ftrace_mod_code(unsigned long ip, void *new_code)
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();
wait_for_nmi_and_set_mod_flag();

/* 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();

clear_mod_flag();
wait_for_nmi();

return mod_code_status;
Expand Down Expand Up @@ -393,7 +410,6 @@ int ftrace_disable_ftrace_graph_caller(void)
void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
{
unsigned long old;
unsigned long long calltime;
int faulted;
struct ftrace_graph_ent trace;
unsigned long return_hooker = (unsigned long)
Expand Down Expand Up @@ -436,10 +452,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
return;
}

calltime = trace_clock_local();

if (ftrace_push_return_trace(old, calltime,
self_addr, &trace.depth) == -EBUSY) {
if (ftrace_push_return_trace(old, self_addr, &trace.depth) == -EBUSY) {
*parent = old;
return;
}
Expand Down
17 changes: 9 additions & 8 deletions trunk/arch/x86/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,13 +638,13 @@ static void __used __kprobes kretprobe_trampoline_holder(void)
#else
" pushf\n"
/*
* Skip cs, ip, orig_ax.
* Skip cs, ip, orig_ax and gs.
* trampoline_handler() will plug in these values
*/
" subl $12, %esp\n"
" subl $16, %esp\n"
" pushl %fs\n"
" pushl %ds\n"
" pushl %es\n"
" pushl %ds\n"
" pushl %eax\n"
" pushl %ebp\n"
" pushl %edi\n"
Expand All @@ -655,19 +655,19 @@ static void __used __kprobes kretprobe_trampoline_holder(void)
" movl %esp, %eax\n"
" call trampoline_handler\n"
/* Move flags to cs */
" movl 52(%esp), %edx\n"
" movl %edx, 48(%esp)\n"
" movl 56(%esp), %edx\n"
" movl %edx, 52(%esp)\n"
/* Replace saved flags with true return address. */
" movl %eax, 52(%esp)\n"
" movl %eax, 56(%esp)\n"
" popl %ebx\n"
" popl %ecx\n"
" popl %edx\n"
" popl %esi\n"
" popl %edi\n"
" popl %ebp\n"
" popl %eax\n"
/* Skip ip, orig_ax, es, ds, fs */
" addl $20, %esp\n"
/* Skip ds, es, fs, gs, orig_ax and ip */
" addl $24, %esp\n"
" popf\n"
#endif
" ret\n");
Expand All @@ -691,6 +691,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
regs->cs = __KERNEL_CS;
#else
regs->cs = __KERNEL_CS | get_kernel_rpl();
regs->gs = 0;
#endif
regs->ip = trampoline_address;
regs->orig_ax = ~0UL;
Expand Down
16 changes: 16 additions & 0 deletions trunk/fs/debugfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

static struct vfsmount *debugfs_mount;
static int debugfs_mount_count;
static bool debugfs_registered;

static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev)
{
Expand Down Expand Up @@ -496,6 +497,16 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
}
EXPORT_SYMBOL_GPL(debugfs_rename);

/**
* debugfs_initialized - Tells whether debugfs has been registered
*/
bool debugfs_initialized(void)
{
return debugfs_registered;
}
EXPORT_SYMBOL_GPL(debugfs_initialized);


static struct kobject *debug_kobj;

static int __init debugfs_init(void)
Expand All @@ -509,11 +520,16 @@ static int __init debugfs_init(void)
retval = register_filesystem(&debug_fs_type);
if (retval)
kobject_put(debug_kobj);
else
debugfs_registered = true;

return retval;
}

static void __exit debugfs_exit(void)
{
debugfs_registered = false;

simple_release_fs(&debugfs_mount, &debugfs_mount_count);
unregister_filesystem(&debug_fs_type);
kobject_put(debug_kobj);
Expand Down
8 changes: 8 additions & 0 deletions trunk/include/linux/debugfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ struct dentry *debugfs_create_bool(const char *name, mode_t mode,
struct dentry *debugfs_create_blob(const char *name, mode_t mode,
struct dentry *parent,
struct debugfs_blob_wrapper *blob);

bool debugfs_initialized(void);

#else

#include <linux/err.h>
Expand Down Expand Up @@ -183,6 +186,11 @@ static inline struct dentry *debugfs_create_blob(const char *name, mode_t mode,
return ERR_PTR(-ENODEV);
}

static inline bool debugfs_initialized(void)
{
return false;
}

#endif

#endif
15 changes: 10 additions & 5 deletions trunk/include/linux/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,15 @@ enum {
};

struct dyn_ftrace {
unsigned long ip; /* address of mcount call-site */
unsigned long flags;
struct dyn_arch_ftrace arch;
union {
unsigned long ip; /* address of mcount call-site */
struct dyn_ftrace *freelist;
};
union {
unsigned long flags;
struct dyn_ftrace *newlist;
};
struct dyn_arch_ftrace arch;
};

int ftrace_force_update(void);
Expand Down Expand Up @@ -369,8 +375,7 @@ struct ftrace_ret_stack {
extern void return_to_handler(void);

extern int
ftrace_push_return_trace(unsigned long ret, unsigned long long time,
unsigned long func, int *depth);
ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth);
extern void
ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret);

Expand Down
11 changes: 8 additions & 3 deletions trunk/include/linux/ring_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ struct ring_buffer_event {
/**
* enum ring_buffer_type - internal ring buffer types
*
* @RINGBUF_TYPE_PADDING: Left over page padding
* array is ignored
* size is variable depending on how much
* @RINGBUF_TYPE_PADDING: Left over page padding or discarded event
* If time_delta is 0:
* array is ignored
* size is variable depending on how much
* padding is needed
* If time_delta is non zero:
* everything else same as RINGBUF_TYPE_DATA
*
* @RINGBUF_TYPE_TIME_EXTEND: Extend the time delta
* array[0] = time delta (28 .. 59)
Expand Down Expand Up @@ -65,6 +68,8 @@ ring_buffer_event_time_delta(struct ring_buffer_event *event)
return event->time_delta;
}

void ring_buffer_event_discard(struct ring_buffer_event *event);

/*
* size is in bytes for each per CPU buffer.
*/
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,8 @@ struct task_struct {
int curr_ret_stack;
/* Stack of return addresses for return function tracing */
struct ftrace_ret_stack *ret_stack;
/* time stamp for last schedule */
unsigned long long ftrace_timestamp;
/*
* Number of functions that haven't been traced
* because of depth overrun.
Expand Down
3 changes: 1 addition & 2 deletions trunk/init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ static void __init do_basic_setup(void)
{
rcu_init_sched(); /* needed by module_init stage. */
init_workqueues();
cpuset_init_smp();
usermodehelper_init();
driver_init();
init_irq_proc();
Expand Down Expand Up @@ -865,8 +866,6 @@ static int __init kernel_init(void * unused)
smp_init();
sched_init_smp();

cpuset_init_smp();

do_basic_setup();

/*
Expand Down
15 changes: 13 additions & 2 deletions trunk/kernel/extable.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,22 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/ftrace.h>
#include <linux/memory.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/ftrace.h>
#include <asm/uaccess.h>

#include <asm/sections.h>
#include <asm/uaccess.h>

/*
* mutex protecting text section modification (dynamic code patching).
* some users need to sleep (allocating memory...) while they hold this lock.
*
* NOT exported to modules - patching kernel text is a really delicate matter.
*/
DEFINE_MUTEX(text_mutex);

extern struct exception_table_entry __start___ex_table[];
extern struct exception_table_entry __stop___ex_table[];
Expand Down
Loading

0 comments on commit adde71e

Please sign in to comment.