Re: [PATCH] create /proc/all-interrupts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2007-07-26 at 11:56 -0700, H. Peter Anvin wrote: 
> Joe Korty wrote:
> > Create /proc/all-interrupts for some architectures.
> > 
> > Create a version of /proc/interrupts that displays _every_
> > IRQ vector, not just those that someone thought might be
> > interesting, and add an entry in the commentary column
> > for those vectors which lacked such a comment.
> > 
> > Rationale: /proc/interrupts is not truly useful unless it
> > displays every IRQ vector, not just those somebody thought
> > would be interesting.  For example, since /proc/interrupts
> > does not display the rescheduling interrupt, the occurance
> > of rescheduling interrupt floods ends up affecting
> > latencies, yet without an entry in /proc/interrupts, it
> > is difficult to discern why latencies are being affected.
> > 
> > Rather than modify /proc/interrupts, this patch creates
> > a new version of /proc/interrupts, on the off-chance
> > that adding new lines to /proc/interrupts, and appending
> > new fields to the end of old lines, might break some
> > longstanding script.  However, these kinds of changes
> > traditionally do not affect scripts, so it might be
> > reasonable to fold /proc/all-interrupts back into
> > /proc/interrupts.
> 
> I think that would be the right thing to do.  We have added things to
> /proc/interrupts in the past.
> 
Hi Andrew,

Would it make sense to drop this patch into -mm for feedback?

Thanks,

Sven
--- Begin Message ---
Add missing IRQs to /proc/interrupts.

/proc/interrupts is not truly useful unless it displays
every IRQ vector, not just those somebody thought
would be interesting.  For example, since the default
/proc/interrupts setup did not display the rescheduling
interrupt, the occurance of rescheduling interrupt floods
ends up affecting latencies, yet without an entry in
/proc/interrupts, it is difficult to discern why latencies
are being affected.

Also does a silly little expansion of the 'ERR:' display
to be per cpu.  This makes its layout identical to all
the other display lines in /proc/interrupts.

Signed-off-by: Joe Korty <[email protected]>

