X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_extensions.c;h=af2c0e2756408210a55b6473d05e529b66137ce0;hp=defad8f68145ec1fe0385203a553f67bd658b036;hb=88a3605446744969abe6f193a7bc20e62d5aa555;hpb=a8627ddaccf49073eb04286c5ea4767e2903c351 diff --git a/palacios/src/palacios/vmm_extensions.c b/palacios/src/palacios/vmm_extensions.c index defad8f..af2c0e2 100644 --- a/palacios/src/palacios/vmm_extensions.c +++ b/palacios/src/palacios/vmm_extensions.c @@ -26,6 +26,14 @@ static struct hashtable * ext_table = NULL; +/* + * This is a place holder to ensure that the _v3_extensions section gets created by gcc + */ +static struct {} null_ext __attribute__((__used__)) \ + __attribute__((unused, __section__ ("_v3_extensions"), \ + aligned(sizeof(addr_t)))); + + static uint_t ext_hash_fn(addr_t key) { char * name = (char *)key; @@ -50,15 +58,21 @@ int V3_init_extensions() { ext_table = v3_create_htable(0, ext_hash_fn, ext_eq_fn); while (tmp_ext != __stop__v3_extensions) { - V3_Print("Registering Extension (%s)\n", (*tmp_ext)->name); + + if ((*tmp_ext) && (*tmp_ext)->init && ((*tmp_ext)->init() != 0)) { + PrintError(VM_NONE, VCORE_NONE, "Could not initialize extension (%s)\n", (*tmp_ext)->name); + return -1; + } + + V3_Print(VM_NONE, VCORE_NONE, "Registering Extension (%s)\n", (*tmp_ext)->name); if (v3_htable_search(ext_table, (addr_t)((*tmp_ext)->name))) { - PrintError("Multiple instances of Extension (%s)\n", (*tmp_ext)->name); + PrintError(VM_NONE, VCORE_NONE, "Multiple instances of Extension (%s)\n", (*tmp_ext)->name); return -1; } if (v3_htable_insert(ext_table, (addr_t)((*tmp_ext)->name), (addr_t)(*tmp_ext)) == 0) { - PrintError("Could not register Extension (%s)\n", (*tmp_ext)->name); + PrintError(VM_NONE, VCORE_NONE, "Could not register Extension (%s)\n", (*tmp_ext)->name); return -1; } @@ -73,6 +87,7 @@ int V3_init_extensions() { int V3_deinit_extensions() { v3_free_htable(ext_table, 0, 0); + return 0; } @@ -89,9 +104,39 @@ int v3_init_ext_manager(struct v3_vm_info * vm) { int v3_deinit_ext_manager(struct v3_vm_info * vm) { + struct v3_extensions * ext_state = &(vm->extensions); + struct v3_extension * ext = NULL; + struct v3_extension * tmp = NULL; + int i; + + /* deinit per-core state first */ + for (i = 0; i < vm->num_cores; i++) + v3_deinit_core_extensions(&(vm->cores[i])); + + list_for_each_entry_safe(ext, tmp, &(ext_state->extensions), node) { + + V3_Print(vm, VCORE_NONE, "Cleaning up Extension (%s)\n", ext->impl->name); + if (ext->impl) { + if (ext->impl->vm_deinit) { + if (ext->impl->vm_deinit(vm, ext->priv_data) == -1) { + PrintError(vm, VCORE_NONE, "Error cleaning up extension (%s)\n", ext->impl->name); + return -1; + } + } - PrintError("I should really do something here... \n"); - return -1; + if (ext->impl->on_exit) + list_del(&ext->exit_node); + + if (ext->impl->on_entry) + list_del(&ext->entry_node); + } + + list_del(&ext->node); + V3_Free(ext); + + } + + return 0; } @@ -99,27 +144,30 @@ int v3_deinit_ext_manager(struct v3_vm_info * vm) { int v3_add_extension(struct v3_vm_info * vm, const char * name, v3_cfg_tree_t * cfg) { struct v3_extension_impl * impl = NULL; struct v3_extension * ext = NULL; + int ext_size; impl = (void *)v3_htable_search(ext_table, (addr_t)name); if (impl == NULL) { - PrintError("Could not find requested extension (%s)\n", name); + PrintError(vm, VCORE_NONE, "Could not find requested extension (%s)\n", name); return -1; } - V3_ASSERT(impl->init); + V3_ASSERT(vm, VCORE_NONE, impl->vm_init); - ext = V3_Malloc(sizeof(struct v3_extension)); + /* this allows each extension to track its own per-core state */ + ext_size = sizeof(struct v3_extension) + (sizeof(void *) * vm->num_cores); + ext = V3_Malloc(ext_size); if (!ext) { - PrintError("Could not allocate extension\n"); + PrintError(vm, VCORE_NONE, "Could not allocate extension\n"); return -1; } ext->impl = impl; - if (impl->init(vm, cfg, &(ext->priv_data)) == -1) { - PrintError("Error initializing Extension (%s)\n", name); + if (impl->vm_init(vm, cfg, &(ext->priv_data)) == -1) { + PrintError(vm, VCORE_NONE, "Error initializing Extension (%s)\n", name); V3_Free(ext); return -1; } @@ -139,11 +187,12 @@ int v3_add_extension(struct v3_vm_info * vm, const char * name, v3_cfg_tree_t * int v3_init_core_extensions(struct guest_info * core) { struct v3_extension * ext = NULL; + uint32_t cpuid = core->vcpu_id; list_for_each_entry(ext, &(core->vm_info->extensions.extensions), node) { if ((ext->impl) && (ext->impl->core_init)) { - if (ext->impl->core_init(core, ext->priv_data) == -1) { - PrintError("Error configuring per core extension %s on core %d\n", + if (ext->impl->core_init(core, ext->priv_data, &(ext->core_ext_priv_data[cpuid])) == -1) { + PrintError(core->vm_info, core, "Error configuring per core extension %s on core %d\n", ext->impl->name, core->vcpu_id); return -1; } @@ -154,6 +203,25 @@ int v3_init_core_extensions(struct guest_info * core) { } +int v3_deinit_core_extensions (struct guest_info * core) { + struct v3_extension * ext = NULL; + struct v3_extension * tmp = NULL; + struct v3_vm_info * vm = core->vm_info; + uint32_t cpuid = core->vcpu_id; + + list_for_each_entry_safe(ext, tmp, &(vm->extensions.extensions), node) { + if ((ext->impl) && (ext->impl->core_deinit)) { + if (ext->impl->core_deinit(core, ext->priv_data, ext->core_ext_priv_data[cpuid]) == -1) { + PrintError(core->vm_info, core, "Error tearing down per core extension %s on core %d\n", + ext->impl->name, cpuid); + return -1; + } + } + } + + return 0; +} + void * v3_get_extension_state(struct v3_vm_info * vm, const char * name) { @@ -167,3 +235,19 @@ void * v3_get_extension_state(struct v3_vm_info * vm, const char * name) { return NULL; } + + +void * v3_get_ext_core_state (struct guest_info * core, const char * name) { + struct v3_extension * ext = NULL; + struct v3_vm_info * vm = core->vm_info; + uint32_t cpuid = core->vcpu_id; + + list_for_each_entry(ext, &(vm->extensions.extensions), node) { + if (strncmp(ext->impl->name, name, strlen(ext->impl->name)) == 0) { + return ext->core_ext_priv_data[cpuid]; + } + } + + return NULL; +} +