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.


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