Skip to contentSkip to conversation

Miscellaneous updates

PATCH New George Dunlap 1 participant 8 messages Oct 10, 2012

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Miscellaneous updates

Clearing out my local queue of changes before applying other's.

#1 lore raw

PATCH 1/1 xenalyze: Add HVM_EVENT_VLAPIC

# HG changeset patch
# User George Dunlap <[email protected]> # Date 1349261311 -3600
# Node ID 3230041f50a54889784121579604412fdc260228 # Parent 4d47a8934b40556dd98428361c482be419c643be
xenalyze: Add HVM_EVENT_VLAPIC

xenalyze.c +2 -0
@@ -958,6 +958,7 @@ enum {
     HVM_EVENT_REALMODE_EMULATE,
     HVM_EVENT_TRAP,
     HVM_EVENT_TRAP_DEBUG,
+    HVM_EVENT_VLAPIC,
     HVM_EVENT_HANDLER_MAX
 };
 char * hvm_event_handler_name[HVM_EVENT_HANDLER_MAX] = {
@@ -993,6 +994,7 @@ char * hvm_event_handler_name[HVM_EVENT_
     "realmode_emulate",
     "trap",
     "trap_debug",
+    "vlapic"
 };
 
 enum {
#2 lore raw

PATCH 1/1 xenalyze: Process NPFs as generic for summary purposes

In reply to George Dunlap

# HG changeset patch
# User George Dunlap <[email protected]> # Date 1349261558 -3600
# Node ID 4ea8fb7197ff3fad82b224a65cdfbe86db66d6ab # Parent 3230041f50a54889784121579604412fdc260228
xenalyze: Process NPFs as generic for summary purposes

Moves the "generic" post-processing initialization into a function, and calls that function for NPF processes, so that we can get summary information about NPF.

xenalyze.c +16 -7
@@ -4640,6 +4640,8 @@ void hvm_pf_inject_process(struct record
     }
 }
 
+void hvm_generic_postprocess_init(struct record_info *ri, struct hvm_data *h);
+
 void hvm_npf_process(struct record_info *ri, struct hvm_data *h)
 {
     struct {
@@ -4654,6 +4656,9 @@ void hvm_npf_process(struct record_info 
                ri->dump_header,
                (unsigned long long)r->gpa, r->qualification,
                (unsigned long long)r->mfn, r->p2mt);
+
+    if ( opt.summary_info )
+        hvm_generic_postprocess_init(ri, h);
 }
 
 void hvm_rdtsc_process(struct record_info *ri, struct hvm_data *h)
@@ -4695,6 +4700,15 @@ void hvm_generic_summary(struct hvm_data
 
 }
 
+void hvm_generic_postprocess_init(struct record_info *ri, struct hvm_data *h)
+{
+    if ( h->post_process != hvm_generic_postprocess )
+        fprintf(warn, "%s: Strange, h->postprocess set!\n",
+                __func__);
+    h->inflight.generic.event = ri->event;
+    bcopy(h->d, h->inflight.generic.d, sizeof(unsigned int) * 4); 
+}
+
 void hvm_generic_postprocess(struct hvm_data *h)
 {
     long evt = 0;
@@ -4930,15 +4944,10 @@ needs_vmexit:
     case TRC_HVM_CR_READ:
     case TRC_HVM_CR_READ64:
     default:
-        if ( h->post_process != hvm_generic_postprocess )
-            fprintf(warn, "%s: Strange, h->postprocess set!\n",
-                __func__);
-        h->inflight.generic.event = ri->event;
-        bcopy(h->d, h->inflight.generic.d, sizeof(unsigned int) * 4); 
         if(opt.dump_all)
-        {
             hvm_generic_dump(ri, "]");
-        }
+        if(opt.summary_info)
+            hvm_generic_postprocess_init(ri, h);
         break;
     }
 }
#3 lore raw

PATCH 1/1 xenalyze: Don't warn about switching paging levels unless verbosity>=6

In reply to George Dunlap

# HG changeset patch
# User George Dunlap <[email protected]>
# Date 1349261732 -3600
# Node ID 3aad48bd6ca3213c598d16c307ba531dc45d6240
# Parent 4ea8fb7197ff3fad82b224a65cdfbe86db66d6ab
xenalyze: Don't warn about switching paging levels unless verbosity>=6

During boot, the guest paging levels changes back and forth frequently, leading to spam when your'e doing the analysis. Don't print these messages escept at verbosity level 6 (the default is 5).

xenalyze.c +9 -4
@@ -5158,8 +5158,9 @@ void hvm_vmexit_process(struct record_in
     if(ri->event == TRC_HVM_VMEXIT64) {
         if(v->guest_paging_levels != 4)
         {
-            fprintf(warn, "%s: VMEXIT64, but guest_paging_levels %d.  Switching to 4.\n",
-                    __func__, v->guest_paging_levels);
+            if ( verbosity >= 6 )
+                fprintf(warn, "%s: VMEXIT64, but guest_paging_levels %d.  Switching to 4.\n",
+                        __func__, v->guest_paging_levels);
             v->guest_paging_levels = 4;
         }
         if(!is_valid_addr64(r->x64.rip))
@@ -5171,10 +5172,14 @@ void hvm_vmexit_process(struct record_in
         if(v->guest_paging_levels == 4)
         {
             int new_paging_levels = opt.default_guest_paging_levels;
+
             if(new_paging_levels == 4)
                 new_paging_levels = 2; /* Wild guess */
-            fprintf(warn, "%s: VMEXIT, but guest_paging_levels %d.  Switching to %d(default).\n",
-                    __func__, v->guest_paging_levels, new_paging_levels);
+
+            if ( verbosity >= 6 )
+                fprintf(warn, "%s: VMEXIT, but guest_paging_levels %d.  Switching to %d(default).\n",
+                        __func__, v->guest_paging_levels, new_paging_levels);
+
             v->guest_paging_levels = new_paging_levels;
         }
         h->rip = r->x32.eip;
#4 lore raw

PATCH 1/1 xenalyze: Make the warnigns in hvm_generic_postprocess more informative

In reply to George Dunlap

# HG changeset patch
# User George Dunlap <[email protected]>
# Date 1349262302 -3600
# Node ID 6e0e841283e5e68f03fe64d1c107942ab501846a
# Parent 3aad48bd6ca3213c598d16c307ba531dc45d6240
xenalyze: Make the warnigns in hvm_generic_postprocess more informative

xenalyze.c +9 -6
@@ -4739,16 +4739,19 @@ void hvm_generic_postprocess(struct hvm_
         if ( !warned[h->exit_reason] )
         {
             /* If we aren't a known exception, warn and log results */
-            fprintf(warn, "%s: Strange, exit %x missing a handler\n",
-                    __func__, h->exit_reason);
+            fprintf(warn, "%s: Strange, exit %x(%s) missing a handler\n",
+                    __func__, h->exit_reason,
+                    (h->exit_reason > h->exit_reason_max)
+                      ? "[clipped]"
+                      : h->exit_reason_name[h->exit_reason]);
             warned[h->exit_reason]=1;
         }
     }
 
-    if ( evt > HVM_EVENT_HANDLER_MAX || evt < 0)
-    {
-        fprintf(warn, "%s: invalid hvm event %x\n",
-                __func__, h->inflight.generic.event);
+    if ( evt >= HVM_EVENT_HANDLER_MAX || evt < 0)
+    {
+        fprintf(warn, "%s: invalid hvm event %lx(%x)\n",
+                __func__, evt, h->inflight.generic.event);
         error(ERR_RECORD, NULL);
         return;
     }
#5 lore raw

PATCH 1/1 xenalzye: Also strip write bit when processing a generic event

In reply to George Dunlap

# HG changeset patch
# User George Dunlap <[email protected]>
# Date 1349262739 -3600
# Node ID 344f6609af3335e1e27ef55c686c57ff33402d46
# Parent 6e0e841283e5e68f03fe64d1c107942ab501846a
xenalzye: Also strip write bit when processing a generic event

xenalyze.c +2 -1
@@ -4715,7 +4715,8 @@ void hvm_generic_postprocess(struct hvm_
     static unsigned registered[HVM_EVENT_HANDLER_MAX] = { 0 };
 
     if ( h->inflight.generic.event )
-        evt = (h->inflight.generic.event - TRC_HVM_HANDLER) & ~TRC_64_FLAG;
+        evt = (h->inflight.generic.event - TRC_HVM_HANDLER)
+            & ~(TRC_64_FLAG|HVM_IO_ASSIST_WRITE);
     else  {
         static unsigned warned[HVM_EXIT_REASON_MAX] = { 0 };
         /* Some exits we don't expect a handler; just return */
#6 lore raw

PATCH 1/1 xenalyze: Handle 64-bit MMIO

In reply to George Dunlap

# HG changeset patch
# User George Dunlap <[email protected]> # Date 1349263139 -3600
# Node ID 703cd2301a0a04934d30c7e4f7357df82ed12677 # Parent 344f6609af3335e1e27ef55c686c57ff33402d46
xenalyze: Handle 64-bit MMIO

Also use "TRC_HVM_IOPORT_WRITE" rather than adding in the IO_ASSIST_WRITE flag.

xenalyze.c +4 -3
@@ -4903,12 +4903,13 @@ needs_vmexit:
         hvm_pf_xen_process(ri, h);
         break;
     case TRC_HVM_IOPORT_READ:
-    case TRC_HVM_IOPORT_READ|HVM_IO_ASSIST_WRITE:
+    case TRC_HVM_IOPORT_WRITE:
         hvm_io_assist_process(ri, h);
         break;
     case TRC_HVM_IOMEM_READ:
-    case TRC_HVM_IOMEM_READ|HVM_IO_ASSIST_WRITE:
-        /* FIXME: 64-bit */
+    case TRC_HVM_IOMEM_WRITE:
+    case TRC_HVM_IOMEM_READ|TRC_64_FLAG:
+    case TRC_HVM_IOMEM_WRITE|TRC_64_FLAG:
         hvm_mmio_assist_process(ri, h);
         break;
     case TRC_HVM_CR_WRITE:
#7 lore raw

PATCH 1/1 xenalyze: Analyze populate-on-demand reclamation patterns

In reply to George Dunlap

# HG changeset patch
# User George Dunlap <[email protected]> # Date 1349264664 -3600
# Node ID 393e0ead61a506f8bd1dea55ed7b3611ec4c7c1f # Parent 703cd2301a0a04934d30c7e4f7357df82ed12677
xenalyze: Analyze populate-on-demand reclamation patterns

This includes attempting to classify each reclamation to see if it was the result of a fault or of ballooning, as well as tracking the order of the pages reclaimed.

xenalyze.c +121 -3
@@ -1723,6 +1723,21 @@ char * domain_runstate_name[] = {
     [DOMAIN_RUNSTATE_LOST]="lost",
 };
 
+enum {
+    POD_RECLAIM_CONTEXT_UNKNOWN=0,
+    POD_RECLAIM_CONTEXT_FAULT,
+    POD_RECLAIM_CONTEXT_BALLOON,
+    POD_RECLAIM_CONTEXT_MAX
+};
+
+char * pod_reclaim_context_name[] = {
+    [POD_RECLAIM_CONTEXT_UNKNOWN]="unknown",
+    [POD_RECLAIM_CONTEXT_FAULT]="fault",
+    [POD_RECLAIM_CONTEXT_BALLOON]="balloon",
+};
+
+#define POD_ORDER_MAX 4
+
 struct domain_data {
     struct domain_data *next;
     int did;
@@ -1747,6 +1762,14 @@ struct domain_data {
         int done_for[MEM_MAX];
         int done_for_interval[MEM_MAX];
     } memops;
+
+    struct {
+        int reclaim_order[POD_ORDER_MAX];
+        int reclaim_context[POD_RECLAIM_CONTEXT_MAX];
+        int reclaim_context_order[POD_RECLAIM_CONTEXT_MAX][POD_ORDER_MAX];
+        /* FIXME: Do a full cycle summary */
+        int populate_order[POD_ORDER_MAX];
+    } pod;
 };
 
 struct domain_data * domain_list=NULL;
@@ -7396,7 +7419,7 @@ void sched_process(struct pcpu_info *p)
 
 /* ---- Memory ---- */
 void mem_summary_domain(struct domain_data *d) {
-    int i;
+    int i, j;
 
     printf(" Grant table ops:\n");
 
@@ -7413,23 +7436,103 @@ void mem_summary_domain(struct domain_da
             printf("   %-14s: %d\n",
                    mem_name[i],
                    d->memops.done_for[i]);
+
+    printf(" Populate-on-demand:\n");
+    printf("  Populated:\n");
+    for(i=0; i<4; i++)
+    {
+        if ( d->pod.populate_order[i] )
+            printf("   [%d] %d\n", i,
+                   d->pod.populate_order[i]);
+    }
+    printf("  Reclaim order:\n");
+    for(i=0; i<4; i++)
+    {
+        if ( d->pod.reclaim_order[i] )
+            printf("   [%d] %d\n", i,
+                   d->pod.reclaim_order[i]);
+    }
+    printf("  Reclaim contexts:\n");
+    for(j=0; j<POD_RECLAIM_CONTEXT_MAX; j++)
+    {
+        if ( d->pod.reclaim_context[j] )
+        {
+            printf("   * [%s] %d\n",
+                   pod_reclaim_context_name[j],
+                   d->pod.reclaim_context[j]);
+            for(i=0; i<4; i++)
+            {
+                if ( d->pod.reclaim_context_order[j][i] )
+                    printf("    [%d] %d\n", i,
+                           d->pod.reclaim_context_order[j][i]);
+            }
+        }
+    }
+}
+
+int p2m_canonical_order(int order)
+{
+    if ( order % 9
+         || (order / 9) > 2 )
+    {
+        fprintf(warn, "%s: Strange, non-canonical order %d\n",
+                __func__, order);
+        order = 4;
+    } else {
+        order /= 9;
+    }
+    return order;           
 }
 
 void mem_pod_zero_reclaim_process(struct pcpu_info *p)
 {
     struct record_info *ri = &p->ri;
+    int context = POD_RECLAIM_CONTEXT_UNKNOWN;
+    struct vcpu_data *v = p->current;
 
     struct {
         uint64_t gfn, mfn;
         int d:16,order:16;
     } *r = (typeof(r))ri->d;
 
+    if ( v && v->hvm.vmexit_valid )
+    {
+        switch(v->hvm.exit_reason)
+        {
+        case EXIT_REASON_EPT_VIOLATION:
+        case EXIT_REASON_EXCEPTION_NMI:
+            context = POD_RECLAIM_CONTEXT_FAULT;
+            break;
+        case EXIT_REASON_VMCALL:
+            context = POD_RECLAIM_CONTEXT_BALLOON;
+            break;
+        }
+    }
+
     if ( opt.dump_all )
     {
-        printf(" %s pod_zero_reclaim d%d o%d g %llx m %llx\n",
+        printf(" %s pod_zero_reclaim d%d o%d g %llx m %llx ctx %s\n",
                ri->dump_header,
                r->d, r->order,
-               (unsigned long long)r->gfn, (unsigned long long)r->mfn);
+               (unsigned long long)r->gfn, (unsigned long long)r->mfn,
+               pod_reclaim_context_name[context]);
+
+    }
+
+    if ( opt.summary_info )
+    {
+        struct domain_data *d;
+
+        if ( v && (d=v->d) )
+        {
+            int order;
+
+            order = p2m_canonical_order(r->order);
+
+            d->pod.reclaim_order[order]++;
+            d->pod.reclaim_context[context]++;
+            d->pod.reclaim_context_order[context][order]++;
+        }
     }
 }
 
@@ -7449,6 +7552,21 @@ void mem_pod_populate_process(struct pcp
                r->d, r->order,
                (unsigned long long)r->gfn, (unsigned long long)r->mfn);
     }
+
+    if ( opt.summary_info )
+    {
+        struct vcpu_data *v = p->current;
+        struct domain_data *d;
+
+        if ( v && (d=v->d) )
+        {
+            int order;
+
+            order = p2m_canonical_order(r->order);
+
+            d->pod.populate_order[order]++;
+        }        
+    }
 }
 
 void mem_pod_superpage_splinter_process(struct pcpu_info *p)