X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_telemetry.c;h=4ddea670b37e45a4693e13e51f61679ccde802ea;hp=906f2ef0fdcd93486d07dc6e5b0ab1bf9d9f9312;hb=f7e83e5d2d00ba107ccda346da4660ab523471bb;hpb=f3eb8bbb7c58c98b03797f2188e6c1d2a7610c15 diff --git a/palacios/src/palacios/vmm_telemetry.c b/palacios/src/palacios/vmm_telemetry.c index 906f2ef..4ddea67 100644 --- a/palacios/src/palacios/vmm_telemetry.c +++ b/palacios/src/palacios/vmm_telemetry.c @@ -21,19 +21,20 @@ #include #include #include +#include -#ifdef CONFIG_TELEMETRY_GRANULARITY -#define DEFAULT_GRANULARITY CONFIG_TELEMETRY_GRANULARITY +#ifdef V3_CONFIG_TELEMETRY_GRANULARITY +#define DEFAULT_GRANULARITY V3_CONFIG_TELEMETRY_GRANULARITY #else -#define DEFAULT_GRANULARITY 5000 +#define DEFAULT_GRANULARITY 50000 #endif struct telemetry_cb { - void (*telemetry_fn)(struct guest_info * info, void * private_data); + void (*telemetry_fn)(struct v3_vm_info * vm, void * private_data, char * hdr); void * private_data; struct list_head cb_node; @@ -49,25 +50,59 @@ struct exit_event { }; -void v3_init_telemetry(struct guest_info * info) { - struct v3_telemetry_state * telemetry = &(info->telemetry); +static int free_callback(struct v3_vm_info * vm, struct telemetry_cb * cb); +static int free_exit(struct guest_info * core, struct exit_event * event); + + +void v3_init_telemetry(struct v3_vm_info * vm) { + struct v3_telemetry_state * telemetry = &(vm->telemetry); - telemetry->exit_cnt = 0; - telemetry->vmm_start_tsc = 0; - telemetry->prev_tsc = 0; telemetry->invoke_cnt = 0; telemetry->granularity = DEFAULT_GRANULARITY; + telemetry->prev_tsc = 0; - telemetry->exit_root.rb_node = NULL; INIT_LIST_HEAD(&(telemetry->cb_list)); } +void v3_deinit_telemetry(struct v3_vm_info * vm) { + struct telemetry_cb * cb = NULL; + struct telemetry_cb * tmp = NULL; + + list_for_each_entry_safe(cb, tmp, &(vm->telemetry.cb_list), cb_node) { + free_callback(vm, cb); + } +} + + +void v3_init_core_telemetry(struct guest_info * core) { + struct v3_core_telemetry * telemetry = &(core->core_telem); + + telemetry->exit_cnt = 0; + telemetry->vmm_start_tsc = 0; + + telemetry->vm_telem = &(core->vm_info->telemetry); + + telemetry->exit_root.rb_node = NULL; +} + +void v3_deinit_core_telemetry(struct guest_info * core) { + struct rb_node * node = v3_rb_first(&(core->core_telem.exit_root)); + struct exit_event * evt = NULL; + + while (node) { + evt = rb_entry(node, struct exit_event, tree_node); + node = v3_rb_next(node); + + free_exit(core, evt); + } +} + static inline struct exit_event * __insert_event(struct guest_info * info, struct exit_event * evt) { - struct rb_node ** p = &(info->telemetry.exit_root.rb_node); + struct rb_node ** p = &(info->core_telem.exit_root.rb_node); struct rb_node * parent = NULL; struct exit_event * tmp_evt = NULL; @@ -96,14 +131,14 @@ static inline struct exit_event * insert_event(struct guest_info * info, return ret; } - v3_rb_insert_color(&(evt->tree_node), &(info->telemetry.exit_root)); + v3_rb_insert_color(&(evt->tree_node), &(info->core_telem.exit_root)); return NULL; } static struct exit_event * get_exit(struct guest_info * info, uint_t exit_code) { - struct rb_node * n = info->telemetry.exit_root.rb_node; + struct rb_node * n = info->core_telem.exit_root.rb_node; struct exit_event * evt = NULL; while (n) { @@ -132,13 +167,22 @@ static inline struct exit_event * create_exit(uint_t exit_code) { return evt; } + + +static int free_exit(struct guest_info * core, struct exit_event * evt) { + v3_rb_erase(&(evt->tree_node), &(core->core_telem.exit_root)); + V3_Free(evt); + return 0; +} + + void v3_telemetry_start_exit(struct guest_info * info) { - rdtscll(info->telemetry.vmm_start_tsc); + rdtscll(info->core_telem.vmm_start_tsc); } void v3_telemetry_end_exit(struct guest_info * info, uint_t exit_code) { - struct v3_telemetry_state * telemetry = &(info->telemetry); + struct v3_core_telemetry * telemetry = &(info->core_telem); struct exit_event * evt = NULL; uint64_t end_tsc = 0; @@ -159,18 +203,19 @@ void v3_telemetry_end_exit(struct guest_info * info, uint_t exit_code) { // check if the exit count has expired - if ((telemetry->exit_cnt % telemetry->granularity) == 0) { - v3_print_telemetry(info); + if ((telemetry->exit_cnt % telemetry->vm_telem->granularity) == 0) { + v3_print_global_telemetry(info->vm_info); + v3_print_core_telemetry(info); } } -void v3_add_telemetry_cb(struct guest_info * info, - void (*telemetry_fn)(struct guest_info * info, void * private_data), - void * private_data) { - struct v3_telemetry_state * telemetry = &(info->telemetry); +void v3_add_telemetry_cb(struct v3_vm_info * vm, + void (*telemetry_fn)(struct v3_vm_info * vm, void * private_data, char * hdr), + void * private_data) { + struct v3_telemetry_state * telemetry = &(vm->telemetry); struct telemetry_cb * cb = (struct telemetry_cb *)V3_Malloc(sizeof(struct telemetry_cb)); cb->private_data = private_data; @@ -180,43 +225,61 @@ void v3_add_telemetry_cb(struct guest_info * info, } -void v3_print_telemetry(struct guest_info * info) { - struct v3_telemetry_state * telemetry = &(info->telemetry); - uint64_t invoke_tsc = 0; - rdtscll(invoke_tsc); +static int free_callback(struct v3_vm_info * vm, struct telemetry_cb * cb) { + list_del(&(cb->cb_node)); + V3_Free(cb); + + return 0; +} - V3_Print("Telemetry (%d)\n", telemetry->invoke_cnt++); - V3_Print("\ttelemetry window tsc cnt: %d\n", (uint32_t)(invoke_tsc - telemetry->prev_tsc)); - // Exit Telemetry - { - struct exit_event * evt = NULL; - struct rb_node * node = v3_rb_first(&(info->telemetry.exit_root)); - - do { - evt = rb_entry(node, struct exit_event, tree_node); - const char * code_str = vmexit_code_to_str(evt->exit_code); - - V3_Print("%s:%sCnt=%u,%sAvg. Time=%u\n", - code_str, - (strlen(code_str) > 14) ? "\t" : "\t\t", - evt->cnt, - (evt->cnt >= 100) ? "\t" : "\t\t", - (uint32_t)(evt->handler_time / evt->cnt)); - - } while ((node = v3_rb_next(node))); +void v3_print_core_telemetry(struct guest_info * core ) { + struct exit_event * evt = NULL; + struct rb_node * node = v3_rb_first(&(core->core_telem.exit_root)); + + V3_Print("Exit information for Core %d\n", core->vcpu_id); + + if (!node) { + V3_Print("No information yet for this core\n"); + return; } + do { + evt = rb_entry(node, struct exit_event, tree_node); + const char * code_str = vmexit_code_to_str(evt->exit_code); + + V3_Print("%s:%sCnt=%u,%sAvg. Time=%u\n", + code_str, + (strlen(code_str) > 13) ? "\t" : "\t\t", + evt->cnt, + (evt->cnt >= 100) ? "\t" : "\t\t", + (uint32_t)(evt->handler_time / evt->cnt)); + } while ((node = v3_rb_next(node))); + return; +} + +void v3_print_global_telemetry(struct v3_vm_info * vm) { + struct v3_telemetry_state * telemetry = &(vm->telemetry); + uint64_t invoke_tsc = 0; + char hdr_buf[32]; + + rdtscll(invoke_tsc); + + snprintf(hdr_buf, 32, "telem.%d>", telemetry->invoke_cnt++); + + V3_Print("%stelemetry window tsc cnt: %d\n", hdr_buf, (uint32_t)(invoke_tsc - telemetry->prev_tsc)); // Registered callbacks { struct telemetry_cb * cb = NULL; list_for_each_entry(cb, &(telemetry->cb_list), cb_node) { - cb->telemetry_fn(info, cb->private_data); + cb->telemetry_fn(vm, cb->private_data, hdr_buf); } } telemetry->prev_tsc = invoke_tsc; + + V3_Print("%s Telemetry done\n", hdr_buf); }