lkml.org 
[lkml]   [2011]   [Jul]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v2 6/6] trace,x86: Add platform_irq_vector_{entry|exit} trace events
Date
Add tracepoints to trace platform specific IRQ vectors which do not have
equivalent generic kernel handlers. Along with the IRQ number traced,
there is a symbolic mapping to the equivalent name of the IRQ.

This patch only traces the x86 and x86_64 platform vectors but other
architectures can add the tracepoints in their equivalent files to make
use of this trace event.

This is a part of overall effort to trace all the interrupts happening
in a system. This shows how the interrupts are interacting with other
events and what time is spent in kernel space versus user space.

Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
---
arch/x86/include/asm/irq_vectors.h | 43 ++++++++++++++++++++++++
arch/x86/kernel/apic/apic.c | 4 ++
arch/x86/kernel/cpu/mcheck/therm_throt.c | 2 +
arch/x86/kernel/cpu/mcheck/threshold.c | 2 +
arch/x86/kernel/irq.c | 2 +
arch/x86/kernel/traps.c | 2 +
arch/x86/mm/tlb.c | 2 +
include/trace/events/irq.h | 52 ++++++++++++++++++++++++++++++
8 files changed, 109 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index f9a3209..ee99ce1 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -181,4 +181,47 @@ static inline int invalid_vm86_irq(int irq)
# define NR_IRQS NR_IRQS_LEGACY
#endif

+#define platform_irq_vector_mapping(x) { (x), #x }
+#define invalidate_tlb_vector_mapping(x) \
+ { (INVALIDATE_TLB_VECTOR_START+x), "INVALIDATE_TLB_VECTOR" }
+#define platform_irq_vector_name \
+ platform_irq_vector_mapping(SPURIOUS_APIC_VECTOR), \
+ platform_irq_vector_mapping(ERROR_APIC_VECTOR), \
+ platform_irq_vector_mapping(THERMAL_APIC_VECTOR), \
+ platform_irq_vector_mapping(THRESHOLD_APIC_VECTOR), \
+ platform_irq_vector_mapping(X86_PLATFORM_IPI_VECTOR), \
+ platform_irq_vector_mapping(NMI_VECTOR), \
+ invalidate_tlb_vector_mapping(0), \
+ invalidate_tlb_vector_mapping(1), \
+ invalidate_tlb_vector_mapping(2), \
+ invalidate_tlb_vector_mapping(3), \
+ invalidate_tlb_vector_mapping(4), \
+ invalidate_tlb_vector_mapping(5), \
+ invalidate_tlb_vector_mapping(6), \
+ invalidate_tlb_vector_mapping(7), \
+ invalidate_tlb_vector_mapping(8), \
+ invalidate_tlb_vector_mapping(9), \
+ invalidate_tlb_vector_mapping(10), \
+ invalidate_tlb_vector_mapping(11), \
+ invalidate_tlb_vector_mapping(12), \
+ invalidate_tlb_vector_mapping(13), \
+ invalidate_tlb_vector_mapping(14), \
+ invalidate_tlb_vector_mapping(15), \
+ invalidate_tlb_vector_mapping(16), \
+ invalidate_tlb_vector_mapping(17), \
+ invalidate_tlb_vector_mapping(18), \
+ invalidate_tlb_vector_mapping(19), \
+ invalidate_tlb_vector_mapping(20), \
+ invalidate_tlb_vector_mapping(21), \
+ invalidate_tlb_vector_mapping(22), \
+ invalidate_tlb_vector_mapping(23), \
+ invalidate_tlb_vector_mapping(24), \
+ invalidate_tlb_vector_mapping(25), \
+ invalidate_tlb_vector_mapping(26), \
+ invalidate_tlb_vector_mapping(27), \
+ invalidate_tlb_vector_mapping(28), \
+ invalidate_tlb_vector_mapping(29), \
+ invalidate_tlb_vector_mapping(30), \
+ invalidate_tlb_vector_mapping(31)
+
#endif /* _ASM_X86_IRQ_VECTORS_H */
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index b24be38..1e3db2d 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1793,6 +1793,7 @@ void smp_spurious_interrupt(struct pt_regs *regs)

exit_idle();
irq_enter();
+ trace_platform_irq_vector_entry(SPURIOUS_APIC_VECTOR);
/*
* Check if this really is a spurious interrupt and ACK it
* if it is a vectored one. Just in case...
@@ -1807,6 +1808,7 @@ void smp_spurious_interrupt(struct pt_regs *regs)
/* see sw-dev-man vol 3, chapter 7.4.13.5 */
pr_info("spurious APIC interrupt on CPU#%d, "
"should never happen.\n", smp_processor_id());
+ trace_platform_irq_vector_exit(SPURIOUS_APIC_VECTOR);
irq_exit();
}

@@ -1830,6 +1832,7 @@ void smp_error_interrupt(struct pt_regs *regs)

exit_idle();
irq_enter();
+ trace_platform_irq_vector_entry(ERROR_APIC_VECTOR);
/* First tickle the hardware, only then report what went on. -- REW */
v0 = apic_read(APIC_ESR);
apic_write(APIC_ESR, 0);
@@ -1850,6 +1853,7 @@ void smp_error_interrupt(struct pt_regs *regs)

apic_printk(APIC_DEBUG, KERN_CONT "\n");

