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;
40 info->profiler.guest_pf_cnt = 0;
42 info->profiler.root.rb_node = NULL;
47 static inline struct exit_event * __insert_event(struct guest_info * info,
48 struct exit_event * evt) {
49 struct rb_node ** p = &(info->profiler.root.rb_node);
50 struct rb_node * parent = NULL;
51 struct exit_event * tmp_evt = NULL;
55 tmp_evt = rb_entry(parent, struct exit_event, tree_node);
57 if (evt->exit_code < tmp_evt->exit_code) {
59 } else if (evt->exit_code > tmp_evt->exit_code) {
65 rb_link_node(&(evt->tree_node), parent, p);
70 static inline struct exit_event * insert_event(struct guest_info * info,
71 struct exit_event * evt) {
72 struct exit_event * ret;
74 if ((ret = __insert_event(info, evt))) {
78 v3_rb_insert_color(&(evt->tree_node), &(info->profiler.root));
84 static struct exit_event * get_exit(struct guest_info * info, uint_t exit_code) {
85 struct rb_node * n = info->profiler.root.rb_node;
86 struct exit_event * evt = NULL;
89 evt = rb_entry(n, struct exit_event, tree_node);
91 if (exit_code < evt->exit_code) {
93 } else if (exit_code > evt->exit_code) {
104 static inline struct exit_event * create_exit(uint_t exit_code) {
105 struct exit_event * evt = V3_Malloc(sizeof(struct exit_event));
107 evt->exit_code = exit_code;
109 evt->handler_time = 0;
114 void v3_profile_exit(struct guest_info * info, uint_t exit_code) {
115 uint_t time = (info->profiler.end_time - info->profiler.start_time);
116 struct exit_event * evt = get_exit(info, exit_code);
119 evt = create_exit(exit_code);
120 insert_event(info, evt);
125 evt->handler_time = (evt->handler_time * .99) + (time * .01);
130 info->profiler.total_exits++;
134 void v3_print_profile(struct guest_info * info) {
135 struct exit_event * evt = NULL;
136 struct rb_node * node = v3_rb_first(&(info->profiler.root));
138 PrintDebug("GUEST_PF: %u\n", info->profiler.guest_pf_cnt);
141 evt = rb_entry(node, struct exit_event, tree_node);
142 const char * code_str = vmexit_code_to_str(evt->exit_code);
144 PrintDebug("%s:%sCnt=%u,%sTime=%u\n",
146 (strlen(code_str) > 14) ? "\t" : "\t\t",
148 (evt->exit_count >= 100) ? "\t" : "\t\t",
151 } while ((node = v3_rb_next(node)));