Index: 2.6.22.1-rt8/arch/i386/kernel/apic.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/i386/kernel/apic.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/i386/kernel/apic.c	2007-07-25 16:07:43.000000000 -0400
@@ -1268,6 +1268,8 @@
 {
 	unsigned long v;
 
+	atomic_inc(&__get_cpu_var(irq_spur_counts));
+
 	irq_enter();
 	/*
 	 * Check if this really is a spurious interrupt and ACK it
@@ -1297,7 +1299,7 @@
 	apic_write(APIC_ESR, 0);
 	v1 = apic_read(APIC_ESR);
 	ack_APIC_irq();
-	atomic_inc(&irq_err_count);
+	atomic_inc(&__get_cpu_var(irq_err_counts));
 
 	/* Here is what the APIC error bits mean:
 	   0: Send CS error
Index: 2.6.22.1-rt8/arch/i386/kernel/cpu/mcheck/p4.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/i386/kernel/cpu/mcheck/p4.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/i386/kernel/cpu/mcheck/p4.c	2007-07-25 16:07:43.000000000 -0400
@@ -60,6 +60,7 @@
 fastcall void smp_thermal_interrupt(struct pt_regs *regs)
 {
 	irq_enter();
+	atomic_inc(&__get_cpu_var(irq_thermal_counts));
 	vendor_thermal_interrupt(regs);
 	irq_exit();
 }
Index: 2.6.22.1-rt8/arch/i386/kernel/i8259.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/i386/kernel/i8259.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/i386/kernel/i8259.c	2007-07-25 16:07:43.000000000 -0400
@@ -209,7 +209,7 @@
 			printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
 			spurious_irq_mask |= irqmask;
 		}
-		atomic_inc(&irq_err_count);
+		atomic_inc(&__get_cpu_var(irq_err_counts));
 		/*
 		 * Theoretically we do not have to handle this IRQ,
 		 * but in Linux this does not cause problems and is
Index: 2.6.22.1-rt8/arch/i386/kernel/io_apic.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/i386/kernel/io_apic.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/i386/kernel/io_apic.c	2007-07-25 16:07:43.000000000 -0400
@@ -51,7 +51,6 @@
 #include "io_ports.h"
 
 int (*ioapic_renumber_irq)(int ioapic, int irq);
-atomic_t irq_mis_count;
 
 /* Where if anywhere is the i8259 connect in external int mode */
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
@@ -2031,7 +2030,7 @@
 	ack_APIC_irq();
 
 	if (!(v & (1 << (i & 0x1f)))) {
-		atomic_inc(&irq_mis_count);
+		atomic_inc(&__get_cpu_var(irq_mis_counts));
 		spin_lock(&ioapic_lock);
 		/* mask = 1, trigger = 0 */
 		__modify_IO_APIC_irq(irq, 0x00010000, 0x00008000);
Index: 2.6.22.1-rt8/arch/i386/kernel/irq.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/i386/kernel/irq.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/i386/kernel/irq.c	2007-07-25 16:23:12.000000000 -0400
@@ -252,7 +252,13 @@
  * Interrupt statistics:
  */
 
-atomic_t irq_err_count;
+DEFINE_PER_CPU(atomic_t, irq_resched_counts);
+DEFINE_PER_CPU(atomic_t, irq_call_counts);
+DEFINE_PER_CPU(atomic_t, irq_spur_counts);
+DEFINE_PER_CPU(atomic_t, irq_tlb_counts);
+DEFINE_PER_CPU(atomic_t, irq_thermal_counts);
+DEFINE_PER_CPU(atomic_t, irq_err_counts);
+DEFINE_PER_CPU(atomic_t, irq_mis_counts);
 
 /*
  * /proc/interrupts printing:
@@ -305,9 +311,60 @@
 				per_cpu(irq_stat,j).apic_timer_irqs);
 		seq_putc(p, '\n');
 #endif
-		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
-#if defined(CONFIG_X86_IO_APIC)
-		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+#ifdef CONFIG_SMP
+#ifdef RESCHEDULE_VECTOR
+		seq_printf(p, "RES: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ",
+				atomic_read(&per_cpu(irq_resched_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#endif
+#ifdef CONFIG_SMP
+#ifdef CALL_FUNCTION_VECTOR
+		seq_printf(p, "CAL: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ",
+				atomic_read(&per_cpu(irq_call_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#endif
+#ifdef CONFIG_SMP
+#ifdef INVALIDATE_TLB_VECTOR
+		seq_printf(p, "TLB: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ",
+				atomic_read(&per_cpu(irq_tlb_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#endif
+#ifdef THERMAL_APIC_VECTOR
+		seq_printf(p, "TRM: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ",
+				atomic_read(&per_cpu(irq_thermal_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#ifdef SPURIOUS_APIC_VECTOR
+		seq_printf(p, "SPU: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ",
+				atomic_read(&per_cpu(irq_spur_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#ifdef ERROR_APIC_VECTOR
+		seq_printf(p, "ERR: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ",
+				atomic_read(&per_cpu(irq_err_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#if defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
+		seq_printf(p, "MIS: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ",
+				atomic_read(&per_cpu(irq_mis_counts, j)));
+		seq_putc(p, '\n');
 #endif
 	}
 	return 0;
Index: 2.6.22.1-rt8/arch/i386/kernel/smp.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/i386/kernel/smp.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/i386/kernel/smp.c	2007-07-25 16:07:43.000000000 -0400
@@ -315,6 +315,7 @@
 	unsigned long cpu;
 
 	cpu = get_cpu();
+	atomic_inc(&__get_cpu_var(irq_tlb_counts));
 
 	if (!cpu_isset(cpu, flush_cpumask))
 		goto out;
@@ -658,6 +659,7 @@
 {
 	trace_special(regs->eip, 0, 0);
 	ack_APIC_irq();
+	atomic_inc(&__get_cpu_var(irq_resched_counts));
 	set_tsk_need_resched(current);
 }
 
@@ -668,6 +670,7 @@
 	int wait = call_data->wait;
 
 	ack_APIC_irq();
+	atomic_inc(&__get_cpu_var(irq_call_counts));
 	/*
 	 * Notify initiating CPU that I've grabbed the data and am
 	 * about to execute the function
Index: 2.6.22.1-rt8/arch/x86_64/kernel/apic.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/x86_64/kernel/apic.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/x86_64/kernel/apic.c	2007-07-25 16:07:43.000000000 -0400
@@ -1099,6 +1099,9 @@
 asmlinkage void smp_spurious_interrupt(void)
 {
 	unsigned int v;
+
+	atomic_inc(&__get_cpu_var(irq_spur_counts));
+
 	exit_idle();
 	irq_enter();
 	/*
@@ -1127,7 +1130,7 @@
 	apic_write(APIC_ESR, 0);
 	v1 = apic_read(APIC_ESR);
 	ack_APIC_irq();
-	atomic_inc(&irq_err_count);
+	atomic_inc(&__get_cpu_var(irq_err_counts));
 
 	/* Here is what the APIC error bits mean:
 	   0: Send CS error
Index: 2.6.22.1-rt8/arch/x86_64/kernel/i8259.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/x86_64/kernel/i8259.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/x86_64/kernel/i8259.c	2007-07-25 16:07:43.000000000 -0400
@@ -273,7 +273,7 @@
 			printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
 			spurious_irq_mask |= irqmask;
 		}
-		atomic_inc(&irq_err_count);
+		atomic_inc(&__get_cpu_var(irq_err_counts));
 		/*
 		 * Theoretically we do not have to handle this IRQ,
 		 * but in Linux this does not cause problems and is
Index: 2.6.22.1-rt8/arch/x86_64/kernel/irq.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/x86_64/kernel/irq.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/x86_64/kernel/irq.c	2007-07-25 16:23:12.000000000 -0400
@@ -20,7 +20,18 @@
 #include <asm/idle.h>
 #include <asm/smp.h>
 
-atomic_t irq_err_count;
+DEFINE_PER_CPU(atomic_t, irq_resched_counts);
+DEFINE_PER_CPU(atomic_t, irq_call_counts);
+DEFINE_PER_CPU(atomic_t, irq_spur_counts);
+DEFINE_PER_CPU(atomic_t, irq_tlb_counts);
+DEFINE_PER_CPU(atomic_t, irq_threshold_counts);
+DEFINE_PER_CPU(atomic_t, irq_thermal_counts);
+DEFINE_PER_CPU(atomic_t, irq_err_counts);
+#ifdef CONFIG_X86_IO_APIC
+#ifdef APIC_MISMATCH_DEBUG
+DEFINE_PER_CPU(atomic_t, irq_mis_counts);
+#endif
+#endif
 
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 /*
@@ -93,7 +104,62 @@
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs);
 		seq_putc(p, '\n');
-		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+#ifdef CONFIG_SMP
+#ifdef RESCHEDULE_VECTOR
+		seq_printf(p, "RES: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", atomic_read(&per_cpu(irq_resched_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#endif
+#ifdef CONFIG_SMP
+#ifdef CALL_FUNCTION_VECTOR
+		seq_printf(p, "CAL: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", atomic_read(&per_cpu(irq_call_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#endif
+#ifdef CONFIG_SMP
+#ifdef INVALIDATE_TLB_VECTOR_START
+		seq_printf(p, "TLB: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", atomic_read(&per_cpu(irq_tlb_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#endif
+#ifdef THERMAL_APIC_VECTOR
+		seq_printf(p, "TRM: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", atomic_read(&per_cpu(irq_thermal_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#ifdef THRESHOLD_APIC_VECTOR
+		seq_printf(p, "THR: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", atomic_read(&per_cpu(irq_threshold_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#ifdef SPURIOUS_APIC_VECTOR
+		seq_printf(p, "SPU: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", atomic_read(&per_cpu(irq_spur_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#ifdef ERROR_APIC_VECTOR
+		seq_printf(p, "ERR: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", atomic_read(&per_cpu(irq_err_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#ifdef CONFIG_X86_IO_APIC
+#ifdef APIC_MISMATCH_DEBUG
+		seq_printf(p, "MIS: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", atomic_read(&per_cpu(irq_mis_counts, j)));
+		seq_putc(p, '\n');
+#endif
+#endif
 	}
 	return 0;
 }
Index: 2.6.22.1-rt8/arch/x86_64/kernel/mce_amd.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/x86_64/kernel/mce_amd.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/x86_64/kernel/mce_amd.c	2007-07-25 16:07:43.000000000 -0400
@@ -186,6 +186,8 @@
 	exit_idle();
 	irq_enter();
 
+	atomic_inc(&__get_cpu_var(irq_threshold_counts));
+
 	memset(&m, 0, sizeof(m));
 	rdtscll(m.tsc);
 	m.cpu = smp_processor_id();
Index: 2.6.22.1-rt8/arch/x86_64/kernel/mce_intel.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/x86_64/kernel/mce_intel.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/x86_64/kernel/mce_intel.c	2007-07-25 16:07:43.000000000 -0400
@@ -21,6 +21,7 @@
 
 	exit_idle();
 	irq_enter();
+	atomic_inc(&__get_cpu_var(irq_thermal_counts));
 
 	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
 	if (therm_throt_process(msr_val & 1))
Index: 2.6.22.1-rt8/include/asm-i386/apic.h
===================================================================
--- 2.6.22.1-rt8.orig/include/asm-i386/apic.h	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/include/asm-i386/apic.h	2007-07-25 16:07:43.000000000 -0400
@@ -7,6 +7,7 @@
 #include <asm/apicdef.h>
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/atomic.h>
 
 #define Dprintk(x...)
 
@@ -118,6 +119,9 @@
 
 extern void smp_send_nmi_allbutself(void);
 
+DECLARE_PER_CPU(atomic_t, irq_spur_counts);
+DECLARE_PER_CPU(atomic_t, irq_thermal_counts);
+
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
 
Index: 2.6.22.1-rt8/include/asm-i386/hw_irq.h
===================================================================
--- 2.6.22.1-rt8.orig/include/asm-i386/hw_irq.h	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/include/asm-i386/hw_irq.h	2007-07-25 16:07:43.000000000 -0400
@@ -13,6 +13,7 @@
  */
 
 #include <linux/profile.h>
+#include <linux/percpu.h>
 #include <asm/atomic.h>
 #include <asm/irq.h>
 #include <asm/sections.h>
@@ -58,8 +59,11 @@
 
 extern unsigned long io_apic_irqs;
 
-extern atomic_t irq_err_count;
-extern atomic_t irq_mis_count;
+DECLARE_PER_CPU(atomic_t, irq_resched_counts);
+DECLARE_PER_CPU(atomic_t, irq_call_counts);
+DECLARE_PER_CPU(atomic_t, irq_tlb_counts);
+DECLARE_PER_CPU(atomic_t, irq_err_counts);
+DECLARE_PER_CPU(atomic_t, irq_mis_counts);
 
 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
 
Index: 2.6.22.1-rt8/include/asm-x86_64/apic.h
===================================================================
--- 2.6.22.1-rt8.orig/include/asm-x86_64/apic.h	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/include/asm-x86_64/apic.h	2007-07-25 16:07:43.000000000 -0400
@@ -6,6 +6,7 @@
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
 #include <asm/system.h>
+#include <asm/atomic.h>
 
 #define Dprintk(x...)
 
@@ -101,4 +102,7 @@
 extern unsigned boot_cpu_id;
 extern int local_apic_timer_c2_ok;
 
+DECLARE_PER_CPU(atomic_t, irq_spur_counts);
+DECLARE_PER_CPU(atomic_t, irq_thermal_counts);
+
 #endif /* __ASM_APIC_H */
Index: 2.6.22.1-rt8/include/asm-x86_64/hw_irq.h
===================================================================
--- 2.6.22.1-rt8.orig/include/asm-x86_64/hw_irq.h	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/include/asm-x86_64/hw_irq.h	2007-07-25 16:07:43.000000000 -0400
@@ -123,8 +123,12 @@
 
 extern unsigned long io_apic_irqs;
 
-extern atomic_t irq_err_count;
-extern atomic_t irq_mis_count;
+DECLARE_PER_CPU(atomic_t, irq_resched_counts);
+DECLARE_PER_CPU(atomic_t, irq_call_counts);
+DECLARE_PER_CPU(atomic_t, irq_tlb_counts);
+DECLARE_PER_CPU(atomic_t, irq_threshold_counts);
+DECLARE_PER_CPU(atomic_t, irq_err_counts);
+DECLARE_PER_CPU(atomic_t, irq_mis_counts);
 
 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
 
Index: 2.6.22.1-rt8/arch/x86_64/kernel/smp.c
===================================================================
--- 2.6.22.1-rt8.orig/arch/x86_64/kernel/smp.c	2007-07-25 16:07:23.000000000 -0400
+++ 2.6.22.1-rt8/arch/x86_64/kernel/smp.c	2007-07-25 16:07:43.000000000 -0400
@@ -133,6 +133,8 @@
 	int sender;
 	union smp_flush_state *f;
 
+	atomic_inc(&__get_cpu_var(irq_tlb_counts));
+
 	cpu = smp_processor_id();
 	/*
 	 * orig_rax contains the negated interrupt vector.
@@ -508,6 +510,7 @@
 asmlinkage void smp_reschedule_interrupt(void)
 {
 	ack_APIC_irq();
+	atomic_inc(&__get_cpu_var(irq_resched_counts));
 }
 
 asmlinkage void smp_call_function_interrupt(void)
@@ -517,6 +520,7 @@
 	int wait = call_data->wait;
 
 	ack_APIC_irq();
+	atomic_inc(&__get_cpu_var(irq_call_counts));
 	/*
 	 * Notify initiating CPU that I've grabbed the data and am
 	 * about to execute the function

--- End Message ---

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux