[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 01 of 12] xenalyze: Allow several summary handlers to register on a single vmexit
VMX tends to have several distinct kinds of handlers for a single vmexit type; notably, EXCEPTION_NMI gets page faults, other traps, emulations, and sometimes other kinds of traps as well; while for SVM, each different trap has a different call type. This patch introduces a signal-style callback mechanism that allows several callbacks to be attached to a given exit reason. Each of these callbacks will be called in the case of a summary event. In order to distinguish different kinds of callbacks, the callback also includes a value which is passed as-is to the function when it's called. It's the size of a pointer so that it can be used as a pointer if necessary; typically it will probably be a small integer value. Each vmexit should only register a handler once with any given data value; there is some syntactic sugar to make sure this happens. Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx> diff -r 288573cb0f11 -r 2e85d4c4042e xenalyze.c --- a/xenalyze.c Fri Oct 07 11:49:04 2011 +0100 +++ b/xenalyze.c Mon Nov 28 16:16:23 2011 +0000 @@ -1308,6 +1308,14 @@ struct pcpu_info; #define RESYNCS_MAX 17 #define PF_XEN_FIXUP_UNSYNC_RESYNC_MAX 2 +struct hvm_data; + +struct hvm_summary_handler_node { + void (*handler)(struct hvm_data *, void* data); + void *data; + struct hvm_summary_handler_node *next; +}; + struct hvm_data { /* Summary information */ int init; @@ -1318,7 +1326,7 @@ struct hvm_data { /* SVM / VMX compatibility. FIXME - should be global */ char ** exit_reason_name; int exit_reason_max; - void (* exit_reason_summary_handler[HVM_EXIT_REASON_MAX])(struct hvm_data *); + struct hvm_summary_handler_node *exit_reason_summary_handler_list[HVM_EXIT_REASON_MAX]; /* Information about particular exit reasons */ struct { @@ -3011,23 +3019,58 @@ void hvm_short_summary(struct hvm_short_ } } -void hvm_set_summary_handler(struct hvm_data *h, void (*s)(struct hvm_data *h)) { +/* Wrapper to try to make sure this is only called once per + * call site, rather than walking through the list each time */ +#define hvm_set_summary_handler(_h, _s, _d) \ + do { \ + static int done=0; \ + int ret; \ + if(!done) { \ + if ((ret=__hvm_set_summary_handler(_h, _s, _d))) \ + fprintf(stderr, "%s: hvm_set_summary_handler returned %d\n", \ + __func__, ret); \ + done=1; \ + } \ + } while(0) + +int __hvm_set_summary_handler(struct hvm_data *h, void (*s)(struct hvm_data *h, void*d), void*d) { /* Set summary handler */ if(h->exit_reason < h->exit_reason_max) { - if(h->exit_reason_summary_handler[h->exit_reason]) + struct hvm_summary_handler_node *p, **q; + + /* Find the end of the list, checking to make sure there are no + * duplicates along the way */ + q=&h->exit_reason_summary_handler_list[h->exit_reason]; + p = *q; + while(p) { - if(h->exit_reason_summary_handler[h->exit_reason]!= s) - fprintf(warn, "Strange, unexpected summary handler for exit_reason %s (%d!)\n", - h->exit_reason_name[h->exit_reason], h->exit_reason); - } - else - { - h->exit_reason_summary_handler[h->exit_reason] = s; - fprintf(warn, "Setting exit_reason %s (%d) summary handler\n", - h->exit_reason_name[h->exit_reason], h->exit_reason); - } - } + if(p->handler == s && p->data == d) + { + fprintf(stderr, "%s: Unexpected duplicate handler %p,%p\n", + __func__, s, d); + error(ERR_STRICT, NULL); + return -EBUSY; + } + q=&p->next; + p=*q; + } + + assert(p==NULL); + + /* Insert the new handler */ + p=malloc(sizeof(*p)); + if (!p) { + fprintf(stderr, "%s: Malloc failed!\n", __func__); + error(ERR_SYSTEM, NULL); + } + p->handler=s; + p->data = d; + p->next=*q; + *q=p; + return 0; + } + return -EINVAL; } #define SIGN_EXTENDED_BITS (~((1ULL<<48)-1)) @@ -3040,7 +3083,7 @@ static inline int is_valid_addr64(unsign return ((va & SIGN_EXTENDED_BITS) == 0); } -void hvm_pf_xen_summary(struct hvm_data *h) { +void hvm_pf_xen_summary(struct hvm_data *h, void *d) { int i,j, k; for(i=0; i<PF_XEN_MAX; i++) @@ -3314,7 +3357,7 @@ void hvm_pf_xen_postprocess(struct hvm_d } /* Set summary handler */ - hvm_set_summary_handler(h, hvm_pf_xen_summary); + hvm_set_summary_handler(h, hvm_pf_xen_summary, NULL); } if(opt.dump_cooked) @@ -4061,7 +4104,7 @@ void cr3_dump_list(struct cr3_value_stru free(qsort_array); } -void hvm_cr3_write_summary(struct hvm_data *h) { +void hvm_cr3_write_summary(struct hvm_data *h, void *data) { int j; for(j=0; j<RESYNCS_MAX; j++) @@ -4071,7 +4114,7 @@ void hvm_cr3_write_summary(struct hvm_da " *[MAX] "); } -void hvm_cr_write_summary(struct hvm_data *h) +void hvm_cr_write_summary(struct hvm_data *h, void *data) { int i; @@ -4081,7 +4124,7 @@ void hvm_cr_write_summary(struct hvm_dat " cr%d ", i); switch(i) { case 3: - hvm_cr3_write_summary(h); + hvm_cr3_write_summary(h, NULL); break; } } @@ -4168,11 +4211,11 @@ void hvm_cr_write_postprocess(struct hvm if ( opt.svm_mode ) { /* For svm, only need a summary for cr3 */ if ( h->exit_reason == VMEXIT_CR3_WRITE ) - hvm_set_summary_handler(h, hvm_cr3_write_summary); + hvm_set_summary_handler(h, hvm_cr3_write_summary, NULL); } else { /* For vmx, real mode may cause EXNMI exits on cr accesses */ if ( h->exit_reason != EXIT_REASON_EXCEPTION_NMI ) - hvm_set_summary_handler(h, hvm_cr_write_summary); + hvm_set_summary_handler(h, hvm_cr_write_summary, NULL); } } } @@ -4229,7 +4272,7 @@ void hvm_cr_write_process(struct record_ } /* msr_write */ -void hvm_msr_write_summary(struct hvm_data *h) +void hvm_msr_write_summary(struct hvm_data *h, void *d) { } @@ -4247,7 +4290,7 @@ void hvm_msr_write_postprocess(struct hv } /* Set summary handler */ - hvm_set_summary_handler(h, hvm_msr_write_summary); + hvm_set_summary_handler(h, hvm_msr_write_summary, NULL); } void hvm_msr_write_process(struct record_info *ri, struct hvm_data *h) @@ -4274,7 +4317,7 @@ void hvm_msr_write_process(struct record } /* msr_read */ -void hvm_msr_read_summary(struct hvm_data *h) +void hvm_msr_read_summary(struct hvm_data *h, void *d) { } @@ -4292,7 +4335,7 @@ void hvm_msr_read_postprocess(struct hvm } /* Set summary handler */ - hvm_set_summary_handler(h, hvm_msr_read_summary); + hvm_set_summary_handler(h, hvm_msr_read_summary, NULL); } void hvm_msr_read_process(struct record_info *ri, struct hvm_data *h) @@ -4318,7 +4361,7 @@ void hvm_msr_read_process(struct record_ h->post_process = hvm_msr_read_postprocess; } -void hvm_vmcall_summary(struct hvm_data *h) +void hvm_vmcall_summary(struct hvm_data *h, void *d) { int i; @@ -4343,6 +4386,7 @@ void hvm_vmcall_postprocess(struct hvm_d else update_summary(&h->summary.vmcall[HYPERCALL_MAX], h->arc_cycles); + hvm_set_summary_handler(h, hvm_vmcall_summary, NULL); } } @@ -4365,7 +4409,6 @@ void hvm_vmcall_process(struct record_in } if(opt.summary) { - hvm_set_summary_handler(h, hvm_vmcall_summary); h->inflight.vmcall.eax = r->eax; h->post_process = hvm_vmcall_postprocess; } @@ -4391,7 +4434,7 @@ void hvm_inj_exc_process(struct record_i } -void hvm_intr_summary(struct hvm_data *h) +void hvm_intr_summary(struct hvm_data *h, void *d) { int i; @@ -4483,7 +4526,7 @@ void hvm_intr_process(struct hvm_data *h if(opt.summary_info) { if(opt.summary) - hvm_set_summary_handler(h, hvm_intr_summary); + hvm_set_summary_handler(h, hvm_intr_summary, NULL); if(vec < EXTERNAL_INTERRUPT_MAX) h->summary.extint[vec]++; @@ -5321,6 +5364,8 @@ void hvm_summary(struct hvm_data *h) { printf("Exit reasons:\n"); for(i=0; i<h->exit_reason_max; i++) { + struct hvm_summary_handler_node *p; + if ( h->exit_reason_name[i] ) PRINT_SUMMARY(h->summary.exit_reason[i], " %-20s ", h->exit_reason_name[i]); @@ -5328,8 +5373,12 @@ void hvm_summary(struct hvm_data *h) { PRINT_SUMMARY(h->summary.exit_reason[i], " %20d ", i); - if(h->exit_reason_summary_handler[i]) - h->exit_reason_summary_handler[i](h); + p=h->exit_reason_summary_handler_list[i]; + while(p) + { + p->handler(h, p->data); + p=p->next; + } } printf("Guest interrupt counts:\n"); @@ -6238,7 +6287,7 @@ void shadow_process(struct pcpu_info *p) if(sevt.minor <= PF_XEN_LAST_FAULT) { h->inflight.pf_xen.pf_case = sevt.minor; if(opt.summary) { - hvm_set_summary_handler(h, hvm_pf_xen_summary); + hvm_set_summary_handler(h, hvm_pf_xen_summary, NULL); } } _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |