]> xenbits.xensource.com Git - xenalyze.git/commitdiff
[global] Generalize ipi tracking
authorGeorge Dunlap <dunlapg@silas.(none)>
Mon, 3 Nov 2008 12:19:31 +0000 (12:19 +0000)
committerGeorge Dunlap <dunlapg@silas.(none)>
Mon, 3 Nov 2008 12:19:31 +0000 (12:19 +0000)
analyze.c

index 5eed6d2061ccaad2ca3302541ef3934d1bc47922..1d19e5105f3822a47b6ca0d30e872874c3b1c55a 100644 (file)
--- a/analyze.c
+++ b/analyze.c
@@ -1423,10 +1423,15 @@ typedef uint32_t cpu_mask_t;
 #define IDLE_DOMAIN 32767
 #define DEFAULT_DOMAIN 32768
 
+#define MAX_VLAPIC_LIST 8
 struct vlapic_struct {
-    int outstanding_ipis;
-    tsc_t first_ipi_tsc;
-    int ipi_virq_injected;
+    struct {
+        struct outstanding_ipi {
+            tsc_t first_tsc;
+            int vec, count;
+            int injected, valid;
+        } list[MAX_VLAPIC_LIST];
+    } outstanding;
 };
 
 struct vcpu_data {
@@ -3158,10 +3163,75 @@ char * hvm_vlapic_icr_dest_shorthand_name[4] = {
     "dest_field", "self", "all-inc", "all-exc"
 };
 
-void clear_vlapic(struct vlapic_struct *vla) {
-        vla->outstanding_ipis = 0;
-        vla->first_ipi_tsc = 0;
-        vla->ipi_virq_injected = 0;
+void hvm_vlapic_vmentry_cleanup(struct vcpu_data *v, tsc_t tsc)
+{
+    int i;
+    
+    struct vlapic_struct *vla = &v->vlapic;
+
+    for(i=0; i<MAX_VLAPIC_LIST; i++)
+    {
+        unsigned long long lat=0;
+        struct outstanding_ipi *o = vla->outstanding.list + i;
+
+        if(!(o->valid && o->injected))
+            continue;
+
+        if(tsc >= o->first_tsc)
+            lat = tsc - o->first_tsc;
+        else
+            fprintf(warn, "Strange, vec %d first_tsc %lld > ri->tsc %lld!\n",
+                    o->vec, o->first_tsc, tsc);
+
+        if(opt.dump_ipi_latency
+           || (opt.dump_all && o->count > 1)) {
+            struct time_struct t;
+            cycles_to_time(lat, &t);
+            printf(" [vla] d%dv%d vec %d ipis %d, latency %lld (%lu.%09lu s)\n",
+                   v->d->did, v->vid, o->vec, o->count, lat,
+                   t.s, t.ns);
+        }
+
+#if 0
+        /* FIXME: make general somehow */
+        if(opt.summary_info)
+        {
+            update_summary(&h->summary.ipi_latency, lat);
+            h->summary.ipi_count[vla->outstanding_ipis]++;
+        }
+#endif
+
+        o->vec = o->count = o->injected = o->valid = o->first_tsc = 0;
+    }
+}
+
+void hvm_vlapic_clear(struct vlapic_struct *vla)
+{
+    bzero(vla, sizeof(*vla));
+}
+
+struct outstanding_ipi *find_vec(struct vlapic_struct *vla, int vec)
+{
+    struct outstanding_ipi *o = NULL;
+    int i;
+
+    /* Find the entry for this vector, or the first empty one. */
+    for(i=0; i<MAX_VLAPIC_LIST; i++)
+    {
+        if(vla->outstanding.list[i].valid && vla->outstanding.list[i].vec == vec)
+        {
+            o = vla->outstanding.list + i;
+            break;
+        } else if(!vla->outstanding.list[i].valid && !o)
+            o = vla->outstanding.list + i;
+    }
+
+    if(!o->valid) {
+        o->vec = vec;
+        o->valid = 1;
+    }
+
+    return o;
 }
 
 void hvm_vlapic_icr_handler(struct hvm_data *h)
@@ -3182,17 +3252,61 @@ void hvm_vlapic_icr_handler(struct hvm_data *h)
         };
     } icr = { .val = e->data };
 
