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.


Minor tweak to fix handling of extensions without initializers
[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)) {
63             PrintError(VM_NONE, VCORE_NONE, "Impossible extension\n");
64             return -1;
65         }
66         
67         if ((*tmp_ext)->init && ((*tmp_ext)->init() != 0)) {
68             PrintError(VM_NONE, VCORE_NONE, "Could not initialize extension (%s)\n", (*tmp_ext)->name);
69             return -1;
70         } 
71
72         V3_Print(VM_NONE, VCORE_NONE, "Registering Extension (%s)\n", (*tmp_ext)->name);
73
74         if (v3_htable_search(ext_table, (addr_t)((*tmp_ext)->name))) {
75             PrintError(VM_NONE, VCORE_NONE, "Multiple instances of Extension (%s)\n", (*tmp_ext)->name);
76             return -1;
77         }
78
79         if (v3_htable_insert(ext_table, (addr_t)((*tmp_ext)->name), (addr_t)(*tmp_ext)) == 0) {
80             PrintError(VM_NONE, VCORE_NONE, "Could not register Extension (%s)\n", (*tmp_ext)->name);
81             return -1;
82         }
83
84         tmp_ext = &(__start__v3_extensions[++i]);
85     }
86
87     return 0;
88 }
89
90
91
92
93 int V3_deinit_extensions() {
94     v3_free_htable(ext_table, 0, 0);
95
96     return 0;
97 }
98
99
100 int v3_init_ext_manager(struct v3_vm_info * vm) {
101     struct v3_extensions * ext_state = &(vm->extensions);
102
103     INIT_LIST_HEAD(&(ext_state->extensions));
104     INIT_LIST_HEAD(&(ext_state->on_exits));
105     INIT_LIST_HEAD(&(ext_state->on_entries));
106     
107     return 0;
108 }
109
110
111 int v3_deinit_ext_manager(struct v3_vm_info * vm)  {
112     struct v3_extensions * ext_state = &(vm->extensions);
113     struct v3_extension * ext = NULL;
114     struct v3_extension * tmp = NULL;
115     int i;
116
117     /* deinit per-core state first */
118     for (i = 0; i < vm->num_cores; i++) 
119         v3_deinit_core_extensions(&(vm->cores[i]));
120
121     list_for_each_entry_safe(ext, tmp, &(ext_state->extensions), node) {
122         
123         V3_Print(vm, VCORE_NONE, "Cleaning up Extension (%s)\n", ext->impl->name);
124         if (ext->impl) { 
125             if (ext->impl->vm_deinit) {
126                 if (ext->impl->vm_deinit(vm, ext->priv_data) == -1) {
127                     PrintError(vm, VCORE_NONE, "Error cleaning up extension (%s)\n", ext->impl->name);
128                     return -1;
129                 }
130             }
131
132             if (ext->impl->on_exit)
133                 list_del(&ext->exit_node);
134             
135             if (ext->impl->on_entry)
136                 list_del(&ext->entry_node);
137         }
138             
139         list_del(&ext->node);
140         V3_Free(ext);
141             
142     }
143
144     return 0;
145 }
146
147
148
149 int v3_add_extension(struct v3_vm_info * vm, const char * name, v3_cfg_tree_t * cfg) {
150     struct v3_extension_impl * impl = NULL;
151     struct v3_extension * ext = NULL;
152     int ext_size;
153
154     impl = (void *)v3_htable_search(ext_table, (addr_t)name);
155
156     if (impl == NULL) {
157         PrintError(vm, VCORE_NONE, "Could not find requested extension (%s)\n", name);
158         return -1;
159     }
160     
161     V3_ASSERT(vm, VCORE_NONE, impl->vm_init);
162
163     /* this allows each extension to track its own per-core state */
164     ext_size = sizeof(struct v3_extension) + (sizeof(void *) * vm->num_cores);
165     ext = V3_Malloc(ext_size);
166     
167     if (!ext) {
168         PrintError(vm, VCORE_NONE,  "Could not allocate extension\n");
169         return -1;
170     }
171
172     ext->impl = impl;
173
174     if (impl->vm_init(vm, cfg, &(ext->priv_data)) == -1) {
175         PrintError(vm, VCORE_NONE,  "Error initializing Extension (%s)\n", name);
176         V3_Free(ext);
177         return -1;
178     }
179
180     list_add(&(ext->node), &(vm->extensions.extensions));
181
182     if (impl->on_exit) {
183         list_add(&(ext->exit_node), &(vm->extensions.on_exits));
184     }
185
186     if (impl->on_entry) {
187         list_add(&(ext->entry_node), &(vm->extensions.on_entries));
188     }
189     
190     return 0;
191 }
192
193 int v3_init_core_extensions(struct guest_info * core) {
194     struct v3_extension * ext = NULL;
195     uint32_t cpuid = core->vcpu_id;
196
197     list_for_each_entry(ext, &(core->vm_info->extensions.extensions), node) {
198         if ((ext->impl) && (ext->impl->core_init)) {
199             if (ext->impl->core_init(core, ext->priv_data, &(ext->core_ext_priv_data[cpuid])) == -1) {
200                 PrintError(core->vm_info, core, "Error configuring per core extension %s on core %d\n", 
201                            ext->impl->name, core->vcpu_id);
202                 return -1;
203             }
204         }
205     }
206
207     return 0;
208 }
209
210
211 int v3_deinit_core_extensions (struct guest_info * core) {
212         struct v3_extension * ext = NULL;
213         struct v3_extension * tmp = NULL;
214         struct v3_vm_info * vm = core->vm_info;
215         uint32_t cpuid = core->vcpu_id;
216
217         list_for_each_entry_safe(ext, tmp, &(vm->extensions.extensions), node) {
218             if ((ext->impl) && (ext->impl->core_deinit)) {
219                 if (ext->impl->core_deinit(core, ext->priv_data, ext->core_ext_priv_data[cpuid]) == -1) {
220                     PrintError(core->vm_info, core, "Error tearing down per core extension %s on core %d\n",
221                                 ext->impl->name, cpuid);
222                     return -1;
223                 }
224             }
225         }
226
227         return 0;
228 }
229
230
231
232 void * v3_get_extension_state(struct v3_vm_info * vm, const char * name) {
233     struct v3_extension * ext = NULL;
234
235     list_for_each_entry(ext, &(vm->extensions.extensions), node) {
236         if (strncmp(ext->impl->name, name, strlen(ext->impl->name)) == 0) {
237             return ext->priv_data;
238         }
239     }
240
241     return NULL;
242 }
243
244
245 void * v3_get_ext_core_state (struct guest_info * core, const char * name) {
246     struct v3_extension * ext = NULL;
247     struct v3_vm_info * vm = core->vm_info;
248     uint32_t cpuid = core->vcpu_id;
249
250     list_for_each_entry(ext, &(vm->extensions.extensions), node) {
251         if (strncmp(ext->impl->name, name, strlen(ext->impl->name)) == 0) {
252             return ext->core_ext_priv_data[cpuid];
253         }
254     }
255
256     return NULL;
257 }
258