Skip to content

Commit

Permalink
Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/sc…
Browse files Browse the repository at this point in the history
…m/linux/kernel/git/tip/linux-2.6-tip

* 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  tracing/documentation: Cover new frame pointer semantics
  tracing/documentation: Fix a typo in ftrace.txt
  ring-buffer: Check for end of page in iterator
  ring-buffer: Check if ring buffer iterator has stale data
  tracing: Prevent kernel oops with corrupted buffer
  • Loading branch information
Linus Torvalds committed Feb 1, 2010
2 parents 4ca5ded + 0368897 commit 935cc93
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 10 deletions.
26 changes: 23 additions & 3 deletions Documentation/trace/ftrace-design.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
function tracer guts
====================
By Mike Frysinger

Introduction
------------
Expand Down Expand Up @@ -173,14 +174,16 @@ void ftrace_graph_caller(void)

unsigned long *frompc = &...;
unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE;
prepare_ftrace_return(frompc, selfpc);
/* passing frame pointer up is optional -- see below */
prepare_ftrace_return(frompc, selfpc, frame_pointer);

/* restore all state needed by the ABI */
}
#endif

For information on how to implement prepare_ftrace_return(), simply look at
the x86 version. The only architecture-specific piece in it is the setup of
For information on how to implement prepare_ftrace_return(), simply look at the
x86 version (the frame pointer passing is optional; see the next section for
more information). The only architecture-specific piece in it is the setup of
the fault recovery table (the asm(...) code). The rest should be the same
across architectures.

Expand All @@ -205,6 +208,23 @@ void return_to_handler(void)
#endif


HAVE_FUNCTION_GRAPH_FP_TEST
---------------------------

An arch may pass in a unique value (frame pointer) to both the entering and
exiting of a function. On exit, the value is compared and if it does not
match, then it will panic the kernel. This is largely a sanity check for bad
code generation with gcc. If gcc for your port sanely updates the frame
pointer under different opitmization levels, then ignore this option.

However, adding support for it isn't terribly difficult. In your assembly code
that calls prepare_ftrace_return(), pass the frame pointer as the 3rd argument.
Then in the C version of that function, do what the x86 port does and pass it
along to ftrace_push_return_trace() instead of a stub value of 0.

Similarly, when you call ftrace_return_to_handler(), pass it the frame pointer.


HAVE_FTRACE_NMI_ENTER
---------------------

Expand Down
2 changes: 1 addition & 1 deletion Documentation/trace/ftrace.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1625,7 +1625,7 @@ If I am only interested in sys_nanosleep and hrtimer_interrupt:

# echo sys_nanosleep hrtimer_interrupt \
> set_ftrace_filter
# echo ftrace > current_tracer
# echo function > current_tracer
# echo 1 > tracing_enabled
# usleep 1
# echo 0 > tracing_enabled
Expand Down
4 changes: 1 addition & 3 deletions kernel/trace/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ config HAVE_FUNCTION_GRAPH_TRACER
config HAVE_FUNCTION_GRAPH_FP_TEST
bool
help
An arch may pass in a unique value (frame pointer) to both the
entering and exiting of a function. On exit, the value is compared
and if it does not match, then it will panic the kernel.
See Documentation/trace/ftrace-design.txt

config HAVE_FUNCTION_TRACE_MCOUNT_TEST
bool
Expand Down
24 changes: 21 additions & 3 deletions kernel/trace/ring_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,8 @@ struct ring_buffer_iter {
struct ring_buffer_per_cpu *cpu_buffer;
unsigned long head;
struct buffer_page *head_page;
struct buffer_page *cache_reader_page;
unsigned long cache_read;
u64 read_stamp;
};

Expand Down Expand Up @@ -2716,6 +2718,8 @@ static void rb_iter_reset(struct ring_buffer_iter *iter)
iter->read_stamp = cpu_buffer->read_stamp;
else
iter->read_stamp = iter->head_page->page->time_stamp;
iter->cache_reader_page = cpu_buffer->reader_page;
iter->cache_read = cpu_buffer->read;
}

/**
Expand Down Expand Up @@ -3060,13 +3064,22 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
struct ring_buffer_event *event;
int nr_loops = 0;

if (ring_buffer_iter_empty(iter))
return NULL;

cpu_buffer = iter->cpu_buffer;
buffer = cpu_buffer->buffer;

/*
* Check if someone performed a consuming read to
* the buffer. A consuming read invalidates the iterator
* and we need to reset the iterator in this case.
*/
if (unlikely(iter->cache_read != cpu_buffer->read ||
iter->cache_reader_page != cpu_buffer->reader_page))
rb_iter_reset(iter);

again:
if (ring_buffer_iter_empty(iter))
return NULL;

/*
* We repeat when a timestamp is encountered.
* We can get multiple timestamps by nested interrupts or also
Expand All @@ -3081,6 +3094,11 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
if (rb_per_cpu_empty(cpu_buffer))
return NULL;

if (iter->head >= local_read(&iter->head_page->page->commit)) {
rb_inc_iter(iter);
goto again;
}

event = rb_iter_head_event(iter);

switch (event->type_len) {
Expand Down
5 changes: 5 additions & 0 deletions kernel/trace/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,11 @@ void trace_find_cmdline(int pid, char comm[])
return;
}

if (WARN_ON_ONCE(pid < 0)) {
strcpy(comm, "<XXX>");
return;
}

if (pid > PID_MAX_DEFAULT) {
strcpy(comm, "<...>");
return;
Expand Down

0 comments on commit 935cc93

Please sign in to comment.