X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_telemetry.c;h=988090fc3f303c1646afbe1581d2208a3ab8b658;hb=40a6dd36505a959c132c32497aa50bd74afd8250;hp=fae3c76c813d51fa71086e60c3de725e674b9376;hpb=300810f123725663d5f7ae638ff6cb93d0a89ae5;p=palacios.git diff --git a/palacios/src/palacios/vmm_telemetry.c b/palacios/src/palacios/vmm_telemetry.c index fae3c76..988090f 100644 --- a/palacios/src/palacios/vmm_telemetry.c +++ b/palacios/src/palacios/vmm_telemetry.c @@ -20,12 +20,14 @@ #include #include #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 50000 #endif @@ -50,6 +52,10 @@ struct exit_event { }; +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); @@ -61,6 +67,16 @@ void v3_init_telemetry(struct v3_vm_info * vm) { 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); @@ -72,6 +88,18 @@ void v3_init_core_telemetry(struct guest_info * core) { 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, @@ -134,6 +162,11 @@ static struct exit_event * get_exit(struct guest_info * info, uint_t exit_code) static inline struct exit_event * create_exit(uint_t exit_code) { struct exit_event * evt = V3_Malloc(sizeof(struct exit_event)); + if (!evt) { + PrintError(VM_NONE, VCORE_NONE, "Cannot allocate in createing exit in telemetry\n"); + return NULL; + } + evt->exit_code = exit_code; evt->cnt = 0; evt->handler_time = 0; @@ -141,6 +174,15 @@ 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->core_telem.vmm_start_tsc); } @@ -169,7 +211,7 @@ 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->vm_telem->granularity) == 0) { - v3_print_telemetry(info->vm_info); + v3_print_telemetry(info->vm_info, info); } } @@ -182,6 +224,11 @@ void v3_add_telemetry_cb(struct v3_vm_info * vm, struct v3_telemetry_state * telemetry = &(vm->telemetry); struct telemetry_cb * cb = (struct telemetry_cb *)V3_Malloc(sizeof(struct telemetry_cb)); + if (!cb) { + PrintError(vm, VCORE_NONE, "Cannot allocate in adding a telemtry callback\n"); + return ; + } + cb->private_data = private_data; cb->telemetry_fn = telemetry_fn; @@ -190,47 +237,96 @@ void v3_add_telemetry_cb(struct v3_vm_info * vm, -void v3_print_telemetry(struct v3_vm_info * vm) { +static int free_callback(struct v3_vm_info * vm, struct telemetry_cb * cb) { + list_del(&(cb->cb_node)); + V3_Free(cb); + + return 0; +} + + +static void telemetry_header(struct v3_vm_info *vm, char *hdr_buf, int len) +{ struct v3_telemetry_state * telemetry = &(vm->telemetry); - uint64_t invoke_tsc = 0; - char hdr_buf[32]; - int i; + snprintf(hdr_buf, len, "telem.%d>", telemetry->invoke_cnt); +} +static void print_telemetry_start(struct v3_vm_info *vm, char *hdr_buf) +{ + struct v3_telemetry_state * telemetry = &(vm->telemetry); + uint64_t invoke_tsc = 0; rdtscll(invoke_tsc); + V3_Print(vm, VCORE_NONE, "%stelemetry window tsc cnt: %u\n", hdr_buf, (uint32_t)(invoke_tsc - telemetry->prev_tsc)); + telemetry->prev_tsc = invoke_tsc; +} - snprintf(hdr_buf, 32, "telem.%d>", telemetry->invoke_cnt++); +static void print_telemetry_end(struct v3_vm_info *vm, char *hdr_buf) +{ + V3_Print(vm, VCORE_NONE, "%s Telemetry done\n", hdr_buf); +} - V3_Print("%stelemetry window tsc cnt: %d\n", hdr_buf, (uint32_t)(invoke_tsc - telemetry->prev_tsc)); +static void print_core_telemetry(struct guest_info * core, char *hdr_buf) +{ + struct exit_event * evt = NULL; + struct rb_node * node = v3_rb_first(&(core->core_telem.exit_root)); + V3_Print(core->vm_info, core, "Exit information for Core %d\n", core->vcpu_id); + + if (!node) { + V3_Print(core->vm_info, core, "No information yet for this core\n"); + return; + } - // Exit Telemetry - for (i = 0; i < vm->num_cores; i++) { - struct guest_info * core = &(vm->cores[i]); - struct exit_event * evt = NULL; - struct rb_node * node = v3_rb_first(&(core->core_telem.exit_root)); + do { + extern v3_cpu_arch_t v3_mach_type; + const char * code_str = NULL; - V3_Print("Exit information for Core %d\n", core->cpu_id); - - if (!node) { - V3_Print("No information yet for this core\n"); - continue; + evt = rb_entry(node, struct exit_event, tree_node); + + switch (v3_mach_type) { + case V3_SVM_CPU: + case V3_SVM_REV3_CPU: + + code_str = v3_svm_exit_code_to_str(evt->exit_code); + break; + case V3_VMX_CPU: + case V3_VMX_EPT_CPU: + case V3_VMX_EPT_UG_CPU: + code_str = v3_vmx_exit_code_to_str(evt->exit_code); + break; + + default: + continue; } - do { - evt = rb_entry(node, struct exit_event, tree_node); - const char * code_str = vmexit_code_to_str(evt->exit_code); - - V3_Print("%s%s:%sCnt=%u,%sAvg. Time=%u\n", - hdr_buf, - 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))); - } + V3_Print(core->vm_info, core, "%s%s:%sCnt=%u,%sAvg. Time=%u\n", + hdr_buf, 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_core_telemetry(struct guest_info * core ) { + struct v3_vm_info *vm = core->vm_info; + struct v3_telemetry_state * telemetry = &(vm->telemetry); + char hdr_buf[32]; + + telemetry_header(vm, hdr_buf, 32); + telemetry->invoke_cnt++; // XXX this increment isn't atomic and probably should be + print_telemetry_start(vm, hdr_buf); + print_core_telemetry(core, hdr_buf); + print_telemetry_end(vm, hdr_buf); + return; +} + +static void telemetry_callbacks(struct v3_vm_info * vm, char *hdr_buf) +{ + struct v3_telemetry_state * telemetry = &(vm->telemetry); // Registered callbacks { struct telemetry_cb * cb = NULL; @@ -239,9 +335,32 @@ void v3_print_telemetry(struct v3_vm_info * vm) { cb->telemetry_fn(vm, cb->private_data, hdr_buf); } } +} - telemetry->prev_tsc = invoke_tsc; +void v3_print_global_telemetry(struct v3_vm_info * vm) { + struct v3_telemetry_state * telemetry = &(vm->telemetry); + char hdr_buf[32]; + + telemetry_header(vm, hdr_buf, 32); + telemetry->invoke_cnt++; // XXX this increment isn't atomic and probably should be + + print_telemetry_start( vm, hdr_buf ); + telemetry_callbacks( vm, hdr_buf ); + print_telemetry_end( vm, hdr_buf ); +} + +void v3_print_telemetry(struct v3_vm_info * vm, struct guest_info * core ) +{ + struct v3_telemetry_state * telemetry = &(vm->telemetry); + char hdr_buf[32]; + + telemetry_header(vm, hdr_buf, 32); + telemetry->invoke_cnt++; // XXX this increment isn't atomic and probably should be - V3_Print("%s Telemetry done\n", hdr_buf); + print_telemetry_start(vm, hdr_buf); + print_core_telemetry(core, hdr_buf); + telemetry_callbacks(vm, hdr_buf); + print_telemetry_end(vm, hdr_buf); + return; }