+    void ipi_send(struct vcpu_data *ov, int vec)
+    {
+        struct vlapic_struct *vla;
+        struct outstanding_ipi *o = NULL;
+
+        if(ov->runstate.state == RUNSTATE_LOST) {
+            if(opt.dump_all)
+                fprintf(warn, "%s: v%d in state RUNSTATE_LOST, not counting ipi\n",
+                        __func__, ov->vid);
+            return;
+        }
+
+        vla = &ov->vlapic;
+
+        o = find_vec(vla, vec);
+
+        if(!o)
+        {
+            fprintf(warn, "%s: Couldn't find an open slot!\n",
+                    __func__);
+            return;
+        }
+
+        if(!o->first_tsc) 
+            o->first_tsc = P.now;
+
+        if(opt.dump_all && o->count == 0 && o->injected)
+            printf(" [vla] Pre-injection\n");
+
+        o->count++;
+
+        if((opt.dump_all || opt.dump_cooked)
+#if 0
+           && (ov->runstate.state != RUNSTATE_RUNNING
+               || ov->hvm.vmexit_valid) 
+#endif
+            )
+            printf(" [vla] d%dv%d vec %d state %s (outstanding ipis %d)\n",
+                   ov->d->did, ov->vid,
+                   o->vec,
+                   runstate_name[ov->runstate.state],
+                   o->count);
+    }
+
     if(e->mmio_is_write) {
         if(opt.dump_all || opt.dump_cooked) {
-            printf("              vlapic icr vec %d %s\n",
+            printf("              [vla] d%dv%d icr vec %d %s\n",
+                   h->v->d->did, h->v->vid,
                    icr.vec,
                    hvm_vlapic_icr_dest_shorthand_name[icr.dest_shorthand]);
         }
 
-        if(icr.dest_shorthand == 3 && icr.vec == 0xd1)
+        if(icr.dest_shorthand == 3)
         {
             struct vcpu_data *ov, *v = h->v;
-            struct vlapic_struct *vla;
             struct domain_data *d = v->d;
             int i;
 
@@ -3202,44 +3316,47 @@ void hvm_vlapic_icr_handler(struct hvm_data *h)
                 if(!ov || ov == v)
                     continue;
 
-                if(ov->runstate.state == RUNSTATE_LOST) {
-                    if(opt.dump_all)
-                        fprintf(warn, "%s: v%d in state RUNSTATE_LOST, not counting ipi\n",
-                                __func__, ov->vid);
-                    continue;
-                }
-
-                vla = &ov->vlapic;
+                ipi_send(ov, icr.vec);
 
-                if(!vla->first_ipi_tsc)
-                {
-                    struct record_info *ri;
-                    ri = &v->p->ri;
-                    vla->first_ipi_tsc = ri->tsc;
-                }
-
-                vla->outstanding_ipis++;
-
-                if((opt.dump_all || opt.dump_cooked) &&
-                   (ov->runstate.state != RUNSTATE_RUNNING))
-                    printf(" v%d in state %s (outstanding ipis %d)\n",
-                           ov->vid, runstate_name[ov->runstate.state],
-                           vla->outstanding_ipis);
             }
+        } else if(icr.dest_shorthand != 1) {
+            fprintf(warn, "Strange, vlapic icr %s vec %d!\n",
+                    hvm_vlapic_icr_dest_shorthand_name[icr.dest_shorthand],
+                    icr.vec);
         }
     } else {
         /* Read */
         if(opt.dump_all || opt.dump_cooked) {
-            printf("              vlapic icr status %s\n",
+            printf("              [vla] d%dv%d icr status %s\n",
+                   h->v->d->did, h->v->vid,
                    icr.delivery_status?"pending":"idle");
         }
     }
 
 }
 
