[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 5 of 5] xenalyze: Handle new IRQ tracing
Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx> diff -r 21e56bad8f2c -r 4833fe142a4f analyze.h --- a/analyze.h Fri Oct 07 11:35:45 2011 +0100 +++ b/analyze.h Fri Oct 07 11:36:27 2011 +0100 @@ -7,10 +7,23 @@ #define TRC_MEM_MAIN 4 #define TRC_PV_MAIN 5 #define TRC_SHADOW_MAIN 6 -#define TRC_PM_MAIN 7 +#define TRC_HW_MAIN 7 #define TRC_LOST_RECORDS_END (TRC_GEN + 50) +#define NR_CPUS 128 +#if __x86_64__ +# define BITS_PER_LONG 64 +#else +# define BITS_PER_LONG 32 +#endif + +#define BITS_TO_LONGS(bits) \ + (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) +#define DECLARE_BITMAP(name,bits) \ + unsigned long name[BITS_TO_LONGS(bits)] +typedef struct cpumask{ DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t; + enum { TRCE_SFLAG_SET_AD, TRCE_SFLAG_SET_A, diff -r 21e56bad8f2c -r 4833fe142a4f trace.h --- a/trace.h Fri Oct 07 11:35:45 2011 +0100 +++ b/trace.h Fri Oct 07 11:36:27 2011 +0100 @@ -38,7 +38,7 @@ #define TRC_MEM 0x0010f000 /* Xen memory trace */ #define TRC_PV 0x0020f000 /* Xen PV traces */ #define TRC_SHADOW 0x0040f000 /* Xen shadow tracing */ -#define TRC_PM 0x0080f000 /* Xen power management trace */ +#define TRC_HW 0x0080f000 /* Xen hardware-related traces */ #define TRC_GUEST 0x0800f000 /* Guest-generated traces */ #define TRC_ALL 0x0ffff000 #define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff) @@ -57,11 +57,13 @@ #define TRC_SCHED_CLASS 0x00022000 /* Scheduler-specific */ #define TRC_SCHED_VERBOSE 0x00028000 /* More inclusive scheduling */ +#define TRC_HW_PM 0x00801000 /* Power management traces */ +#define TRC_HW_IRQ 0x00802000 /* Traces relating to the handling of IRQs */ + /* Trace events per class */ #define TRC_LOST_RECORDS (TRC_GEN + 1) #define TRC_TRACE_WRAP_BUFFER (TRC_GEN + 2) #define TRC_TRACE_CPU_CHANGE (TRC_GEN + 3) -#define TRC_TRACE_IRQ (TRC_GEN + 4) #define TRC_SCHED_RUNSTATE_CHANGE (TRC_SCHED_MIN + 1) #define TRC_SCHED_CONTINUE_RUNNING (TRC_SCHED_MIN + 2) @@ -164,14 +166,25 @@ #define TRC_HVM_IOPORT_WRITE (TRC_HVM_HANDLER + 0x216) #define TRC_HVM_IOMEM_WRITE (TRC_HVM_HANDLER + 0x217) -/* trace subclasses for power management */ -#define TRC_PM_FREQ 0x00801000 /* xen cpu freq events */ -#define TRC_PM_IDLE 0x00802000 /* xen cpu idle events */ +/* trace events for per class */ +#define TRC_PM_FREQ_CHANGE (TRC_HW_PM + 0x01) +#define TRC_PM_IDLE_ENTRY (TRC_HW_PM + 0x02) +#define TRC_PM_IDLE_EXIT (TRC_HW_PM + 0x03) -/* trace events for per class */ -#define TRC_PM_FREQ_CHANGE (TRC_PM_FREQ + 0x01) -#define TRC_PM_IDLE_ENTRY (TRC_PM_IDLE + 0x01) -#define TRC_PM_IDLE_EXIT (TRC_PM_IDLE + 0x02) +#define TRC_HW_IRQ_MOVE_CLEANUP_DELAY (TRC_HW_IRQ + 0x1) +#define TRC_HW_IRQ_MOVE_CLEANUP (TRC_HW_IRQ + 0x2) +#define TRC_HW_IRQ_BIND_VECTOR (TRC_HW_IRQ + 0x3) +#define TRC_HW_IRQ_CLEAR_VECTOR (TRC_HW_IRQ + 0x4) +#define TRC_HW_IRQ_MOVE_FINISH (TRC_HW_IRQ + 0x5) +#define TRC_HW_IRQ_ASSIGN_VECTOR (TRC_HW_IRQ + 0x6) +#define TRC_HW_IRQ_UNMAPPED_VECTOR (TRC_HW_IRQ + 0x7) +#define TRC_HW_IRQ_HANDLED (TRC_HW_IRQ + 0x8) +#define TRC_HW_IRQ_MSI_WRITE (TRC_HW_IRQ + 0x9) +#define TRC_HW_IRQ_MAP_PIRQ_MSI (TRC_HW_IRQ + 0xa) +#define TRC_HW_IRQ_MAP_PIRQ_GSI (TRC_HW_IRQ + 0xb) +#define TRC_HW_IRQ_MSI_SET_AFFINITY (TRC_HW_IRQ + 0x10) +#define TRC_HW_IRQ_SET_DESC_AFFINITY (TRC_HW_IRQ + 0x11) +#define TRC_HW_IRQ_IOMMU_AMD_IRE (TRC_HW_IRQ + 0x12) /* This structure represents a single trace buffer record. */ struct t_rec { diff -r 21e56bad8f2c -r 4833fe142a4f xenalyze.c --- a/xenalyze.c Fri Oct 07 11:35:45 2011 +0100 +++ b/xenalyze.c Fri Oct 07 11:36:27 2011 +0100 @@ -144,6 +144,7 @@ struct { scatterplot_pcpu:1, scatterplot_extint_cycles:1, scatterplot_rdtsc:1, + scatterplot_irq:1, histogram_interrupt_eip:1, interval_mode:1, dump_cooked:1, @@ -218,6 +219,7 @@ struct { .scatterplot_pcpu=0, .scatterplot_extint_cycles=0, .scatterplot_rdtsc=0, + .scatterplot_irq=0, .histogram_interrupt_eip=0, .dump_cooked = 0, .dump_all = 0, @@ -7564,9 +7566,6 @@ void mem_process(struct pcpu_info *p) { } /* ---- PM ---- */ -#define TRC_PM_FREQ_CHANGE (TRC_PM_FREQ + 0x01) -#define TRC_PM_IDLE_ENTRY (TRC_PM_IDLE + 0x01) -#define TRC_PM_IDLE_EXIT (TRC_PM_IDLE + 0x02) #define CSTATE_MAX 5 #define CSTATE_INVALID ((CSTATE_MAX)+1) void pm_process(struct pcpu_info *p) { @@ -7609,7 +7608,383 @@ void pm_process(struct pcpu_info *p) { } - +/* + * IRQ related stuff + */ + +#define MAX_VECTOR 256 +int global_vector_used[256] = {0}; +struct pci_dev { + uint8_t bus; + uint8_t devfn; + int vector_used[MAX_VECTOR]; + struct pci_dev *next; +} *pdev_list; + +#define MAX_IRQ 512 +struct irq_desc { + enum { + IRQ_NONE, + IRQ_MSI, + IRQ_GSI + } type; + struct pci_dev *dev; +} irq_table[MAX_IRQ]; + +struct pci_dev * pdev_find(uint8_t bus, uint8_t devfn) +{ + struct pci_dev *d, *n, **q; + + /* Look for domain, keeping track of the last pointer so we can add + a domain if we need to. */ + for ( d = pdev_list, q=&pdev_list ; + d && ( (d->bus < bus) + || (d->bus == bus && d->devfn < devfn) ) ; + q = &d->next, d=d->next ) ; + + if(d && d->bus == bus && d->devfn == devfn) + return d; + + /* Make a new domain */ + fprintf(warn, "Creating pdev %02x:%02x.%x\n", bus, devfn>>4, devfn&3); + + if((n=malloc(sizeof(*n)))==NULL) + { + fprintf(stderr, "%s: malloc %zd failed!\n", __func__, sizeof(*n)); + error(ERR_SYSTEM, NULL); + } + + bzero(n, sizeof(*n)); + + n->bus=bus; + n->devfn=devfn; + + /* Insert it into the list */ + n->next = d; + *q = n; + + return n; +} + +void irq_process(struct pcpu_info *p) { + struct record_info *ri = &p->ri; + + switch ( ri->event ) + { + case TRC_HW_IRQ_BIND_VECTOR: + { + struct { + int irq, vec; + unsigned mask[4]; + } *r = (typeof(r))ri->d; + if ( opt.dump_all ) + { + printf(" %s irq_bind_vector irq %x vec %x mask %04x %04x %04x %04x\n", + ri->dump_header, + r->irq, r->vec, + r->mask[3], + r->mask[2], + r->mask[1], + r->mask[0]); + } + break; + } + case TRC_HW_IRQ_HANDLED: + { + struct { + int irq, start_tsc, end_tsc; + } *r = (typeof(r))ri->d; + int arctime; + + arctime = r->end_tsc - r->start_tsc; + if ( opt.dump_all ) + { + printf(" %s irq_handled irq %x %d (%d,%d)\n", + ri->dump_header, + r->irq, arctime, r->start_tsc, r->end_tsc); + } + if ( opt.scatterplot_irq ) + { + struct time_struct t; + + abs_cycles_to_time(ri->tsc, &t); + + printf("i%x %u.%09u %d\n", + (unsigned)r->irq, + t.s, t.ns, + p->pid); + } + break; + } + case TRC_HW_IRQ_ASSIGN_VECTOR: + { + struct { + int irq, vec; + unsigned mask[4]; + } *r = (typeof(r))ri->d; + if ( opt.dump_all ) + { + printf(" %s irq_assign_vector irq %x vec %x mask %04x %04x %04x %04x\n", + ri->dump_header, + r->irq, r->vec, + r->mask[3], + r->mask[2], + r->mask[1], + r->mask[0]); + } + if ( r->irq < MAX_IRQ + && r->vec < MAX_VECTOR ) + { + if ( irq_table[r->irq].type == IRQ_MSI ) + { + if(global_vector_used[r->vec]) + fprintf(warn, " Vector collision on global table!\n"); + global_vector_used[r->vec]=1; + } + if( irq_table[r->irq].dev ) + { + struct pci_dev * pdev=irq_table[r->irq].dev; + + if(pdev->vector_used[r->vec]) + fprintf(warn, " Vector collision on %02x.%02x!\n", + pdev->bus, pdev->devfn); + pdev->vector_used[r->vec]=1; + } + } + break; + } + case TRC_HW_IRQ_MOVE_CLEANUP_DELAY: + { + struct { + int irq, vec, cpu; + } *r = (typeof(r))ri->d; + + if ( opt.dump_all ) + { + printf(" %s irq_move_cleanup_delay irq %x vec %x cpu %d\n", + ri->dump_header, + r->irq, r->vec, r->cpu); + } + break; + } + case TRC_HW_IRQ_MOVE_CLEANUP: + { + struct { + int irq; + int vec; + int cpu; + } *r = (typeof(r))ri->d; + + if ( opt.dump_all ) + { + printf(" %s irq_move_cleanup irq %x vec %x cpu %d\n", + ri->dump_header, + r->irq, r->vec, r->cpu); + } + if ( r->irq < MAX_IRQ + && r->vec < MAX_VECTOR ) + { + if ( irq_table[r->irq].type == IRQ_MSI ) + { + if(!global_vector_used[r->vec]) + fprintf(warn," Strange, cleanup on non-used vector\n"); + global_vector_used[r->vec]=0; + } + if ( irq_table[r->irq].dev ) + { + struct pci_dev * pdev=irq_table[r->irq].dev; + + if(!pdev->vector_used[r->vec]) + fprintf(warn," Strange, cleanup on non-used vector\n"); + pdev->vector_used[r->vec]=0; + } + } + break; + } + case TRC_HW_IRQ_UNMAPPED_VECTOR: + { + struct { + int vec; + } *r = (typeof(r))ri->d; + + if ( opt.dump_all ) + { + printf(" %s irq_unmapped_vector vec %x\n", + ri->dump_header, + r->vec); + } + break; + } + case TRC_HW_IRQ_MSI_WRITE: + { + struct { + unsigned address_lo, address_hi; + unsigned data; + unsigned irq:16, pos:16; + uint8_t func, slot, bus, type; + unsigned mask_base; + } *r = (typeof(r))ri->d; + + if ( opt.dump_all ) + { + printf(" %s irq_msi_write irq %x t %x base %x addr %x %x data %x pci %02x:%02x.%x %x\n", + ri->dump_header, + r->irq, + r->type, + r->mask_base, + r->address_hi, r->address_lo, + r->data, + r->bus, r->slot, r->func, r->pos); + } + break; + } + case TRC_HW_IRQ_IOMMU_AMD_IRE: + { + struct { + uint16_t bdf, id; + int offset; + uint8_t dest_mode, dev_mode, vector, dest; + } *r = (typeof(r))ri->d; + + if ( opt.dump_all ) + { + printf(" %s irq_iommu_ire bdf %x id %x offset %x dest_mode %x dev_mode %x vec %x dest %x\n", + ri->dump_header, + r->bdf, r->id, + r->offset, + r->dest_mode, r->dev_mode, + r->vector, r->dest); + } + break; + } + case TRC_HW_IRQ_MAP_PIRQ_MSI: + { + struct { + unsigned domain:16, + pirq:16, + irq:16, + bus:16, + devfn:16, + entry_nr:16; + } *r = (typeof(r))ri->d; + + if ( r->irq < MAX_IRQ ) + { + struct irq_desc *irq=irq_table+r->irq; + + if ( irq->dev ) + { + fprintf(warn, "Strange, irq %d already has dev %02x:%x.%x!\n", + r->irq, irq->dev->bus, + irq->dev->devfn>>4, + irq->dev->devfn&3); + } + else + { + struct pci_dev *pdev = pdev_find(r->bus, r->devfn); + + irq->dev=pdev; + irq->type=IRQ_MSI; + } + } + + if ( opt.dump_all ) + { + printf(" %s irq_map_pirq_msi d%d pirq %x(%d) irq %x bus %x devfn %x entry %x\n", + ri->dump_header, + r->domain, + r->pirq, + r->pirq, + r->irq, + r->bus, + r->devfn, + r->entry_nr); + } + break; + } + case TRC_HW_IRQ_MAP_PIRQ_GSI: + { + struct { + unsigned domain, pirq, irq; + } *r = (typeof(r))ri->d; + + if ( opt.dump_all ) + { + printf(" %s irq_map_pirq_gsi d%d pirq %x(%d) irq %x\n", + ri->dump_header, + r->domain, + r->pirq, + r->pirq, + r->irq); + } + break; + } + case TRC_HW_IRQ_MSI_SET_AFFINITY: + { + struct { + unsigned irq, apic_id, vector; + } *r = (typeof(r))ri->d; + + if ( opt.dump_all ) + { + printf(" %s irq_msi_set_affinity irq %x apicid %x vec %x\n", + ri->dump_header, + r->irq, + r->apic_id, + r->vector); + } + break; + } + case TRC_HW_IRQ_SET_DESC_AFFINITY: + { + struct { + unsigned line:16, irq:16; + char fname[24]; /* Extra 7 words; 6 words * 4 = 24 */ + } *r = (typeof(r))ri->d; + char fname[25]; + int i; + + for(i=0; i<24; i++) + fname[i]=r->fname[i]; + fname[i]=0; + + if ( opt.dump_all ) + { + printf(" %s irq_set_desc_affinity irq %x %s:%d\n", + ri->dump_header, + r->irq, + fname, + r->line); + } + break; + } + case TRC_HW_IRQ_CLEAR_VECTOR: + case TRC_HW_IRQ_MOVE_FINISH : + default: + if(opt.dump_all || opt.dump_cooked) { + dump_generic(stdout, ri); + } + break; + } +} + +#define TRC_HW_SUB_PM 1 +#define TRC_HW_SUB_IRQ 2 +void hw_process(struct pcpu_info *p) +{ + struct record_info *ri = &p->ri; + + switch(ri->evt.sub) + { + case TRC_HW_SUB_PM: + pm_process(p); + break; + case TRC_HW_SUB_IRQ: + irq_process(p); + break; + } + +} /* ---- Base ----- */ void dump_generic(FILE * f, struct record_info *ri) { @@ -8404,8 +8779,8 @@ void process_record(struct pcpu_info *p) case TRC_MEM_MAIN: mem_process(p); break; - case TRC_PM_MAIN: - pm_process(p); + case TRC_HW_MAIN: + hw_process(p); break; case TRC_DOM0OP_MAIN: default: @@ -8868,6 +9243,7 @@ enum { OPT_SCATTERPLOT_PCPU, OPT_SCATTERPLOT_EXTINT_CYCLES, OPT_SCATTERPLOT_RDTSC, + OPT_SCATTERPLOT_IRQ, OPT_HISTOGRAM_INTERRUPT_EIP, /* Interval options */ OPT_INTERVAL_CR3_SCHEDULE_TIME, @@ -9119,6 +9495,10 @@ error_t cmd_parser(int key, char *arg, s G.output_defined = 1; opt.scatterplot_rdtsc=1; break; + case OPT_SCATTERPLOT_IRQ: + G.output_defined = 1; + opt.scatterplot_irq=1; + break; case OPT_SCATTERPLOT_IO: { char * inval; @@ -9521,6 +9901,11 @@ const struct argp_option cmd_opts[] = { .group = OPT_GROUP_EXTRA, .doc = "Output scatterplot of rdtsc values.", }, + { .name = "scatterplot-irq", + .key = OPT_SCATTERPLOT_IRQ, + .group = OPT_GROUP_EXTRA, + .doc = "Output scatterplot of irqs on pcpus.", }, + { .name = "histogram-interrupt-eip", .key = OPT_HISTOGRAM_INTERRUPT_EIP, .arg = "vector[,increment]", _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |