Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


8093faef81db3cbfea31b8e1f1f26a1b1de7bd6b
[palacios.git] / palacios / src / palacios / vmm_exits.c
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2012, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2012, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_exits.h>
23 #include <palacios/vm_guest.h>
24
25
26 int v3_init_exit_hooks(struct v3_vm_info * vm) {
27     struct v3_exit_map * map = &(vm->exit_map);
28     
29     map->exits = V3_Malloc(sizeof(struct v3_exit_hook) * V3_EXIT_INVALID);
30
31     if (map->exits == NULL) {
32         PrintError("Error allocating exit map\n");
33         return -1;
34     }
35     
36     memset(map->exits, 0, sizeof(struct v3_exit_hook) * V3_EXIT_INVALID);
37
38
39     return 0;
40 }
41
42 int v3_deinit_exit_hooks(struct v3_vm_info * vm) {
43     struct v3_exit_map * map = &(vm->exit_map);
44
45     V3_Free(map->exits);
46
47     return 0;
48 }
49
50
51
52
53 int v3_init_exit_hooks_core(struct guest_info * core) {
54     struct v3_vm_info * vm = core->vm_info;
55     struct v3_exit_map * map = &(vm->exit_map);  
56     struct v3_exit_hook * hook = NULL;
57     int i = 0;
58
59     for (i = 0; i < V3_EXIT_INVALID; i++) {
60         hook = &(map->exits[i]);
61
62         if (hook->hooked) {
63             if (hook->enable(core, i) != 0) {
64                 PrintError("Error could not enable exit hook %d on core %d\n", i, core->vcpu_id);
65                 return -1;
66             }
67         }
68     }
69
70     return 0;
71 }
72
73 int v3_deinit_exit_hooks_core(struct guest_info * core) {
74
75     return 0;
76 }
77
78
79
80 int v3_dispatch_exit_hook(struct guest_info * core, v3_exit_type_t exit_type, void * exit_data) {
81     struct v3_exit_map * map = &(core->vm_info->exit_map);       
82     struct v3_exit_hook * hook = NULL;
83
84     if (exit_type >= V3_EXIT_INVALID) {
85         PrintError("Error: Tried to dispatch invalid exit type (%d)\n", exit_type);
86         return -1;
87     }
88   
89     hook = &(map->exits[exit_type]);
90
91     if (hook->hooked == 0) {
92         PrintError("Tried to dispatch an unhooked exit (%d)\n", exit_type);
93         return -1;
94     }
95
96     return hook->handler(core, exit_type, hook->priv_data, exit_data);
97    
98 }
99
100
101 int v3_register_exit(struct v3_vm_info * vm, v3_exit_type_t exit_type,
102                      int (*enable)(struct guest_info * core, v3_exit_type_t exit_type),
103                      int (*disable)(struct guest_info * core, v3_exit_type_t exit_type)) {
104     struct v3_exit_map * map = &(vm->exit_map);  
105     struct v3_exit_hook * hook = NULL;
106
107     if (exit_type >= V3_EXIT_INVALID) {
108         PrintError("Error: Tried to register invalid exit type (%d)\n", exit_type);
109         return -1;
110     }
111   
112     hook = &(map->exits[exit_type]);
113
114     if (hook->registered == 1) {
115         PrintError("Tried to reregister an exit (%d)\n", exit_type);
116         return -1;
117     }
118
119     hook->registered = 1;
120     hook->enable = enable;
121     hook->disable = disable;
122     
123
124     return 0;
125 }
126
127
128 int v3_hook_exit(struct v3_vm_info * vm, v3_exit_type_t exit_type,
129                  int (*handler)(struct guest_info * core, v3_exit_type_t exit_type, 
130                              void * priv_data, void * exit_data),
131                  void * priv_data, 
132                  struct guest_info * current_core) {
133     struct v3_exit_map * map = &(vm->exit_map);  
134     struct v3_exit_hook * hook = NULL;
135     
136     
137     if (exit_type >= V3_EXIT_INVALID) {
138         PrintError("Error: Tried to hook invalid exit type (%d)\n", exit_type);
139         return -1;
140     }
141   
142     hook = &(map->exits[exit_type]);
143
144     if (hook->registered == 0) {
145         PrintError("Tried to hook unregistered exit (%d)\n", exit_type);
146         return -1;
147     } 
148
149     if (hook->hooked != 0) {
150         PrintError("Tried to rehook exit (%d)\n", exit_type);
151         return -1;
152     }
153
154
155     hook->hooked = 1;
156     hook->handler = handler;
157     hook->priv_data = priv_data;
158
159     if ((vm->run_state == VM_RUNNING) || 
160         (vm->run_state == VM_SIMULATING)) {
161         int i = 0;
162
163         while (v3_raise_barrier(vm, current_core) == -1);
164         
165         for (i = 0; i < vm->num_cores; i++) {
166             
167             if (hook->enable(&(vm->cores[i]), exit_type) != 0) {
168                 PrintError("Error could not enable exit hook %d on core %d\n", exit_type, i);
169                 v3_lower_barrier(vm);
170                 return -1;
171             }   
172         }
173
174         v3_lower_barrier(vm);
175     }
176     
177     return 0;
178 }
179
180
181
182 int v3_unhook_exit(struct v3_vm_info * vm, v3_exit_type_t exit_type, struct guest_info * current_core) {
183     struct v3_exit_map * map = &(vm->exit_map);  
184     struct v3_exit_hook * hook = NULL;
185     
186     
187     if (exit_type >= V3_EXIT_INVALID) {
188         PrintError("Error: Tried to unhook invalid exit type (%d)\n", exit_type);
189         return -1;
190     }
191   
192     hook = &(map->exits[exit_type]);
193
194     if (hook->registered == 0) {
195         PrintError("Tried to unhook an unregistered exit (%d)\n", exit_type);
196         return -1;
197     } 
198
199     if (hook->hooked == 0) {
200         PrintError("Tried to unhook and unhooked exit (%d)\n", exit_type);
201         return -1;
202     }
203
204
205     hook->hooked = 0;
206     hook->handler = NULL;
207     hook->priv_data = NULL;
208
209     
210     if ((vm->run_state == VM_RUNNING) || 
211         (vm->run_state == VM_SIMULATING)) {
212         int i = 0;
213
214         while (v3_raise_barrier(vm, current_core) == -1);
215         
216         for (i = 0; i < vm->num_cores; i++) {
217             
218             if (hook->disable(&(vm->cores[i]), exit_type) != 0) {
219                 PrintError("Error could not enable exit hook %d on core %d\n", exit_type, i);
220                 v3_lower_barrier(vm);
221                 return -1;
222             }   
223         }
224
225         v3_lower_barrier(vm);
226     }
227     
228     return 0;
229 }