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.


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