+ trace_platform_irq_vector_exit(ERROR_APIC_VECTOR);
irq_exit();
}

diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 27c6251..4528f26 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -398,8 +398,10 @@ asmlinkage void smp_thermal_interrupt(struct pt_regs *regs)
{
exit_idle();
irq_enter();
+ trace_platform_irq_vector_entry(THERMAL_APIC_VECTOR);
inc_irq_stat(irq_thermal_count);
smp_thermal_vector();
+ trace_platform_irq_vector_exit(THERMAL_APIC_VECTOR);
irq_exit();
/* Ack only at the end to avoid potential reentry */
ack_APIC_irq();
diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c
index d746df2..0876815 100644
--- a/arch/x86/kernel/cpu/mcheck/threshold.c
+++ b/arch/x86/kernel/cpu/mcheck/threshold.c
@@ -21,8 +21,10 @@ asmlinkage void smp_threshold_interrupt(void)
{
exit_idle();
irq_enter();
+ trace_platform_irq_vector_entry(THRESHOLD_APIC_VECTOR);
inc_irq_stat(irq_threshold_count);
mce_threshold_vector();
+ trace_platform_irq_vector_exit(THRESHOLD_APIC_VECTOR);
irq_exit();
/* Ack only at the end to avoid potential reentry */
ack_APIC_irq();
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 6c0802e..0c730f4 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -211,12 +211,14 @@ void smp_x86_platform_ipi(struct pt_regs *regs)
exit_idle();

irq_enter();
+ trace_platform_irq_vector_entry(X86_PLATFORM_IPI_VECTOR);

inc_irq_stat(x86_platform_ipis);

if (x86_platform_ipi_callback)
x86_platform_ipi_callback();

+ trace_platform_irq_vector_exit(X86_PLATFORM_IPI_VECTOR);
irq_exit();

set_irq_regs(old_regs);
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 545eb3d..9f65f12 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -447,12 +447,14 @@ dotraplinkage notrace __kprobes void
do_nmi(struct pt_regs *regs, long error_code)
{
nmi_enter();
+ trace_platform_irq_vector_entry(NMI_VECTOR);

inc_irq_stat(__nmi_count);

if (!ignore_nmis)
default_do_nmi(regs);

+ trace_platform_irq_vector_exit(NMI_VECTOR);
nmi_exit();
}

diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index d6c0418..5c9e766 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -141,6 +141,7 @@ void smp_invalidate_interrupt(struct pt_regs *regs)
sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START;
f = &flush_state[sender];

+ trace_platform_irq_vector_entry(sender + INVALIDATE_TLB_VECTOR_START);
if (!cpumask_test_cpu(cpu, to_cpumask(f->flush_cpumask)))
goto out;
/*
@@ -167,6 +168,7 @@ out:
cpumask_clear_cpu(cpu, to_cpumask(f->flush_cpumask));
smp_mb__after_clear_bit();
inc_irq_stat(irq_tlb_count);
+ trace_platform_irq_vector_exit(sender + INVALIDATE_TLB_VECTOR_START);
}

static void flush_tlb_others_ipi(const struct cpumask *cpumask,
diff --git a/include/trace/events/irq.h b/include/trace/events/irq.h
index 5e4f731..7d2b057 100644
--- a/include/trace/events/irq.h
+++ b/include/trace/events/irq.h
@@ -457,6 +457,58 @@ DEFINE_EVENT(call_function_ipi, call_function_single_ipi_exit,
TP_ARGS(ignore)
);

+#include <asm/irq.h>
+
+#if !defined(platform_irq_vector_name)
+#define platform_irq_vector_name { NULL, NULL }
+#endif
+
+DECLARE_EVENT_CLASS(platform_irq_vector,
+
+ TP_PROTO(unsigned int vec_num),
+
+ TP_ARGS(vec_num),
+
+ TP_STRUCT__entry(
+ __field( unsigned int, vec_num )
+ ),
+
+ TP_fast_assign(
+ __entry->vec_num = vec_num;
+ ),
+
+ TP_printk("%u: %s", __entry->vec_num,
+ __print_symbolic(__entry->vec_num, platform_irq_vector_name))
+);
+
+/**
+ * platform_irq_vector_entry - called immediately after entering the
+ * platform vector interrupt handler
+ *
+ * When used in combination with the platform_irq_vector_exit tracepoint
+ * we can determine the platform interrupt vector handler runtime.
+ */
+DEFINE_EVENT(platform_irq_vector, platform_irq_vector_entry,
+
+ TP_PROTO(unsigned int vec_num),
+
+ TP_ARGS(vec_num)
+);
+
+/**
+ * platform_irq_vector_exit - called just before the platform vector
+ * interrupt handler returns
+ *
+ * When used in combination with the platform_irq_vector_entry tracepoint
+ * we can determine the platform interrupt vector handler runtime.
+ */
+DEFINE_EVENT(platform_irq_vector, platform_irq_vector_exit,
+
+ TP_PROTO(unsigned int vec_num),
+
+ TP_ARGS(vec_num)
+);
+
#endif /* _TRACE_IRQ_H */

/* This part must be outside protection */
--
1.7.3.1


\
 
 \ /
  Last update: 2011-07-27 21:01    [W:0.150 / U:27.460 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site