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.


Cleanup and sanity-checking of assorted additional issues from second pass (Coverity...
[palacios.git] / palacios / src / palacios / vmm_extensions.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) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, 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 #include <palacios/vmm.h>
21
22 #include <palacios/vmm_extensions.h>
23 #include <palacios/vm_guest.h>
24 #include <palacios/vmm_hashtable.h>
25
26
27 static struct hashtable * ext_table = NULL;
28
29 /*
30  * This is a place holder to ensure that the _v3_extensions section gets created by gcc
31  */
32 static struct {} null_ext  __attribute__((__used__))                    \
33     __attribute__((unused, __section__ ("_v3_extensions"),                \
34                    aligned(sizeof(addr_t))));
35
36
37
38 static uint_t ext_hash_fn(addr_t key) {
39     char * name = (char *)key;
40     return v3_hash_buffer((uint8_t *)name, strlen(name));
41 }
42
43 static int ext_eq_fn(addr_t key1, addr_t key2) {
44     char * name1 = (char *)key1;
45     char * name2 = (char *)key2;
46
47     return (strcmp(name1, name2) == 0);
48 }
49
50
51
52 int V3_init_extensions() {
53     extern struct v3_extension_impl * __start__v3_extensions[];
54     extern struct v3_extension_impl * __stop__v3_extensions[];
55     struct v3_extension_impl ** tmp_ext = __start__v3_extensions;
56     int i = 0;
57
58     ext_table = v3_create_htable(0, ext_hash_fn, ext_eq_fn);
59
60     while (tmp_ext != __stop__v3_extensions) {
61
62         if (!(*tmp_ext) || !(*tmp_ext)->init || ((*tmp_ext)->init() != 0)) {
63             PrintError(VM_NONE, VCORE_NONE, "Could not initialize extension (%s)\n", (*tmp_ext) ? (*tmp_ext)->name : "UNKNOWN");
64             return -1;
65         } 
66
67         V3_Print(VM_NONE, VCORE_NONE, "Registering Extension (%s)\n", (*tmp_ext)->name);
68
69         if (v3_htable_search(ext_table, (addr_t)((*tmp_ext)->name))) {
70             PrintError(VM_NONE, VCORE_NONE, "Multiple instances of Extension (%s)\n", (*tmp_ext)->name);
71             return -1;
72         }
73
74         if (v3_htable_insert(ext_table, (addr_t)((*tmp_ext)->name), (addr_t)(*tmp_ext)) == 0) {
75             PrintError(VM_NONE, VCORE_NONE, "Could not register Extension (%s)\n", (*tmp_ext)->name);
76             return -1;
77         }
78
79         tmp_ext = &(__start__v3_extensions[++i]);
80     }
81
82     return 0;
83 }
84
85
86
87
88 int V3_deinit_extensions() {
89     v3_free_htable(ext_table, 0, 0);
90
91     return 0;
92 }
93
94
95 int v3_init_ext_manager(struct v3_vm_info * vm) {
96     struct v3_extensions * ext_state = &(vm->extensions);
97
98     INIT_LIST_HEAD(&(ext_state->extensions));
99     INIT_LIST_HEAD(&(ext_state->on_exits));
100     INIT_LIST_HEAD(&(ext_state->on_entries));
101     
102     return 0;
103 }
104
105
106 int v3_deinit_ext_manager(struct v3_vm_info * vm)  {
107     struct v3_extensions * ext_state = &(vm->extensions);
108     struct v3_extension * ext = NULL;
109     struct v3_extension * tmp = NULL;
110     int i;
111
112     /* deinit per-core state first */
113     for (i = 0; i < vm->num_cores; i++) 
114         v3_deinit_core_extensions(&(vm->cores[i]));
115
116     list_for_each_entry_safe(ext, tmp, &(ext_state->extensions), node) {
117         
118         V3_Print(vm, VCORE_NONE, "Cleaning up Extension (%s)\n", ext->impl->name);
119         if (ext->impl) { 
120             if (ext->impl->vm_deinit) {
121                 if (ext->impl->vm_deinit(vm, ext->priv_data) == -1) {
122                     PrintError(vm, VCORE_NONE, "Error cleaning up extension (%s)\n", ext->impl->name);
123                     return -1;
124                 }
125             }
126
127             if (ext->impl->on_exit)
128                 list_del(&ext->exit_node);
129             
130             if (ext->impl->on_entry)
131                 list_del(&ext->entry_node);
132         }
133             
134         list_del(&ext->node);
135         V3_Free(ext);
136             
137     }
138
139     return 0;
140 }
141
142
143
144 int v3_add_extension(struct v3_vm_info * vm, const char * name, v3_cfg_tree_t * cfg) {
145     struct v3_extension_impl * impl = NULL;
146     struct v3_extension * ext = NULL;
147     int ext_size;
148
149     impl = (void *)v3_htable_search(ext_table, (addr_t)name);
150
151     if (impl == NULL) {
152         PrintError(vm, VCORE_NONE, "Could not find requested extension (%s)\n", name);
153         return -1;
154     }
155     
156     V3_ASSERT(vm, VCORE_NONE, impl->vm_init);
157
158     /* this allows each extension to track its own per-core state */
159     ext_size = sizeof(struct v3_extension) + (sizeof(void *) * vm->num_cores);
160     ext = V3_Malloc(ext_size);
161     
162     if (!ext) {
163         PrintError(vm, VCORE_NONE,  "Could not allocate extension\n");
164         return -1;
165     }
166
167     ext->impl = impl;
168
169     if (impl->vm_init(vm, cfg, &(ext->priv_data)) == -1) {
170         PrintError(vm, VCORE_NONE,  "Error initializing Extension (%s)\n", name);
171         V3_Free(ext);
172         return -1;
173     }
174
175     list_add(&(ext->node), &(vm->extensions.extensions));
176
177     if (impl->on_exit) {
178         list_add(&(ext->exit_node), &(vm->extensions.on_exits));
179     }
180
181     if (impl->on_entry) {
182         list_add(&(ext->entry_node), &(vm->extensions.on_entries));
183     }
184     
185     return 0;
186 }
187
188 int v3_init_core_extensions(struct guest_info * core) {
189     struct v3_extension * ext = NULL;
190     uint32_t cpuid = core->vcpu_id;
191
192     list_for_each_entry(ext, &(core->vm_info->extensions.extensions), node) {
193         if ((ext->impl) && (ext->impl->core_init)) {
194             if (ext->impl->core_init(core, ext->priv_data, &(ext->core_ext_priv_data[cpuid])) == -1) {
195                 PrintError(core->vm_info, core, "Error configuring per core extension %s on core %d\n", 
196                            ext->impl->name, core->vcpu_id);
197                 return -1;
198             }
199         }
200     }
201
202     return 0;
203 }
204
205
206 int v3_deinit_core_extensions (struct guest_info * core) {
207         struct v3_extension * ext = NULL;
208         struct v3_extension * tmp = NULL;
209         struct v3_vm_info * vm = core->vm_info;
210         uint32_t cpuid = core->vcpu_id;
211
212         list_for_each_entry_safe(ext, tmp, &(vm->extensions.extensions), node) {
213             if ((ext->impl) && (ext->impl->core_deinit)) {
214                 if (ext->impl->core_deinit(core, ext->priv_data, ext->core_ext_priv_data[cpuid]) == -1) {
215                     PrintError(core->vm_info, core, "Error tearing down per core extension %s on core %d\n",
216                                 ext->impl->name, cpuid);
217                     return -1;
218                 }
219             }
220         }
221
222         return 0;
223 }
224
225
226
227 void * v3_get_extension_state(struct v3_vm_info * vm, const char * name) {
228     struct v3_extension * ext = NULL;
229
230     list_for_each_entry(ext, &(vm->extensions.extensions), node) {
231         if (strncmp(ext->impl->name, name, strlen(ext->impl->name)) == 0) {
232             return ext->priv_data;
233         }
234     }
235
236     return NULL;
237 }
238
239
240 void * v3_get_ext_core_state (struct guest_info * core, const char * name) {
241     struct v3_extension * ext = NULL;
242     struct v3_vm_info * vm = core->vm_info;
243     uint32_t cpuid = core->vcpu_id;
244
245     list_for_each_entry(ext, &(vm->extensions.extensions), node) {
246         if (strncmp(ext->impl->name, name, strlen(ext->impl->name)) == 0) {
247             return ext->core_ext_priv_data[cpuid];
248         }
249     }
250
251     return NULL;
252 }
253