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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
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.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
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>
25 static struct hashtable * capsule_table = NULL;
26 static LIST_HEAD(capsule_list);
30 * This is a place holder to ensure that the _v3_modules section gets created by gcc
32 static struct {} null_mod __attribute__((__used__)) \
33 __attribute__((unused, __section__ ("_v3_capsules"), \
34 aligned(sizeof(addr_t))));
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));
41 static int mod_eq_fn(addr_t key1, addr_t key2) {
42 char * name1 = (char *)key1;
43 char * name2 = (char *)key2;
45 return (strcmp(name1, name2) == 0);
53 uint32_t flags; // see 'struct v3_symmod_flags'
54 } __attribute__((packed));
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;
64 if (tmp_def == __stop__v3_capsules) {
65 PrintDebug(VM_NONE, VCORE_NONE, "No Symbiotic capsules found\n");
69 capsule_table = v3_create_htable(0, mod_hash_fn, mod_eq_fn);
71 while (tmp_def != __stop__v3_capsules) {
72 struct v3_sym_capsule * capsule = NULL;
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);
80 capsule = V3_Malloc(sizeof(struct v3_sym_capsule));
83 PrintError(VM_NONE, VCORE_NONE, "Cannot allocate in initializing symmod\n");
88 memset(capsule, 0, sizeof(struct v3_sym_capsule));
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;
97 if (capsule->type == V3_SYMMOD_MOD) {
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;
109 PrintDebug(VM_NONE, VCORE_NONE, "Registering Symbiotic Module (%s)\n", tmp_def->name);
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);
119 list_add(&(capsule->node), &capsule_list);
121 tmp_def = &(__start__v3_capsules[++i]);
127 int V3_deinit_symmod() {
128 v3_free_htable(capsule_table, 1, 0);
133 /* ***************** */
134 /* Linkage functions */
135 /* ***************** */
138 /* Data structure containing symbols exported via the symbiotic interface */
139 struct v3_symbol_def32 {
142 } __attribute__((packed));
144 struct v3_symbol_def64 {
147 } __attribute__((packed));
155 struct list_head sym_node;
160 #include <palacios/vm_guest_mem.h>
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;
169 PrintError(core->vm_info, core, "Received SYMMOD symbol tables addr=%p, size=%d\n", (void *)sym_start_gva, sym_size);
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);
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");
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");
188 PrintError(core->vm_info, core, "Symbiotic Symbol (%s) at %p\n", sym_name, (void *)(addr_t)tmp_symbol->value);
190 new_symbol = (struct v3_symbol *)V3_Malloc(sizeof(struct v3_symbol));
193 PrintError(core->vm_info, core, "Cannot allocate in symbiotic hcall handler\n");
197 strncpy(new_symbol->name, sym_name, 256);
198 new_symbol->name[255] = 0;
199 new_symbol->linkage = tmp_symbol->value;
201 list_add(&(new_symbol->sym_node), &(symmod_state->v3_sym_list));
208 int v3_init_symmod_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
209 struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
210 struct v3_symspy_global_page * sym_page = v3_sym_get_symspy_vm(vm);
211 struct v3_sym_capsule * tmp_capsule = NULL;
213 symmod_state->capsule_table = v3_create_htable(0, mod_hash_fn, mod_eq_fn);
216 // Add modules to local hash table, should be keyed to config
217 list_for_each_entry(tmp_capsule, &capsule_list, node) {
218 V3_Print(vm, VCORE_NONE, "Adding %s to local module table\n", tmp_capsule->name);
219 if (v3_htable_insert(symmod_state->capsule_table,
220 (addr_t)(tmp_capsule->name),
221 (addr_t)(tmp_capsule)) == 0) {
222 PrintError(vm, VCORE_NONE, "Could not insert module %s to vm local list\n", tmp_capsule->name);
225 symmod_state->num_avail_capsules++;
228 symmod_state->num_loaded_capsules = 0;
229 sym_page->symmod_enabled = 1;
231 v3_register_hypercall(vm, SYMMOD_SYMS_HCALL, symbol_hcall_handler, NULL);
233 INIT_LIST_HEAD(&(symmod_state->v3_sym_list));
235 V3_Print(vm, VCORE_NONE, "Symmod initialized\n");
240 int v3_deinit_symmod_vm(struct v3_vm_info * vm) {
241 struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
242 struct v3_symbol * sym = NULL;
243 struct v3_symbol * tmp_sym = NULL;
245 v3_remove_hypercall(vm, SYMMOD_SYMS_HCALL);
247 v3_free_htable(symmod_state->capsule_table, 0, 0);
249 list_for_each_entry_safe(sym, tmp_sym, &(symmod_state->v3_sym_list), sym_node) {
250 list_del(&(sym->sym_node));
258 int v3_set_symmod_loader(struct v3_vm_info * vm, struct v3_symmod_loader_ops * ops, void * priv_data) {
259 struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
261 symmod_state->loader_ops = ops;
262 symmod_state->loader_data = priv_data;
271 int v3_load_sym_capsule(struct v3_vm_info * vm, char * name) {
272 struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
273 struct v3_sym_capsule * capsule = (struct v3_sym_capsule *)v3_htable_search(capsule_table, (addr_t)name);
276 PrintError(vm, VCORE_NONE, "Could not find capsule %s\n", name);
280 PrintDebug(vm, VCORE_NONE, "Loading Capsule (%s)\n", name);
282 return symmod_state->loader_ops->load_capsule(vm, capsule, symmod_state->loader_data);
287 struct list_head * v3_get_sym_capsule_list() {
288 return &(capsule_list);
292 struct v3_sym_capsule * v3_get_sym_capsule(struct v3_vm_info * vm, char * name) {
293 struct v3_sym_capsule * mod = (struct v3_sym_capsule *)v3_htable_search(capsule_table, (addr_t)name);
296 PrintError(vm, VCORE_NONE, "Could not find module %s\n", name);