2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm_types.h>
21 #include <palacios/vmm_profiler.h>
22 #include <palacios/svm_handler.h>
23 #include <palacios/vmm_rbtree.h>
31 struct rb_node tree_node;
35 void v3_init_profiler(struct guest_info * info) {
36 info->profiler.total_exits = 0;
38 info->profiler.start_time = 0;
39 info->profiler.end_time = 0;
41 info->profiler.root.rb_node = NULL;
46 static inline struct exit_event * __insert_event(struct guest_info * info,
47 struct exit_event * evt) {
48 struct rb_node ** p = &(info->profiler.root.rb_node);
49 struct rb_node * parent = NULL;
50 struct exit_event * tmp_evt = NULL;
54 tmp_evt = rb_entry(parent, struct exit_event, tree_node);
56 if (evt->exit_code < tmp_evt->exit_code) {
58 } else if (evt->exit_code > tmp_evt->exit_code) {
64 rb_link_node(&(evt->tree_node), parent, p);
69 static inline struct exit_event * insert_event(struct guest_info * info,
70 struct exit_event * evt) {
71 struct exit_event * ret;
73 if ((ret = __insert_event(info, evt))) {
77 v3_rb_insert_color(&(evt->tree_node), &(info->profiler.root));
83 static struct exit_event * get_exit(struct guest_info * info, uint_t exit_code) {
84 struct rb_node * n = info->profiler.root.rb_node;
85 struct exit_event * evt = NULL;
88 evt = rb_entry(n, struct exit_event, tree_node);
90 if (exit_code < evt->exit_code) {
92 } else if (exit_code > evt->exit_code) {
103 static inline struct exit_event * create_exit(uint_t exit_code) {
104 struct exit_event * evt = V3_Malloc(sizeof(struct exit_event));
106 evt->exit_code = exit_code;
108 evt->handler_time = 0;
113 void v3_profile_exit(struct guest_info * info, uint_t exit_code) {
114 uint_t time = (info->profiler.end_time - info->profiler.start_time);
115 struct exit_event * evt = get_exit(info, exit_code);
118 evt = create_exit(exit_code);
119 insert_event(info, evt);
122 evt->handler_time += time;
125 info->profiler.total_exits++;
129 void v3_print_profile(struct guest_info * info) {
130 struct exit_event * evt = NULL;
131 struct rb_node * node = v3_rb_first(&(info->profiler.root));
134 evt = rb_entry(node, struct exit_event, tree_node);
135 const char * code_str = vmexit_code_to_str(evt->exit_code);
137 PrintDebug("%s:%sCnt=%u,%sTime=%u\n",
139 (strlen(code_str) > 14) ? "\t" : "\t\t",
141 (evt->exit_count >= 100) ? "\t" : "\t\t",
144 } while ((node = v3_rb_next(node)));