Miscellaneous updates
PATCH 1/1 Miscellaneous updates
Clearing out my local queue of changes before applying other's.
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 {
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 ; } }
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_inif (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_inif (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;
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 ; }
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 */
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 :
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_daprintf (" %-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)