Commit a8de4bad authored by Philippe Gerum's avatar Philippe Gerum

ipipe: add latency tracer

The latency tracer is a variant of ftrace's 'function' tracer
providing detailed information about the current interrupt state at
each function entry (i.e. virtual interrupt flag and CPU interrupt
disable bit). This commit introduces the generic tracer code, which
builds upon the regular ftrace API.

The arch-specific code should provide for ipipe_read_tsc(), a helper
routine returning a 64bit monotonic time value for timestamping
purpose. HAVE_IPIPE_TRACER_SUPPORT should be selected by the
arch-specific code for enabling the tracer, which in turn makes
CONFIG_IPIPE_TRACE available from the Kconfig interface.
parent 216ce73c
......@@ -253,7 +253,9 @@ static inline int ipipe_chained_irq_p(struct irq_desc *desc)
static inline void ipipe_handle_demuxed_irq(unsigned int cascade_irq)
{
ipipe_trace_irq_entry(cascade_irq);
__ipipe_dispatch_irq(cascade_irq, IPIPE_IRQF_NOSYNC);
ipipe_trace_irq_exit(cascade_irq);
}
static inline void __ipipe_init_threadflags(struct thread_info *ti)
......@@ -297,6 +299,12 @@ int ipipe_test_ti_thread_flag(struct thread_info *ti, int flag)
#define ipipe_test_thread_flag(flag) \
ipipe_test_ti_thread_flag(current_thread_info(), flag)
#ifdef CONFIG_IPIPE_TRACE
void __ipipe_tracer_hrclock_initialized(void);
#else /* !CONFIG_IPIPE_TRACE */
#define __ipipe_tracer_hrclock_initialized() do { } while(0)
#endif /* !CONFIG_IPIPE_TRACE */
#else /* !CONFIG_IPIPE */
#define __ipipe_root_p 1
......
/* -*- linux-c -*-
* include/linux/ipipe_trace.h
*
* Copyright (C) 2005 Luotao Fu.
* 2005-2007 Jan Kiszka.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
* USA; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _LINUX_IPIPE_TRACE_H
#define _LINUX_IPIPE_TRACE_H
#ifdef CONFIG_IPIPE_TRACE
#include <linux/types.h>
struct pt_regs;
void ipipe_trace_begin(unsigned long v);
void ipipe_trace_end(unsigned long v);
void ipipe_trace_freeze(unsigned long v);
void ipipe_trace_special(unsigned char special_id, unsigned long v);
void ipipe_trace_pid(pid_t pid, short prio);
void ipipe_trace_event(unsigned char id, unsigned long delay_tsc);
int ipipe_trace_max_reset(void);
int ipipe_trace_frozen_reset(void);
void ipipe_trace_irqbegin(int irq, struct pt_regs *regs);
void ipipe_trace_irqend(int irq, struct pt_regs *regs);
#else /* !CONFIG_IPIPE_TRACE */
#define ipipe_trace_begin(v) do { (void)(v); } while(0)
#define ipipe_trace_end(v) do { (void)(v); } while(0)
#define ipipe_trace_freeze(v) do { (void)(v); } while(0)
#define ipipe_trace_special(id, v) do { (void)(id); (void)(v); } while(0)
#define ipipe_trace_pid(pid, prio) do { (void)(pid); (void)(prio); } while(0)
#define ipipe_trace_event(id, delay_tsc) do { (void)(id); (void)(delay_tsc); } while(0)
#define ipipe_trace_max_reset() ({ 0; })
#define ipipe_trace_frozen_reset() ({ 0; })
#define ipipe_trace_irqbegin(irq, regs) do { } while(0)
#define ipipe_trace_irqend(irq, regs) do { } while(0)
#endif /* !CONFIG_IPIPE_TRACE */
#ifdef CONFIG_IPIPE_TRACE_PANIC
void ipipe_trace_panic_freeze(void);
void ipipe_trace_panic_dump(void);
#else
static inline void ipipe_trace_panic_freeze(void) { }
static inline void ipipe_trace_panic_dump(void) { }
#endif
#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
#define ipipe_trace_irq_entry(irq) ipipe_trace_begin(irq)
#define ipipe_trace_irq_exit(irq) ipipe_trace_end(irq)
#define ipipe_trace_irqsoff() ipipe_trace_begin(0x80000000UL)
#define ipipe_trace_irqson() ipipe_trace_end(0x80000000UL)
#else
#define ipipe_trace_irq_entry(irq) do { (void)(irq);} while(0)
#define ipipe_trace_irq_exit(irq) do { (void)(irq);} while(0)
#define ipipe_trace_irqsoff() do { } while(0)
#define ipipe_trace_irqson() do { } while(0)
#endif
#endif /* !__LINUX_IPIPE_TRACE_H */
......@@ -21,3 +21,80 @@ config IPIPE_DEBUG_INTERNAL
When this feature is enabled, I-pipe will perform internal
consistency checks of its subsystems, e.g. on per-cpu variable
access.
config HAVE_IPIPE_TRACER_SUPPORT
bool
config IPIPE_TRACE
bool "Latency tracing"
depends on HAVE_IPIPE_TRACER_SUPPORT
depends on IPIPE_DEBUG
select CONFIG_FTRACE
select CONFIG_FUNCTION_TRACER
select KALLSYMS
select PROC_FS
---help---
Activate this option if you want to use per-function tracing of
the kernel. The tracer will collect data via instrumentation
features like the one below or with the help of explicite calls
of ipipe_trace_xxx(). See include/linux/ipipe_trace.h for the
in-kernel tracing API. The collected data and runtime control
is available via /proc/ipipe/trace/*.
if IPIPE_TRACE
config IPIPE_TRACE_ENABLE
bool "Enable tracing on boot"
default y
---help---
Disable this option if you want to arm the tracer after booting
manually ("echo 1 > /proc/ipipe/tracer/enable"). This can reduce
boot time on slow embedded devices due to the tracer overhead.
config IPIPE_TRACE_MCOUNT
bool "Instrument function entries"
default y
select FTRACE
select FUNCTION_TRACER
---help---
When enabled, records every kernel function entry in the tracer
log. While this slows down the system noticeably, it provides
the highest level of information about the flow of events.
However, it can be switch off in order to record only explicit
I-pipe trace points.
config IPIPE_TRACE_IRQSOFF
bool "Trace IRQs-off times"
default y
---help---
Activate this option if I-pipe shall trace the longest path
with hard-IRQs switched off.
config IPIPE_TRACE_SHIFT
int "Depth of trace log (14 => 16Kpoints, 15 => 32Kpoints)"
range 10 18
default 14
---help---
The number of trace points to hold tracing data for each
trace path, as a power of 2.
config IPIPE_TRACE_VMALLOC
bool "Use vmalloc'ed trace buffer"
default y if EMBEDDED
---help---
Instead of reserving static kernel data, the required buffer
is allocated via vmalloc during boot-up when this option is
enabled. This can help to start systems that are low on memory,
but it slightly degrades overall performance. Try this option
when a traced kernel hangs unexpectedly at boot time.
config IPIPE_TRACE_PANIC
bool "Enable panic back traces"
default y
---help---
Provides services to freeze and dump a back trace on panic
situations. This is used on IPIPE_DEBUG_CONTEXT exceptions
as well as ordinary kernel oopses. You can control the number
of printed back trace points via /proc/ipipe/trace.
endif
obj-$(CONFIG_IPIPE) += core.o timer.o
obj-$(CONFIG_IPIPE_TRACE) += tracer.o
......@@ -211,6 +211,8 @@ void __init __ipipe_init_proc(void)
proc_create("version", 0444, ipipe_proc_root,
&__ipipe_version_proc_ops);
add_domain_proc(ipipe_root_domain);
__ipipe_init_tracer();
}
#else
......@@ -1400,6 +1402,7 @@ void ipipe_root_only(void)
hard_smp_local_irq_restore(flags);
ipipe_prepare_panic();
ipipe_trace_panic_freeze();
if (this_domain != ipipe_root_domain)
pr_err("I-pipe: Detected illicit call from head domain '%s'\n"
......@@ -1411,6 +1414,7 @@ void ipipe_root_only(void)
" A critical section may have been "
"left unterminated.\n");
dump_stack();
ipipe_trace_panic_dump();
}
EXPORT_SYMBOL(ipipe_root_only);
......
This diff is collapsed.
......@@ -20,6 +20,7 @@
#include <linux/ftrace.h>
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/ipipe_trace.h>
#include <linux/kexec.h>
#include <linux/sched.h>
#include <linux/ipipe.h>
......@@ -469,6 +470,7 @@ void oops_enter(void)
{
tracing_off();
/* can't trust the integrity of the kernel anymore: */
ipipe_trace_panic_freeze();
ipipe_disable_context_check();
debug_locks_off();
do_oops_enter_exit();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment