|
[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 |