[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 07 of 12] xenalyze: Handle MMIO records from different vmexits
handle_mmio() is called in Xen as a generic way to do emulation; in VMX, this at least includes not only EXCEPTION_NMI (page faults in shadow mode) and NPF (nested page fault in HAP mode), but also APIC_ACCESS and sometimes even CR_ACCESS. This patch allows xenalyze to process and summarize mmio records for different vmexits separately. The change that causes the biggest number of line changes is pulling the MMIO information out of pf_xen_extra and in its own struct, which is kept separate from the inflight union. Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx> diff -r 910605f7ade3 -r c9f583c65e07 xenalyze.c --- a/xenalyze.c Mon Nov 28 16:16:23 2011 +0000 +++ b/xenalyze.c Mon Nov 28 16:16:23 2011 +0000 @@ -1252,6 +1252,20 @@ char * pf_xen_name[PF_XEN_MAX] = { #define CORR_VA_INVALID (0ULL-1) +enum { + NONPF_MMIO_APIC, + NONPF_MMIO_NPF, + NONPF_MMIO_UNKNOWN, + NONPF_MMIO_MAX +}; + +struct mmio_info { + unsigned long long gpa; + unsigned long long va; /* Filled only by shadow */ + unsigned data; + unsigned data_valid:1, is_write:1; +}; + struct pf_xen_extra { unsigned long long va; union { @@ -1302,9 +1316,7 @@ struct pf_xen_extra { /* Flags */ unsigned corr_valid:1, corr_is_kernel:1, - va_is_kernel:1, - mmio_data_valid:1, - mmio_is_write:1; + va_is_kernel:1; }; struct pcpu_info; @@ -1351,6 +1363,7 @@ struct hvm_data { struct event_cycle_summary cr3_write_resyncs[RESYNCS_MAX+1]; struct event_cycle_summary vmcall[HYPERCALL_MAX+1]; struct event_cycle_summary generic[HVM_EVENT_HANDLER_MAX]; + struct event_cycle_summary mmio[NONPF_MMIO_MAX]; struct hvm_gi_struct { int count; struct cycle_summary runtime[GUEST_INTERRUPT_CASE_MAX]; @@ -1367,33 +1380,37 @@ struct hvm_data { } summary; /* In-flight accumulation information */ - union { - struct { - unsigned port:31, - is_write:1; - unsigned int val; - } io; - struct pf_xen_extra pf_xen; - struct { - unsigned cr; - unsigned long long val; - int repromote; - } cr_write; - struct { - unsigned addr; - unsigned long long val; - } msr; - struct { - unsigned int event; - uint32_t d[4]; - } generic; - struct { - unsigned eax; - } vmcall; - struct { - unsigned vec; - } intr; - } inflight; + struct { + union { + struct { + unsigned port:31, + is_write:1; + unsigned int val; + } io; + struct pf_xen_extra pf_xen; + struct { + unsigned cr; + unsigned long long val; + int repromote; + } cr_write; + struct { + unsigned addr; + unsigned long long val; + } msr; + struct { + unsigned int event; + uint32_t d[4]; + } generic; + struct { + unsigned eax; + } vmcall; + struct { + unsigned vec; + } intr; + }; + /* MMIO gets its separate area, since many exits may use it */ + struct mmio_info mmio; + }inflight; int resyncs; void (*post_process)(struct hvm_data *); tsc_t exit_tsc, arc_cycles, entry_tsc; @@ -3309,6 +3326,7 @@ void pf_preprocess(struct pf_xen_extra * void hvm_pf_xen_preprocess(unsigned event, struct hvm_data *h) { struct pf_xen_extra *e = &h->inflight.pf_xen; + struct mmio_info *m = &h->inflight.mmio; struct hvm_pf_xen_record *r = (typeof(r))h->d; if(event == TRC_HVM_PF_XEN64) @@ -3325,7 +3343,7 @@ void hvm_pf_xen_preprocess(unsigned even e->error_code = r->x32.error_code; } - if(e->mmio_data_valid) + if(m->data_valid) e->pf_case = PF_XEN_MMIO; else { @@ -3363,8 +3381,11 @@ void hvm_pf_xen_postprocess(struct hvm_d struct pf_xen_extra *e = &h->inflight.pf_xen; if(opt.summary_info) { - update_summary(&h->summary.pf_xen[e->pf_case], - h->arc_cycles); + if(e->pf_case) + update_summary(&h->summary.pf_xen[e->pf_case], + h->arc_cycles); + else + fprintf(warn, "Strange, pf_case 0!\n"); switch(e->pf_case) { case PF_XEN_EMULATE: @@ -3530,7 +3551,7 @@ struct outstanding_ipi *find_vec(struct void hvm_vlapic_icr_handler(struct hvm_data *h) { - struct pf_xen_extra *e = &h->inflight.pf_xen; + struct mmio_info *m = &h->inflight.mmio; union { unsigned int val; struct { @@ -3544,7 +3565,7 @@ void hvm_vlapic_icr_handler(struct hvm_d _res2:2, dest_shorthand:2; }; - } icr = { .val = e->data }; + } icr = { .val = m->data }; void ipi_send(struct vcpu_data *ov, int vec) { @@ -3590,7 +3611,7 @@ void hvm_vlapic_icr_handler(struct hvm_d o->count); } - if(e->mmio_is_write) { + if(m->is_write) { if(opt.dump_all || opt.dump_cooked) { printf(" [vla] d%dv%d icr vec %d %s\n", h->v->d->did, h->v->vid, @@ -3657,9 +3678,9 @@ void hvm_vlapic_eoi_handler(struct hvm_d void hvm_vlapic_handler(struct hvm_data *h) { - struct pf_xen_extra *e = &h->inflight.pf_xen; - - switch(e->gpa) { + struct mmio_info *m = &h->inflight.mmio; + + switch(m->gpa) { case 0xfee00300: hvm_vlapic_icr_handler(h); break; @@ -3673,14 +3694,56 @@ void hvm_vlapic_handler(struct hvm_data /* Also called by shadow_mmio_postprocess */ void enumerate_mmio(struct hvm_data *h) { - struct pf_xen_extra *e = &h->inflight.pf_xen; - - if ( e->mmio_data_valid ) - update_io_address(&h->summary.io.mmio, e->gpa, e->mmio_is_write, h->arc_cycles, e->va); + struct mmio_info *m = &h->inflight.mmio; + + if ( m->data_valid ) + update_io_address(&h->summary.io.mmio, m->gpa, m->is_write, h->arc_cycles, m->va); +} + +void hvm_mmio_summary(struct hvm_data *h, void *data) +{ + int reason=(int)data; + + PRINT_SUMMARY(h->summary.mmio[reason], + " mmio "); } void hvm_mmio_assist_postprocess(struct hvm_data *h) { + int reason; + + switch(h->exit_reason) + { + case VMEXIT_NPF: + case EXIT_REASON_EPT_VIOLATION: + reason=NONPF_MMIO_NPF; + hvm_set_summary_handler(h, hvm_mmio_summary, (void *)reason); + break; + case EXIT_REASON_APIC_ACCESS: + reason=NONPF_MMIO_APIC; + hvm_set_summary_handler(h, hvm_mmio_summary, (void *)reason); + break; + default: + { + static int warned = 0; + if (!warned) + { + fprintf(stderr, "%s: Strange, MMIO with unexpected exit reason %d\n", + __func__, h->exit_reason); + warned=1; + } + reason=NONPF_MMIO_UNKNOWN; + hvm_set_summary_handler(h, hvm_mmio_summary, (void *)reason); + break; + } + } + + if(opt.summary_info) + { + update_summary(&h->summary.mmio[reason], + h->arc_cycles); + } + if ( opt.with_mmio_enumeration ) enumerate_mmio(h); } @@ -3688,8 +3751,7 @@ void hvm_mmio_assist_postprocess(struct #define HVM_IO_ASSIST_WRITE 0x200 void hvm_mmio_assist_process(struct record_info *ri, struct hvm_data *h) { - struct pf_xen_extra *e = &h->inflight.pf_xen; - + struct mmio_info *m = &h->inflight.mmio; union { struct { unsigned int gpa; @@ -3711,30 +3773,32 @@ void hvm_mmio_assist_process(struct reco } mevt = { .event = ri->event }; if(mevt.x64) { - e->gpa = r->x64.gpa; - e->data = r->x64.data; + m->gpa = r->x64.gpa; + m->data = r->x64.data; if(ri->extra_words*(sizeof(unsigned int))==sizeof(r->x64)) - e->mmio_data_valid=1; + m->data_valid=1; } else { - e->gpa = r->x32.gpa; - e->data = r->x32.data; + m->gpa = r->x32.gpa; + m->data = r->x32.data; if(ri->extra_words*(sizeof(unsigned int))==sizeof(r->x32)) - e->mmio_data_valid=1; - } - - e->mmio_is_write = mevt.write; + m->data_valid=1; + } + + m->is_write = mevt.write; if(opt.dump_all) { - if(e->mmio_data_valid) - printf("]%s mmio_assist %c gpa %llx data %x\n", h->dump_header, - mevt.write?'w':'r', e->gpa, e->data); + if(m->data_valid) + printf("]%s mmio_assist %c gpa %llx data %x\n", + h->dump_header, + mevt.write?'w':'r', + m->gpa, m->data); else printf("]%s mmio_assist %c gpa %llx (no data)\n", h->dump_header, - mevt.write?'w':'r', e->gpa); - } - - if((e->gpa & 0xfffff000) == 0xfee00000) + mevt.write?'w':'r', m->gpa); + } + + if((m->gpa & 0xfffff000) == 0xfee00000) hvm_vlapic_handler(h); /* Catch MMIOs that don't go through the shadow code; tolerate @@ -5857,6 +5921,7 @@ void shadow_emulate_other_process(struct e->gfn = r.gfn; e->va = r.va; + e->pf_case = sevt.minor; pf_preprocess(e, h->v->guest_paging_levels); @@ -6035,10 +6100,15 @@ void shadow_fixup_process(struct record_ void shadow_mmio_postprocess(struct hvm_data *h) { struct pf_xen_extra *e = &h->inflight.pf_xen; + struct mmio_info *m = &h->inflight.mmio; if ( opt.summary_info ) { - update_summary(&h->summary.pf_xen[e->pf_case], h->arc_cycles); + if(e->pf_case) + update_summary(&h->summary.pf_xen[e->pf_case], + h->arc_cycles); + else + fprintf(warn, "Strange, pf_case 0!\n"); hvm_update_short_summary(h, HVM_SHORT_SUMMARY_MMIO); } @@ -6048,23 +6118,23 @@ void shadow_mmio_postprocess(struct hvm_ if ( opt.dump_cooked ) { - if(e->mmio_data_valid) + if(m->data_valid) printf(" %s %smmio %s va %llx eip %llx%s gpa %llx data %x\n", h->dump_header, (e->pf_case==PF_XEN_FAST_MMIO)?"fast ":"", - e->mmio_is_write?"write":"read", + m->is_write?"write":"read", e->va, h->rip, find_symbol(h->rip), - e->gpa, - e->data); + m->gpa, + m->data); else printf(" %s %smmio %s va %llx eip %llx%s gpa %llx (no data)\n", h->dump_header, (e->pf_case==PF_XEN_FAST_MMIO)?"fast ":"", - e->mmio_is_write?"write":"read", - e->va, + m->is_write?"write":"read", + m->va, h->rip, find_symbol(h->rip), - e->gpa); + m->gpa); } } @@ -6072,6 +6142,7 @@ void shadow_mmio_postprocess(struct hvm_ void shadow_mmio_process(struct record_info *ri, struct hvm_data *h) { struct pf_xen_extra *e = &h->inflight.pf_xen; + struct mmio_info *m = &h->inflight.mmio; union { /* for PAE, guest_l1e may be 64 while guest_va may be 32; so put it first for alignment sake. */ @@ -6104,7 +6175,7 @@ void shadow_mmio_process(struct record_i error(ERR_RECORD, ri); return; } - e->va = r->gpl2.va; + e->va = m->va = r->gpl2.va; break; case 4: if(sizeof(r->gpl4) != ri->extra_words * 4) @@ -6115,7 +6186,7 @@ void shadow_mmio_process(struct record_i error(ERR_RECORD, ri); return; } - e->va = r->gpl4.va; + e->va = m->va = r->gpl4.va; break; } @@ -6135,7 +6206,11 @@ void shadow_propagate_postprocess(struct if ( opt.summary_info ) { - update_summary(&h->summary.pf_xen[e->pf_case], h->arc_cycles); + if(e->pf_case) + update_summary(&h->summary.pf_xen[e->pf_case], + h->arc_cycles); + else + fprintf(warn, "Strange, pf_case 0!\n"); hvm_update_short_summary(h, HVM_SHORT_SUMMARY_PROPAGATE); } @@ -6255,20 +6330,20 @@ void shadow_fault_generic_dump(unsigned void shadow_fault_generic_postprocess(struct hvm_data *h) { - union shadow_event sevt = { .event = h->inflight.generic.event }; + struct pf_xen_extra *e = &h->inflight.pf_xen; + if ( e->pf_case < PF_XEN_NOT_SHADOW || e->pf_case > PF_XEN_LAST_FAULT ) + { + fprintf(warn, "%s: Strange, unexpected case %d\n", + __func__, e->pf_case); + return; + } + if(opt.summary_info) { - update_summary(&h->summary.pf_xen[sevt.minor], - h->arc_cycles); + update_summary(&h->summary.pf_xen[e->pf_case], + h->arc_cycles); hvm_update_short_summary(h, HVM_SHORT_SUMMARY_PROPAGATE); } - - if(opt.dump_cooked) - { - shadow_fault_generic_dump(h->inflight.generic.event, - h->inflight.generic.d, - " ", h->dump_header); - } } void shadow_fault_generic_process(struct record_info *ri, struct hvm_data *h) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |