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;
palacios/vmm_socket.o \
palacios/vmm_xed.o \
palacios/vmm_rbtree.o \
+ palacios/vmm_profiler.o \
# vmx.c vmcs_gen.c vmcs.c
int v3_handle_svm_exit(struct guest_info * info);
+const uchar_t * vmexit_code_to_str(uint_t exit_code);
+
#endif // ! __V3VEE__
#include <palacios/vmm_emulator.h>
#include <palacios/vmm_host_events.h>
#include <palacios/vmm_msr.h>
+#include <palacios/vmm_profiler.h>
};
struct shadow_page_state;
-struct shadow_map;
-struct vmm_io_map;
struct emulation_state;
struct v3_intr_state;
-
+struct v3_profiler;
void * vmm_data;
+ uint_t enable_profiler;
+ struct v3_profiler profiler;
+
void * decoder_state;
struct v3_msr guest_efer;
// 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;
-
/*
* This file is part of the Palacios Virtual Machine Monitor developed
* by the V3VEE Project with funding from the United States National
#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)); \
}
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 */
/* ************ */
+/*
+ * 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 <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
#include <palacios/vmm_types.h>
--- /dev/null
+/*
+ * 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 <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * 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 <palacios/vmm_rbtree.h>
+
+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
#include <palacios/vmm_rbtree.h>
+#include <palacios/vmm_profiler.h>
+
extern void v3_stgi();
extern void v3_clgi();
ullong_t tmp_tsc;
uint_t vm_cr_low = 0, vm_cr_high = 0;
-
v3_enable_ints();
v3_clgi();
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));
}
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));
break;
}
+
}
return 0;
}
#include <palacios/vmm_intr.h>
#include <palacios/vmm_emulator.h>
#include <palacios/svm_msr.h>
+#include <palacios/vmm_profiler.h>
-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;
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))) {
}
- // }
- // 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);
// 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)) {
#include <palacios/vmm_debug.h>
#include <palacios/vmm_msr.h>
#include <palacios/vmm_decoder.h>
+#include <palacios/vmm_profiler.h>
+#include <palacios/vmm_mem.h>
#include <devices/serial.h>
#include <devices/keyboard.h>
#include <devices/bochs_debug.h>
+
#include <palacios/vmm_host_events.h>
#define USE_GENERIC 1
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
+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 */
+/*
+ * 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 <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * 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
--- /dev/null
+/*
+ * 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 <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm_types.h>
+#include <palacios/vmm_profiler.h>
+#include <palacios/svm_handler.h>
+#include <palacios/vmm_rbtree.h>
+
+
+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)));
+}
-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);