Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 71015
b: refs/heads/master
c: 38e760a
h: refs/heads/master
i:
  71013: 99d00fa
  71011: d545b4e
  71007: c49aa07
v: v3
  • Loading branch information
Joe Korty authored and Thomas Gleixner committed Oct 17, 2007
1 parent f9c5915 commit e351aab
Show file tree
Hide file tree
Showing 15 changed files with 111 additions and 6 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: 9aa8d7195acb18fc436847f6c66a97f8359ad54d
refs/heads/master: 38e760a1335ffaca5a08624a9aed6fe2055c2c98
30 changes: 29 additions & 1 deletion trunk/Documentation/filesystems/proc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,35 @@ connects the CPUs in a SMP system. This means that an error has been detected,
the IO-APIC automatically retry the transmission, so it should not be a big
problem, but you should read the SMP-FAQ.

In this context it could be interesting to note the new irq directory in 2.4.
In 2.6.2* /proc/interrupts was expanded again. This time the goal was for
/proc/interrupts to display every IRQ vector in use by the system, not
just those considered 'most important'. The new vectors are:

THR -- interrupt raised when a machine check threshold counter
(typically counting ECC corrected errors of memory or cache) exceeds
a configurable threshold. Only available on some systems.

TRM -- a thermal event interrupt occurs when a temperature threshold
has been exceeded for the CPU. This interrupt may also be generated
when the temperature drops back to normal.

SPU -- a spurious interrupt is some interrupt that was raised then lowered
by some IO device before it could be fully processed by the APIC. Hence
the APIC sees the interrupt but does not know what device it came from.
For this case the APIC will generate the interrupt with a IRQ vector
of 0xff. This might also be generated by chipset bugs.

RES, CAL, TLB -- rescheduling, call and TLB flush interrupts are
sent from one CPU to another per the needs of the OS. Typically,
their statistics are used by kernel developers and interested users to
determine the occurance of interrupt of the given type.

The above IRQ vectors are displayed only when relevent. For example,
the threshold vector does not exist on x86_64 platforms. Others are
suppressed when the system is a uniprocessor. As of this writing, only
i386 and x86_64 platforms support the new IRQ vector displays.

Of some interest is the introduction of the /proc/irq directory to 2.4.
It could be used to set IRQ to CPU affinity, this means that you can "hook" an
IRQ to only one CPU, or to exclude a CPU of handling IRQs. The contents of the
irq subdir is one subdir for each IRQ, and one file; prof_cpu_mask
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/kernel/apic_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -1277,6 +1277,7 @@ void smp_spurious_interrupt(struct pt_regs *regs)
/* see sw-dev-man vol 3, chapter 7.4.13.5 */
printk(KERN_INFO "spurious APIC interrupt on CPU#%d, "
"should never happen.\n", smp_processor_id());
__get_cpu_var(irq_stat).irq_spurious_count++;
irq_exit();
}

Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/kernel/apic_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,7 @@ asmlinkage void smp_spurious_interrupt(void)
if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
ack_APIC_irq();

add_pda(irq_spurious_count, 1);
irq_exit();
}

Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/kernel/cpu/mcheck/p4.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fastcall void smp_thermal_interrupt(struct pt_regs *regs)
{
irq_enter();
vendor_thermal_interrupt(regs);
__get_cpu_var(irq_stat).irq_thermal_count++;
irq_exit();
}

