From: Jack Lange Date: Thu, 29 Jan 2009 04:57:09 +0000 (-0600) Subject: added profiling support X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=362391accc505b29d938e9d0a21bf6a28a8cee34 added profiling support and also added license to some files --- diff --git a/geekos/src/geekos/vm.c b/geekos/src/geekos/vm.c index c391c63..17c3499 100644 --- a/geekos/src/geekos/vm.c +++ b/geekos/src/geekos/vm.c @@ -106,6 +106,8 @@ int RunVMM(struct Boot_Info * bootInfo) { vm_config.rombios_size = rombios->length; region_start += rombios->length; + + vm_config.enable_profiling = 1; vm_config.vgabios = region_start; vm_config.vgabios_size = vgabios->length; diff --git a/palacios/build/Makefile b/palacios/build/Makefile index 3969547..c50323e 100644 --- a/palacios/build/Makefile +++ b/palacios/build/Makefile @@ -267,6 +267,7 @@ VMM_OBJS := \ palacios/vmm_socket.o \ palacios/vmm_xed.o \ palacios/vmm_rbtree.o \ + palacios/vmm_profiler.o \ # vmx.c vmcs_gen.c vmcs.c diff --git a/palacios/include/palacios/svm_handler.h b/palacios/include/palacios/svm_handler.h index e2425ac..4cab37c 100644 --- a/palacios/include/palacios/svm_handler.h +++ b/palacios/include/palacios/svm_handler.h @@ -193,6 +193,8 @@ int v3_handle_svm_exit(struct guest_info * info); +const uchar_t * vmexit_code_to_str(uint_t exit_code); + #endif // ! __V3VEE__ diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 271bbb9..7871eb0 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -32,6 +32,7 @@ #include #include #include +#include @@ -97,11 +98,9 @@ struct v3_segments { }; struct shadow_page_state; -struct shadow_map; -struct vmm_io_map; struct emulation_state; struct v3_intr_state; - +struct v3_profiler; @@ -149,6 +148,9 @@ struct guest_info { void * vmm_data; + uint_t enable_profiler; + struct v3_profiler profiler; + void * decoder_state; struct v3_msr guest_efer; diff --git a/palacios/include/palacios/vmm.h b/palacios/include/palacios/vmm.h index 549ccb1..9fae52e 100644 --- a/palacios/include/palacios/vmm.h +++ b/palacios/include/palacios/vmm.h @@ -258,6 +258,9 @@ struct v3_vm_config { // so we can specify maximum physical address size // (We're screwed if we want to do 32 bit host/64 bit guest) + + int enable_profiling; + int use_ramdisk; void * ramdisk; int ramdisk_size; diff --git a/palacios/include/palacios/vmm_decoder.h b/palacios/include/palacios/vmm_decoder.h index ff70106..0ae0109 100644 --- a/palacios/include/palacios/vmm_decoder.h +++ b/palacios/include/palacios/vmm_decoder.h @@ -1,4 +1,3 @@ - /* * This file is part of the Palacios Virtual Machine Monitor developed * by the V3VEE Project with funding from the United States National diff --git a/palacios/include/palacios/vmm_hashtable.h b/palacios/include/palacios/vmm_hashtable.h index a51c53a..5acb89e 100644 --- a/palacios/include/palacios/vmm_hashtable.h +++ b/palacios/include/palacios/vmm_hashtable.h @@ -104,18 +104,18 @@ ulong_t hash_buffer(uchar_t * msg, uint_t length); #define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ - int fnname (struct hashtable * htable, keytype key, valuetype value) { \ - return hashtable_insert(htable, (addr_t)key, (addr_t)value); \ + static int fnname (struct hashtable * htable, keytype key, valuetype value) { \ + return hashtable_insert(htable, (addr_t)key, (addr_t)value); \ } #define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ - valuetype * fnname (struct hashtable * htable, keytype key) { \ - return (valuetype *) (hashtable_search(htable, (addr_t)key)); \ + static valuetype * fnname (struct hashtable * htable, keytype key) { \ + return (valuetype *) (hashtable_search(htable, (addr_t)key)); \ } #define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype, free_key) \ - valuetype * fnname (struct hashtable * htable, keytype key) { \ - return (valuetype *) (hashtable_remove(htable, (addr_t)key, free_key)); \ + static valuetype * fnname (struct hashtable * htable, keytype key) { \ + return (valuetype *) (hashtable_remove(htable, (addr_t)key, free_key)); \ } @@ -154,6 +154,11 @@ addr_t hashtable_remove(struct hashtable * htable, addr_t key, int free_key); uint_t hashtable_count(struct hashtable * htable); +// Specialty functions for a counting hashtable +int hashtable_inc(struct hashtable * htable, addr_t key, addr_t value); +int hashtable_dec(struct hashtable * htable, addr_t key, addr_t value); + + /* ************ */ /* ITERATOR API */ /* ************ */ diff --git a/palacios/include/palacios/vmm_instr_emulator.h b/palacios/include/palacios/vmm_instr_emulator.h index 74701a5..a971805 100644 --- a/palacios/include/palacios/vmm_instr_emulator.h +++ b/palacios/include/palacios/vmm_instr_emulator.h @@ -1,3 +1,22 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + #include diff --git a/palacios/include/palacios/vmm_profiler.h b/palacios/include/palacios/vmm_profiler.h new file mode 100644 index 0000000..b083232 --- /dev/null +++ b/palacios/include/palacios/vmm_profiler.h @@ -0,0 +1,49 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __VMM_PROFILER_H__ +#define __VMM_PROFILER_H__ + +#ifdef __V3VEE__ + +#include + +struct guest_info; + + +struct v3_profiler { + uint_t total_exits; + + ullong_t start_time; + ullong_t end_time; + + struct rb_root root; +}; + + +void v3_init_profiler(struct guest_info * info); + +void v3_profile_exit(struct guest_info * info, uint_t exit_code); + +void v3_print_profile(struct guest_info * info); + + +#endif + +#endif diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index f5489c3..986bec8 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -39,6 +39,8 @@ #include +#include + extern void v3_stgi(); extern void v3_clgi(); @@ -352,7 +354,6 @@ static int start_svm_guest(struct guest_info *info) { ullong_t tmp_tsc; uint_t vm_cr_low = 0, vm_cr_high = 0; - v3_enable_ints(); v3_clgi(); @@ -384,10 +385,12 @@ static int start_svm_guest(struct guest_info *info) { v3_stgi(); - if (num_exits % 25 == 0) { + if ((num_exits % 1000) == 0) { PrintDebug("SVM Exit number %d\n", num_exits); + v3_print_profile(info); } + if (v3_handle_svm_exit(info) != 0) { vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data)); @@ -416,10 +419,6 @@ static int start_svm_guest(struct guest_info *info) { } v3_print_GPRs(info); - - - - PrintDebug("SVM Exit Code: %p\n", (void *)(addr_t)guest_ctrl->exit_code); PrintDebug("exit_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1)); @@ -442,6 +441,7 @@ static int start_svm_guest(struct guest_info *info) { break; } + } return 0; } diff --git a/palacios/src/palacios/svm_handler.c b/palacios/src/palacios/svm_handler.c index 1f834a6..8424137 100644 --- a/palacios/src/palacios/svm_handler.c +++ b/palacios/src/palacios/svm_handler.c @@ -30,11 +30,10 @@ #include #include #include +#include -static const uchar_t * vmexit_code_to_str(uint_t exit_code); - int v3_handle_svm_exit(struct guest_info * info) { vmcb_ctrl_t * guest_ctrl = 0; @@ -69,7 +68,10 @@ int v3_handle_svm_exit(struct guest_info * info) { exit_code = guest_ctrl->exit_code; - + + + + // Disable printing io exits due to bochs debug messages //if (!((exit_code == VMEXIT_IOIO) && ((ushort_t)(guest_ctrl->exit_info1 >> 16) == 0x402))) { @@ -106,12 +108,10 @@ int v3_handle_svm_exit(struct guest_info * info) { } - // } - // PrintDebugVMCB((vmcb_t*)(info->vmm_data)); - - // PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data); - //PrintDebug("RIP: %x\n", guest_state->rip); + if (info->enable_profiler) { + rdtscll(info->profiler.start_time); + } //PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); @@ -429,6 +429,13 @@ int v3_handle_svm_exit(struct guest_info * info) { // END OF SWITCH (EXIT_CODE) + if (info->enable_profiler) { + rdtscll(info->profiler.end_time); + v3_profile_exit(info, exit_code); + } + + + // Update the low level state if (v3_intr_pending(info)) { diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index 82f34e2..180a618 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -34,6 +36,7 @@ #include + #include #define USE_GENERIC 1 @@ -99,6 +102,14 @@ int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) setup_devices(info, config_ptr); + + if (config_ptr->enable_profiling) { + info->enable_profiler = 1; + v3_init_profiler(info); + } else { + info->enable_profiler = 0; + } + //v3_hook_io_port(info, 1234, &IO_Read, NULL, info); // Setup initial cpu register state diff --git a/palacios/src/palacios/vmm_hashtable.c b/palacios/src/palacios/vmm_hashtable.c index 612ae78..fa9aba3 100644 --- a/palacios/src/palacios/vmm_hashtable.c +++ b/palacios/src/palacios/vmm_hashtable.c @@ -394,6 +394,55 @@ int hashtable_change(struct hashtable * htable, addr_t key, addr_t value, int fr +int hashtable_inc(struct hashtable * htable, addr_t key, addr_t value) { + struct hash_entry * tmp_entry; + uint_t hash_value; + uint_t index; + + hash_value = do_hash(htable, key); + + index = indexFor(htable->table_length, hash_value); + + tmp_entry = htable->table[index]; + + while (tmp_entry != NULL) { + /* Check hash value to short circuit heavier comparison */ + if ((hash_value == tmp_entry->hash) && (htable->eq_fn(key, tmp_entry->key))) { + + tmp_entry->value += value; + return -1; + } + tmp_entry = tmp_entry->next; + } + return 0; +} + + +int hashtable_dec(struct hashtable * htable, addr_t key, addr_t value) { + struct hash_entry * tmp_entry; + uint_t hash_value; + uint_t index; + + hash_value = do_hash(htable, key); + + index = indexFor(htable->table_length, hash_value); + + tmp_entry = htable->table[index]; + + while (tmp_entry != NULL) { + /* Check hash value to short circuit heavier comparison */ + if ((hash_value == tmp_entry->hash) && (htable->eq_fn(key, tmp_entry->key))) { + + tmp_entry->value -= value; + return -1; + } + tmp_entry = tmp_entry->next; + } + return 0; +} + + + /*****************************************************************************/ /* returns value associated with key */ diff --git a/palacios/src/palacios/vmm_paging_debug.h b/palacios/src/palacios/vmm_paging_debug.h index cba22a8..21817a3 100644 --- a/palacios/src/palacios/vmm_paging_debug.h +++ b/palacios/src/palacios/vmm_paging_debug.h @@ -1,3 +1,21 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ #ifdef USE_VMM_PAGING_DEBUG diff --git a/palacios/src/palacios/vmm_profiler.c b/palacios/src/palacios/vmm_profiler.c new file mode 100644 index 0000000..362b8c9 --- /dev/null +++ b/palacios/src/palacios/vmm_profiler.c @@ -0,0 +1,142 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include +#include + + +struct exit_event { + uint_t exit_code; + uint_t exit_count; + uint_t handler_time; + + struct rb_node tree_node; +}; + + +void v3_init_profiler(struct guest_info * info) { + info->profiler.total_exits = 0; + + info->profiler.start_time = 0; + info->profiler.end_time = 0; + + info->profiler.root.rb_node = NULL; +} + + + +static inline struct exit_event * __insert_event(struct guest_info * info, + struct exit_event * evt) { + struct rb_node ** p = &(info->profiler.root.rb_node); + struct rb_node * parent = NULL; + struct exit_event * tmp_evt = NULL; + + while (*p) { + parent = *p; + tmp_evt = rb_entry(parent, struct exit_event, tree_node); + + if (evt->exit_code < tmp_evt->exit_code) { + p = &(*p)->rb_left; + } else if (evt->exit_code > tmp_evt->exit_code) { + p = &(*p)->rb_right; + } else { + return tmp_evt; + } + } + rb_link_node(&(evt->tree_node), parent, p); + + return NULL; +} + +static inline struct exit_event * insert_event(struct guest_info * info, + struct exit_event * evt) { + struct exit_event * ret; + + if ((ret = __insert_event(info, evt))) { + return ret; + } + + v3_rb_insert_color(&(evt->tree_node), &(info->profiler.root)); + + return NULL; +} + + +static struct exit_event * get_exit(struct guest_info * info, uint_t exit_code) { + struct rb_node * n = info->profiler.root.rb_node; + struct exit_event * evt = NULL; + + while (n) { + evt = rb_entry(n, struct exit_event, tree_node); + + if (exit_code < evt->exit_code) { + n = n->rb_left; + } else if (exit_code > evt->exit_code) { + n = n->rb_right; + } else { + return evt; + } + } + + return NULL; +} + + +static inline struct exit_event * create_exit(uint_t exit_code) { + struct exit_event * evt = V3_Malloc(sizeof(struct exit_event)); + + evt->exit_code = exit_code; + evt->exit_count = 0; + evt->handler_time = 0; + + return evt; +} + +void v3_profile_exit(struct guest_info * info, uint_t exit_code) { + uint_t time = (info->profiler.end_time - info->profiler.start_time); + struct exit_event * evt = get_exit(info, exit_code); + + if (evt == NULL) { + evt = create_exit(exit_code); + insert_event(info, evt); + } + + evt->handler_time += time; + evt->exit_count++; + + info->profiler.total_exits++; +} + + +void v3_print_profile(struct guest_info * info) { + struct exit_event * evt = NULL; + struct rb_node * node = v3_rb_first(&(info->profiler.root)); + + do { + evt = rb_entry(node, struct exit_event, tree_node); + + PrintDebug("%s: Cnt=%u, Time=%u\n", + vmexit_code_to_str(evt->exit_code), + evt->exit_count, + evt->handler_time); + + } while ((node = v3_rb_next(node))); +} diff --git a/palacios/src/palacios/vmm_shadow_paging.c b/palacios/src/palacios/vmm_shadow_paging.c index 198d17e..9b89157 100644 --- a/palacios/src/palacios/vmm_shadow_paging.c +++ b/palacios/src/palacios/vmm_shadow_paging.c @@ -62,14 +62,14 @@ struct shadow_page_data { -DEFINE_HASHTABLE_INSERT(add_cr3_to_cache, addr_t, struct hashtable *); -DEFINE_HASHTABLE_SEARCH(find_cr3_in_cache, addr_t, struct hashtable *); -DEFINE_HASHTABLE_REMOVE(del_cr3_from_cache, addr_t, struct hashtable *, 0); +//DEFINE_HASHTABLE_INSERT(add_cr3_to_cache, addr_t, struct hashtable *); +//DEFINE_HASHTABLE_SEARCH(find_cr3_in_cache, addr_t, struct hashtable *); +//DEFINE_HASHTABLE_REMOVE(del_cr3_from_cache, addr_t, struct hashtable *, 0); DEFINE_HASHTABLE_INSERT(add_pte_map, addr_t, addr_t); DEFINE_HASHTABLE_SEARCH(find_pte_map, addr_t, addr_t); -DEFINE_HASHTABLE_REMOVE(del_pte_map, addr_t, addr_t, 0); +//DEFINE_HASHTABLE_REMOVE(del_pte_map, addr_t, addr_t, 0);