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.


Add HVM configuration capability, init/deinit, etc
[palacios.git] / palacios / src / palacios / vmm_symmod.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 #include <palacios/vmm.h>
20 #include <palacios/vmm_symmod.h>
21 #include <palacios/vmm_symbiotic.h>
22 #include <palacios/vm_guest.h>
23 #include <palacios/vmm_list.h>
24
25 static struct hashtable * capsule_table = NULL;
26 static LIST_HEAD(capsule_list);
27
28
29 /* 
30  * This is a place holder to ensure that the _v3_modules section gets created by gcc
31  */
32 static struct {} null_mod  __attribute__((__used__))                    \
33     __attribute__((unused, __section__ ("_v3_capsules"),                \
34                    aligned(sizeof(addr_t))));
35
36 static uint_t mod_hash_fn(addr_t key) {
37     char * name = (char *)key;
38     return v3_hash_buffer((uchar_t *)name, strlen(name));
39 }
40
41 static int mod_eq_fn(addr_t key1, addr_t key2) {
42     char * name1 = (char *)key1;
43     char * name2 = (char *)key2;
44     
45     return (strcmp(name1, name2) == 0);
46 }
47
48
49 struct capsule_def {
50     char * name;
51     addr_t start_addr;
52     addr_t end_addr;
53     uint32_t flags; // see 'struct v3_symmod_flags'
54 } __attribute__((packed));
55
56
57
58 int V3_init_symmod() {
59     extern struct capsule_def __start__v3_capsules[];
60     extern struct capsule_def __stop__v3_capsules[];
61     struct capsule_def * tmp_def = __start__v3_capsules;
62     int i = 0;
63
64     if (tmp_def == __stop__v3_capsules) {
65         PrintDebug(VM_NONE, VCORE_NONE, "No Symbiotic capsules found\n");
66         return 0;
67     }
68
69     capsule_table = v3_create_htable(0, mod_hash_fn, mod_eq_fn);
70
71     while (tmp_def != __stop__v3_capsules) {
72         struct v3_sym_capsule * capsule = NULL;
73
74         if (v3_htable_search(capsule_table, (addr_t)(tmp_def->name))) {
75             PrintError(VM_NONE, VCORE_NONE, "Multiple instances of Module (%s)\n", tmp_def->name);
76             return -1;
77         }
78         
79
80         capsule = V3_Malloc(sizeof(struct v3_sym_capsule));
81
82         if (!capsule) {
83             PrintError(VM_NONE, VCORE_NONE, "Cannot allocate in initializing symmod\n");
84             return -1;
85         }
86
87
88         memset(capsule, 0, sizeof(struct v3_sym_capsule));
89
90         capsule->name = tmp_def->name;
91         capsule->start_addr = (void *)(tmp_def->start_addr);
92         capsule->size = tmp_def->end_addr - tmp_def->start_addr;
93         capsule->flags = tmp_def->flags;
94         
95         
96
97         if (capsule->type == V3_SYMMOD_MOD) {
98             // parse module
99             // capsule->capsule_data = v3_sym_module...
100             // capsule->guest_size = size of linked module
101         } else if (capsule->type == V3_SYMMOD_LNX) {
102             capsule->guest_size = capsule->size;
103             capsule->capsule_data = NULL;
104         } else {
105             V3_Free(capsule);
106             return -1;
107         }
108
109         PrintDebug(VM_NONE, VCORE_NONE, "Registering Symbiotic Module (%s)\n", tmp_def->name);
110
111         if (v3_htable_insert(capsule_table, 
112                              (addr_t)(tmp_def->name),
113                              (addr_t)(capsule)) == 0) {
114             PrintError(VM_NONE, VCORE_NONE, "Could not insert module %s to master list\n", tmp_def->name);
115             V3_Free(capsule);
116             return -1;
117         }
118
119         list_add(&(capsule->node), &capsule_list);
120
121         tmp_def = &(__start__v3_capsules[++i]);
122     }
123     
124     return 0;
125 }
126
127 int V3_deinit_symmod() {
128     v3_free_htable(capsule_table, 1, 0);    
129
130     return 0;
131 }
132
133 /* ***************** */
134 /* Linkage functions */
135 /* ***************** */
136
137
138 /* Data structure containing symbols exported via the symbiotic interface */
139 struct v3_symbol_def32 {
140     uint32_t name_gva;
141     uint32_t value;
142 } __attribute__((packed));
143
144 struct v3_symbol_def64 {
145     uint64_t name_gva;
146     uint64_t value;
147 } __attribute__((packed));
148
149
150
151 struct v3_symbol {
152     char name[256];
153     uint64_t linkage;
154
155     struct list_head sym_node;
156 };
157
158
159
160 #include <palacios/vm_guest_mem.h>
161
162 static int symbol_hcall_handler(struct guest_info * core, hcall_id_t hcall_id, void * priv_data) {
163     struct v3_symmod_state * symmod_state = &(core->vm_info->sym_vm_state.symmod_state);
164     addr_t sym_start_gva = core->vm_regs.rbx;
165     uint32_t sym_size = core->vm_regs.rcx;
166
167     int i = 0;
168
169     PrintError(core->vm_info, core, "Received SYMMOD symbol tables addr=%p, size=%d\n", (void *)sym_start_gva, sym_size);
170
171     for (i = 0; i < sym_size; i++) {
172         char * sym_name = NULL;
173         struct v3_symbol_def32 * tmp_symbol = NULL;
174         struct v3_symbol * new_symbol = NULL;
175         addr_t sym_gva = sym_start_gva + (sizeof(struct v3_symbol_def32) * i);
176
177
178         if (v3_gva_to_hva(core, sym_gva, (addr_t *)&(tmp_symbol)) == -1) {
179             PrintError(core->vm_info, core, "Could not locate symbiotic symbol definition\n");
180             continue;
181         }
182         
183         if (v3_gva_to_hva(core, tmp_symbol->name_gva, (addr_t *)&(sym_name)) == -1) {
184             PrintError(core->vm_info, core, "Could not locate symbiotic symbol name\n");
185             continue;
186         }
187         
188         PrintError(core->vm_info, core, "Symbiotic Symbol (%s) at %p\n", sym_name, (void *)(addr_t)tmp_symbol->value);
189         
190         new_symbol = (struct v3_symbol *)V3_Malloc(sizeof(struct v3_symbol));
191
192         if (!new_symbol) {
193             PrintError(core->vm_info, core, "Cannot allocate in symbiotic hcall handler\n");
194             return -1;
195         }
196
197         strncpy(new_symbol->name, sym_name, 256);
198         new_symbol->linkage = tmp_symbol->value;
199
200         list_add(&(new_symbol->sym_node), &(symmod_state->v3_sym_list));
201     }
202
203     return 0;
204 }
205
206
207 int v3_init_symmod_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
208     struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
209     struct v3_symspy_global_page * sym_page = v3_sym_get_symspy_vm(vm);
210     struct v3_sym_capsule * tmp_capsule = NULL;
211
212     symmod_state->capsule_table = v3_create_htable(0, mod_hash_fn, mod_eq_fn);
213
214
215     // Add modules to local hash table, should be keyed to config
216     list_for_each_entry(tmp_capsule, &capsule_list, node) {
217         V3_Print(vm, VCORE_NONE, "Adding %s to local module table\n", tmp_capsule->name);
218         if (v3_htable_insert(symmod_state->capsule_table, 
219                              (addr_t)(tmp_capsule->name),
220                              (addr_t)(tmp_capsule)) == 0) {
221             PrintError(vm, VCORE_NONE, "Could not insert module %s to vm local list\n", tmp_capsule->name);
222             return -1;
223         }
224         symmod_state->num_avail_capsules++;
225     }
226
227     symmod_state->num_loaded_capsules = 0;
228     sym_page->symmod_enabled = 1;
229
230     v3_register_hypercall(vm, SYMMOD_SYMS_HCALL, symbol_hcall_handler, NULL);
231
232     INIT_LIST_HEAD(&(symmod_state->v3_sym_list));
233
234     V3_Print(vm, VCORE_NONE, "Symmod initialized\n");
235
236     return 0;
237 }
238
239 int v3_deinit_symmod_vm(struct v3_vm_info * vm) {
240     struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
241     struct v3_symbol * sym = NULL;
242     struct v3_symbol * tmp_sym = NULL;
243
244     v3_remove_hypercall(vm, SYMMOD_SYMS_HCALL);
245
246     v3_free_htable(symmod_state->capsule_table, 0, 0);
247
248     list_for_each_entry_safe(sym, tmp_sym, &(symmod_state->v3_sym_list), sym_node) {
249         list_del(&(sym->sym_node));
250         V3_Free(sym);
251     }
252
253     return 0;
254 }
255
256
257 int v3_set_symmod_loader(struct v3_vm_info * vm, struct v3_symmod_loader_ops * ops, void * priv_data) {
258     struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
259    
260     symmod_state->loader_ops = ops;
261     symmod_state->loader_data = priv_data;
262  
263     return 0;
264 }
265
266
267
268
269
270 int v3_load_sym_capsule(struct v3_vm_info * vm, char * name) {
271     struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
272     struct v3_sym_capsule * capsule = (struct v3_sym_capsule *)v3_htable_search(capsule_table, (addr_t)name);
273
274     if (!capsule) {
275         PrintError(vm, VCORE_NONE, "Could not find capsule %s\n", name);
276         return -1;
277     }
278
279     PrintDebug(vm, VCORE_NONE, "Loading Capsule (%s)\n", name);
280
281     return symmod_state->loader_ops->load_capsule(vm, capsule, symmod_state->loader_data);
282 }
283
284
285
286 struct list_head * v3_get_sym_capsule_list() {
287     return &(capsule_list);
288 }
289
290
291 struct v3_sym_capsule * v3_get_sym_capsule(struct v3_vm_info * vm, char * name) {
292     struct v3_sym_capsule * mod = (struct v3_sym_capsule *)v3_htable_search(capsule_table, (addr_t)name);
293
294     if (!mod) {
295         PrintError(vm, VCORE_NONE, "Could not find module %s\n", name);
296         return NULL;
297     }
298
299     return mod;
300 }