Expand Down
31 changes: 29 additions & 2 deletions trunk/arch/x86/kernel/irq_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,14 +280,41 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, "NMI: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", nmi_count(j));
seq_putc(p, '\n');
seq_printf(p, " Non-maskable interrupts\n");
#ifdef CONFIG_X86_LOCAL_APIC
seq_printf(p, "LOC: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ",
per_cpu(irq_stat,j).apic_timer_irqs);
seq_putc(p, '\n');
seq_printf(p, " Local timer interrupts\n");
#endif
#ifdef CONFIG_SMP
seq_printf(p, "RES: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ",
per_cpu(irq_stat,j).irq_resched_count);
seq_printf(p, " Rescheduling interrupts\n");
seq_printf(p, "CAL: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ",
per_cpu(irq_stat,j).irq_call_count);
seq_printf(p, " function call interrupts\n");
seq_printf(p, "TLB: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ",
per_cpu(irq_stat,j).irq_tlb_count);
seq_printf(p, " TLB shootdowns\n");
#endif
seq_printf(p, "TRM: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ",
per_cpu(irq_stat,j).irq_thermal_count);
seq_printf(p, " Thermal event interrupts\n");
seq_printf(p, "SPU: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ",
per_cpu(irq_stat,j).irq_spurious_count);
seq_printf(p, " Spurious interrupts\n");
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));
Expand Down
30 changes: 28 additions & 2 deletions trunk/arch/x86/kernel/irq_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,37 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, "NMI: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
seq_putc(p, '\n');
seq_printf(p, " Non-maskable interrupts\n");
seq_printf(p, "LOC: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs);
seq_putc(p, '\n');
seq_printf(p, " Local timer interrupts\n");
#ifdef CONFIG_SMP
seq_printf(p, "RES: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->irq_resched_count);
seq_printf(p, " Rescheduling interrupts\n");
seq_printf(p, "CAL: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->irq_call_count);
seq_printf(p, " function call interrupts\n");
seq_printf(p, "TLB: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->irq_tlb_count);
seq_printf(p, " TLB shootdowns\n");
#endif
seq_printf(p, "TRM: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->irq_thermal_count);
seq_printf(p, " Thermal event interrupts\n");
seq_printf(p, "THR: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->irq_threshold_count);
seq_printf(p, " Threshold APIC interrupts\n");
seq_printf(p, "SPU: ");
for_each_online_cpu(j)
seq_printf(p, "%10u ", cpu_pda(j)->irq_spurious_count);
seq_printf(p, " Spurious interrupts\n");
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
}
return 0;
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/kernel/mce_amd_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ asmlinkage void mce_threshold_interrupt(void)
}
}
out:
add_pda(irq_threshold_count, 1);
irq_exit();
}

Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/kernel/mce_intel_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ asmlinkage void smp_thermal_interrupt(void)
if (therm_throt_process(msr_val & 1))
mce_log_therm_throt_event(smp_processor_id(), msr_val);

add_pda(irq_thermal_count, 1);
irq_exit();
}

Expand Down
3 changes: 3 additions & 0 deletions trunk/arch/x86/kernel/smp_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ fastcall void smp_invalidate_interrupt(struct pt_regs *regs)
smp_mb__after_clear_bit();
out:
put_cpu_no_resched();
__get_cpu_var(irq_stat).irq_tlb_count++;
}

void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
Expand Down Expand Up @@ -640,6 +641,7 @@ static void native_smp_send_stop(void)
fastcall void smp_reschedule_interrupt(struct pt_regs *regs)
{
ack_APIC_irq();
__get_cpu_var(irq_stat).irq_resched_count++;
}

fastcall void smp_call_function_interrupt(struct pt_regs *regs)
Expand All @@ -660,6 +662,7 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
*/
irq_enter();
(*func)(info);
__get_cpu_var(irq_stat).irq_call_count++;
irq_exit();

if (wait) {
Expand Down
3 changes: 3 additions & 0 deletions trunk/arch/x86/kernel/smp_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
out:
ack_APIC_irq();
cpu_clear(cpu, f->flush_cpumask);
add_pda(irq_tlb_count, 1);
}

static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
Expand Down Expand Up @@ -493,6 +494,7 @@ void smp_send_stop(void)
asmlinkage void smp_reschedule_interrupt(void)
{
ack_APIC_irq();
add_pda(irq_resched_count, 1);
}

asmlinkage void smp_call_function_interrupt(void)
Expand All @@ -514,6 +516,7 @@ asmlinkage void smp_call_function_interrupt(void)
exit_idle();
irq_enter();
(*func)(info);
add_pda(irq_call_count, 1);
irq_exit();
if (wait) {
mb();
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/mach-voyager/voyager_smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,7 @@ smp_call_function_interrupt(void)
*/
irq_enter();
(*func)(info);
__get_cpu_var(irq_stat).irq_call_count++;
irq_exit();
if (wait) {
mb();
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/x86/xen/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id)
*/
irq_enter();
(*func)(info);
__get_cpu_var(irq_stat).irq_call_count++;
irq_exit();

if (wait) {
Expand Down
5 changes: 5 additions & 0 deletions trunk/include/asm-x86/hardirq_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ typedef struct {
unsigned int __nmi_count; /* arch dependent */
unsigned int apic_timer_irqs; /* arch dependent */
unsigned int irq0_irqs;
unsigned int irq_resched_count;
unsigned int irq_call_count;
unsigned int irq_tlb_count;
unsigned int irq_thermal_count;
unsigned int irq_spurious_count;
} ____cacheline_aligned irq_cpustat_t;

DECLARE_PER_CPU(irq_cpustat_t, irq_stat);
Expand Down
6 changes: 6 additions & 0 deletions trunk/include/asm-x86/pda.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ struct x8664_pda {
struct mm_struct *active_mm;
unsigned apic_timer_irqs;
unsigned irq0_irqs;
unsigned irq_resched_count;
unsigned irq_call_count;
unsigned irq_tlb_count;
unsigned irq_thermal_count;
unsigned irq_threshold_count;
unsigned irq_spurious_count;
} ____cacheline_aligned_in_smp;

extern struct x8664_pda *_cpu_pda[];
Expand Down

0 comments on commit e351aab

Please sign in to comment.