+void hvm_vlapic_inject(struct vcpu_data *v, int vec)
+{
+    struct vlapic_struct *vla = &v->vlapic;
+    struct outstanding_ipi *o = NULL;
+
+    o = find_vec(vla, vec);
+
+    if(o) {
+        if(opt.dump_all)
+            printf("  [vla] d%dv%d vec %d injecting\n",
+                   v->d->did, v->vid, vec);
+        o->injected=1;
+    } else {
+        fprintf(stderr, "%s: Couldn't find an open ipi slot!\n",
+                __func__);
+    }
+}
+
 void hvm_vlapic_eoi_handler(struct hvm_data *h) {
     if(opt.dump_all || opt.dump_cooked)
-        printf("              vlapic eoi\n");
+        printf("              [vla] d%dv%d eoi\n",
+               h->v->d->did, h->v->vid);
 }
 
 void hvm_vlapic_handler(struct hvm_data *h)
@@ -3369,10 +3486,7 @@ void hvm_inj_virq_process(struct record_info *ri, struct hvm_data *h) {
         }
     }
 
-
-    /* Vista bug */
-    if(r->vector == 0xd1 && h->v->vlapic.outstanding_ipis)
-        h->v->vlapic.ipi_virq_injected = 1;
+    hvm_vlapic_inject(h->v, r->vector);
 }
 
 /* I/O Handling */
@@ -4623,43 +4737,7 @@ void hvm_vmentry_process(struct record_info *ri, struct hvm_data *h) {
     /* Vista bug 
      * This has to be done here because irqs are injected on the path out
      * to vmexit. */
-    if(h->v->vlapic.ipi_virq_injected)
-    {
-        struct vcpu_data *v = h->v;
-        struct vlapic_struct *vla = &v->vlapic;
-        unsigned long long lat=0;
-
-        if(ri->tsc > vla->first_ipi_tsc)
-            lat = ri->tsc - vla->first_ipi_tsc;
-        else
-            fprintf(stderr, "Strange, first_ipi_tsc %lld > ri->tsc %lld!\n",
-                    vla->first_ipi_tsc, ri->tsc);
-
-        if((opt.dump_all || opt.dump_cooked) && vla->outstanding_ipis > 1)
-        {
-            struct time_struct t;
-            cycles_to_time(lat, &t);
-            printf(" d%dv%d received %d ipis, latency %lld (%lu.%09lu s)\n",
-                   v->d->did, v->vid, vla->outstanding_ipis, lat,
-                   t.s, t.ns);
-        }
-
-        if(opt.summary_info)
-        {
-            update_summary(&h->summary.ipi_latency, lat);
-            h->summary.ipi_count[vla->outstanding_ipis]++;
-            
-        }
-
-        if(opt.dump_cooked || opt.dump_ipi_latency) {
-            struct time_struct t;
-            abs_cycles_to_time(ri->tsc, &t);
-            printf("Ipis: %d latency: %lld (time %lu.%09lu s)\n",
-                   vla->outstanding_ipis, lat, t.s, t.ns);
-        }
-
-        clear_vlapic(vla);
-    }
+    hvm_vlapic_vmentry_cleanup(h->v, ri->tsc);
 
     if(h->w2h.waking && opt.dump_all) 
         printf(" [w2h] d%dv%d Finishing waking\n",
@@ -6473,7 +6551,7 @@ void lose_vcpu(struct vcpu_data *v, tsc_t tsc)
     if(v->data_type == VCPU_DATA_HVM)
         v->hvm.vmexit_valid=0;
     runstate_update(v, RUNSTATE_LOST, tsc);
-    clear_vlapic(&v->vlapic);
+    hvm_vlapic_clear(&v->vlapic);
 
     if(v->data_type == VCPU_DATA_HVM) {
         int i;
@@ -6537,7 +6615,7 @@ void process_lost_records(struct pcpu_info *p)
 
     if ( p->current ) {
     
-        clear_vlapic(&p->current->vlapic);
+        hvm_vlapic_clear(&p->current->vlapic);
         if(p->current->data_type == VCPU_DATA_HVM) {
             p->current->hvm.vmexit_valid=0;
             cr3_switch(0, &p->current->hvm);