Add interrupt counters for IPIs. By default they are disabled, but they

can be enabled by enabling COUNT_IPIS in smptests.h.  When enabled, each
CPU provides an interrupt counter for nearly all of the IPIs it receives
(IPI_STOP currently doesn't have a counter) that can be examined using
vmstat -i, etc.

MFC after:	3 days
Requested by:	rwatson
This commit is contained in:
John Baldwin 2005-09-28 18:04:11 +00:00
parent ea688ef40b
commit 29442a30e2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=150697
3 changed files with 97 additions and 8 deletions

View file

@ -151,14 +151,20 @@ IDTVEC(invltlb)
movl $KDSEL, %eax /* Kernel data selector */
movl %eax, %ds
#ifdef COUNT_XINVLTLB_HITS
#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
pushl %fs
movl $KPSEL, %eax /* Private space selector */
movl %eax, %fs
movl PCPU(CPUID), %eax
popl %fs
#ifdef COUNT_XINVLTLB_HITS
incl xhits_gbl(,%eax,4)
#endif /* COUNT_XINVLTLB_HITS */
#endif
#ifdef COUNT_IPIS
movl ipi_invltlb_counts(,%eax,4),%eax
incl (%eax)
#endif
#endif
movl %cr3, %eax /* invalidate the TLB */
movl %eax, %cr3
@ -184,14 +190,20 @@ IDTVEC(invlpg)
movl $KDSEL, %eax /* Kernel data selector */
movl %eax, %ds
#ifdef COUNT_XINVLTLB_HITS
#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
pushl %fs
movl $KPSEL, %eax /* Private space selector */
movl %eax, %fs
movl PCPU(CPUID), %eax
popl %fs
#ifdef COUNT_XINVLTLB_HITS
incl xhits_pg(,%eax,4)
#endif /* COUNT_XINVLTLB_HITS */
#endif
#ifdef COUNT_IPIS
movl ipi_invlpg_counts(,%eax,4),%eax
incl (%eax)
#endif
#endif
movl smp_tlb_addr1, %eax
invlpg (%eax) /* invalidate single page */
@ -218,14 +230,20 @@ IDTVEC(invlrng)
movl $KDSEL, %eax /* Kernel data selector */
movl %eax, %ds
#ifdef COUNT_XINVLTLB_HITS
#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
pushl %fs
movl $KPSEL, %eax /* Private space selector */
movl %eax, %fs
movl PCPU(CPUID), %eax
popl %fs
#ifdef COUNT_XINVLTLB_HITS
incl xhits_rng(,%eax,4)
#endif /* COUNT_XINVLTLB_HITS */
#endif
#ifdef COUNT_IPIS
movl ipi_invlrng_counts(,%eax,4),%eax
incl (%eax)
#endif
#endif
movl smp_tlb_addr1, %edx
movl smp_tlb_addr2, %eax
@ -354,6 +372,11 @@ IDTVEC(rendezvous)
movl $KPSEL, %eax
movl %eax, %fs
#ifdef COUNT_IPIS
movl PCPU(CPUID), %eax
movl ipi_rendezvous_counts(,%eax,4), %eax
incl (%eax)
#endif
call smp_rendezvous_action
movl lapic, %eax
@ -374,6 +397,11 @@ IDTVEC(lazypmap)
movl $KPSEL, %eax
movl %eax, %fs
#ifdef COUNT_IPIS
movl PCPU(CPUID), %eax
movl ipi_lazypmap_counts(,%eax,4), %eax
incl (%eax)
#endif
call pmap_lazyfix_action
movl lapic, %eax

View file

@ -181,6 +181,19 @@ volatile int smp_tlb_wait;
volatile cpumask_t ipi_nmi_pending;
#endif
#ifdef COUNT_IPIS
/* Interrupt counts. */
#ifdef IPI_PREEMPTION
static u_long *ipi_preempt_counts[MAXCPU];
#endif
static u_long *ipi_ast_counts[MAXCPU];
u_long *ipi_invltlb_counts[MAXCPU];
u_long *ipi_invlrng_counts[MAXCPU];
u_long *ipi_invlpg_counts[MAXCPU];
u_long *ipi_rendezvous_counts[MAXCPU];
u_long *ipi_lazypmap_counts[MAXCPU];
#endif
/*
* Local data and functions.
*/
@ -1130,6 +1143,9 @@ ipi_bitmap_handler(struct clockframe frame)
#ifdef IPI_PREEMPTION
if (ipi_bitmap & IPI_PREEMPT) {
#ifdef COUNT_IPIS
*ipi_preempt_counts[cpu]++;
#endif
mtx_lock_spin(&sched_lock);
/* Don't preempt the idle thread */
if (curthread->td_priority < PRI_MIN_IDLE) {
@ -1143,7 +1159,12 @@ ipi_bitmap_handler(struct clockframe frame)
}
#endif
/* Nothing to do for AST */
if (ipi_bitmap & IPI_AST) {
#ifdef COUNT_IPIS
*ipi_ast_counts[cpu]++;
#endif
/* Nothing to do for AST */
}
}
/*
@ -1445,3 +1466,37 @@ mp_grab_cpu_hlt(void)
__asm __volatile("sti; hlt" : : : "memory");
return (retval);
}
#ifdef COUNT_IPIS
/*
* Setup interrupt counters for IPI handlers.
*/
static void
mp_ipi_intrcnt(void *dummy)
{
char buf[64];
int i;
for (i = 0; i < mp_maxid; i++) {
if (CPU_ABSENT(i))
continue;
snprintf(buf, sizeof(buf), "cpu%d: invltlb", i);
intrcnt_add(buf, &ipi_invltlb_counts[i]);
snprintf(buf, sizeof(buf), "cpu%d: invlrng", i);
intrcnt_add(buf, &ipi_invlrng_counts[i]);
snprintf(buf, sizeof(buf), "cpu%d: invlpg", i);
intrcnt_add(buf, &ipi_invlpg_counts[i]);
#ifdef IPI_PREEMPTION
snprintf(buf, sizeof(buf), "cpu%d: preempt", i);
intrcnt_add(buf, &ipi_preempt_counts[i]);
#endif
snprintf(buf, sizeof(buf), "cpu%d: ast", i);
intrcnt_add(buf, &ipi_ast_counts[i]);
snprintf(buf, sizeof(buf), "cpu%d: rendezvous", i);
intrcnt_add(buf, &ipi_rendezvous_counts[i]);
snprintf(buf, sizeof(buf), "cpu%d: lazypmap", i);
intrcnt_add(buf, &ipi_lazypmap_counts[i]);
}
}
SYSINIT(mp_ipi_intrcnt, SI_SUB_INTR, SI_ORDER_MIDDLE, mp_ipi_intrcnt, NULL)
#endif

View file

@ -40,11 +40,17 @@
#define CPUSTOP_ON_DDBBREAK
/*
* Misc. counters.
* TLB counters.
*
#define COUNT_XINVLTLB_HITS
*/
/*
* Per-CPU IPI interrupt counters.
*
#define COUNT_IPIS
*/
/*
* Address of POST hardware port.
* Defining this enables POSTCODE macros.