From: Peter Dinda Date: Thu, 19 Sep 2013 22:25:42 +0000 (-0500) Subject: Cleaned up deinitialization of VMM and free of VMs X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=e94507c7055f81abcf6a95132cb7ad90f1b5e6ca;p=palacios.releases.git Cleaned up deinitialization of VMM and free of VMs --- diff --git a/linux_module/buddy.c b/linux_module/buddy.c index ea5b705..37f3fec 100644 --- a/linux_module/buddy.c +++ b/linux_module/buddy.c @@ -235,7 +235,13 @@ static int __buddy_remove_mempool(struct buddy_memzone * zone, *user_metadata = pool->user_metadata; - list_del(&(block->link)); + if (is_available(pool,block)) { + list_del(&(block->link)); + } else { + // we may not be on the free list if we are being + // forcibly removed before all allocations are freed + } + rb_erase(&(pool->tree_node), &(zone->mempools)); palacios_free(pool->tag_bits); @@ -254,6 +260,7 @@ int buddy_remove_pool(struct buddy_memzone * zone, unsigned long flags = 0; int ret = 0; + palacios_spinlock_lock_irqsave(&(zone->lock), flags); ret = __buddy_remove_mempool(zone, base_addr, force, user_metadata); palacios_spinlock_unlock_irqrestore(&(zone->lock), flags); diff --git a/linux_module/iface-console.c b/linux_module/iface-console.c index 9364496..0f5bd23 100644 --- a/linux_module/iface-console.c +++ b/linux_module/iface-console.c @@ -446,13 +446,18 @@ static int console_init( void ) { return 0; } +static int console_deinit(void) +{ + // nothing to do + return 0; +} static struct linux_ext console_ext = { .name = "CONSOLE", .init = console_init, - .deinit = NULL, + .deinit = console_deinit, .guest_init = NULL, .guest_deinit = NULL }; diff --git a/linux_module/iface-host-dev.c b/linux_module/iface-host-dev.c index b9d754d..23a3a09 100644 --- a/linux_module/iface-host-dev.c +++ b/linux_module/iface-host-dev.c @@ -1323,6 +1323,11 @@ static int host_dev_init( void ) { } +static int host_dev_deinit(void) { + // nothing to do + return 0; +} + static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) { struct palacios_host_dev * host_dev = palacios_alloc(sizeof(struct palacios_host_dev)); @@ -1358,7 +1363,7 @@ static int host_dev_guest_deinit(struct v3_guest * guest, void * vm_data) { static struct linux_ext host_dev_ext = { .name = "HOST_DEVICE_INTERFACE", .init = host_dev_init, - .deinit = NULL, + .deinit = host_dev_deinit, .guest_init = host_dev_guest_init, .guest_deinit = host_dev_guest_deinit }; diff --git a/linux_module/iface-host-pci.c b/linux_module/iface-host-pci.c index d9622c9..48097d8 100644 --- a/linux_module/iface-host-pci.c +++ b/linux_module/iface-host-pci.c @@ -233,6 +233,9 @@ static int host_pci_init( void ) { } static int host_pci_deinit(void) { + remove_global_ctrl(V3_ADD_PCI_USER_DEV); + remove_global_ctrl(V3_ADD_PCI_HW_DEV); + palacios_spinlock_deinit(&lock); return 0; } diff --git a/linux_module/iface-pmu.c b/linux_module/iface-pmu.c index 2650069..990fb29 100644 --- a/linux_module/iface-pmu.c +++ b/linux_module/iface-pmu.c @@ -644,11 +644,17 @@ static int pmu_init( void ) { return 0; } +static int pmu_deinit(void) +{ + // nothing + return 0; +} + static struct linux_ext pmu_ext = { .name = "PMU", .init = pmu_init, - .deinit = NULL, + .deinit = pmu_deinit, .guest_init = NULL, .guest_deinit = NULL }; diff --git a/linux_module/iface-pwrstat.c b/linux_module/iface-pwrstat.c index 2ae1f54..a823946 100644 --- a/linux_module/iface-pwrstat.c +++ b/linux_module/iface-pwrstat.c @@ -303,12 +303,18 @@ static int pwrstat_init (void) return 0; } -/* if AMD comes up with something it can go here */ + +static int pwrstat_deinit(void) +{ + // nothing to do + return 0; +} + static struct linux_ext pwrstat_ext = { .name = "POWERSTAT", .init = pwrstat_init, - .deinit = NULL, + .deinit = pwrstat_deinit, .guest_init = NULL, .guest_deinit = NULL }; diff --git a/linux_module/linux-exts.c b/linux_module/linux-exts.c index 7b09021..19160bb 100644 --- a/linux_module/linux-exts.c +++ b/linux_module/linux-exts.c @@ -53,7 +53,7 @@ int add_global_ctrl(unsigned int cmd, ctrl->cmd = cmd; ctrl->handler = handler; - if (__insert_global_ctrl(ctrl) != NULL) { + if (__insert_global_ctrl(ctrl) != NULL) { printk("Could not insert guest ctrl %d\n", cmd); palacios_free(ctrl); return -1; @@ -65,9 +65,9 @@ int add_global_ctrl(unsigned int cmd, } -struct global_ctrl * get_global_ctrl(unsigned int cmd) { +static struct rb_node * find_match(unsigned int cmd) { struct rb_node * n = global_ctrls.rb_node; - struct global_ctrl * ctrl = NULL; + struct global_ctrl *ctrl; while (n) { ctrl = rb_entry(n, struct global_ctrl, tree_node); @@ -77,7 +77,7 @@ struct global_ctrl * get_global_ctrl(unsigned int cmd) { } else if (cmd > ctrl->cmd) { n = n->rb_right; } else { - return ctrl; + return n; } } @@ -85,6 +85,38 @@ struct global_ctrl * get_global_ctrl(unsigned int cmd) { } +struct global_ctrl * get_global_ctrl(unsigned int cmd) { + struct rb_node *n = find_match(cmd); + + if (n) { + return rb_entry(n, struct global_ctrl, tree_node); + } else { + return NULL; + } +} + + +int remove_global_ctrl(unsigned int cmd) +{ + struct rb_node *n = find_match(cmd); + struct global_ctrl *c; + + if (!n) { + return -1; + } + + c = rb_entry(n, struct global_ctrl, tree_node); + + rb_erase(n,&global_ctrls); + + if (c) { + palacios_free(c); + } + + return 0; +} + + diff --git a/linux_module/linux-exts.h b/linux_module/linux-exts.h index 289d68a..a6b7301 100644 --- a/linux_module/linux-exts.h +++ b/linux_module/linux-exts.h @@ -37,6 +37,7 @@ int add_global_ctrl(unsigned int cmd, struct global_ctrl * get_global_ctrl(unsigned int cmd); +int remove_global_ctrl(unsigned int cmd); #define register_extension(ext) \ diff --git a/linux_module/main.c b/linux_module/main.c index 99ec9e8..4d09399 100644 --- a/linux_module/main.c +++ b/linux_module/main.c @@ -481,7 +481,7 @@ static int read_info(struct seq_file *s, void *v) if (!v3_lookup_option("mem_block_size")) { mem_block_size = V3_CONFIG_MEM_BLOCK_SIZE; } else { - if (kstrtoull(v3_lookup_option("mem_block_size"), 0, &mem_block_size)) { + if (strict_strtoull(v3_lookup_option("mem_block_size"), 0, &mem_block_size)) { // huh? mem_block_size=-1; } diff --git a/linux_module/mcheck.c b/linux_module/mcheck.c index 9cdc04b..cbb06d7 100644 --- a/linux_module/mcheck.c +++ b/linux_module/mcheck.c @@ -50,11 +50,17 @@ static int guest_deinit(struct v3_guest * guest, void * vm_data) { return 0; } +static int all_deinit(void) +{ + // nothing to do + return 0; +} + struct linux_ext mcheck_ext = { .name = "MACHINE CHECK", .init = NULL, - .deinit = NULL, + .deinit = all_deinit, .guest_init = guest_init, .guest_deinit = guest_deinit }; diff --git a/palacios/include/palacios/vmm_cpu_mapper.h b/palacios/include/palacios/vmm_cpu_mapper.h index 3724bb8..625afc9 100644 --- a/palacios/include/palacios/vmm_cpu_mapper.h +++ b/palacios/include/palacios/vmm_cpu_mapper.h @@ -30,15 +30,22 @@ struct vm_cpu_mapper_impl { int (*vm_deinit)(struct v3_vm_info *vm); int (*admit_core)(struct v3_vm_info * vm, int vcore_id, int target_cpu); int (*admit)(struct v3_vm_info *vm); + // should really be departure options... }; int v3_cpu_mapper_register_vm(struct v3_vm_info *vm, unsigned int cpu_mask); int v3_cpu_mapper_admit_vm(struct v3_vm_info *vm); int v3_cpu_mapper_admit_core(struct v3_vm_info * vm, int vcore_id, int target_cpu); + int V3_init_cpu_mapper(); +int V3_deinit_cpu_mapper(); + int v3_register_cpu_mapper(struct vm_cpu_mapper_impl *vm); +struct vm_cpu_mapper_impl *v3_unregister_cpu_mapper(char *name); struct vm_cpu_mapper_impl *v3_cpu_mapper_lookup(char *name); + int V3_enable_cpu_mapper(); +int V3_disable_cpu_mapper(); #endif /* __VMM_cpu_mapper_H__ */ diff --git a/palacios/include/palacios/vmm_options.h b/palacios/include/palacios/vmm_options.h index 16dab9a..6034569 100644 --- a/palacios/include/palacios/vmm_options.h +++ b/palacios/include/palacios/vmm_options.h @@ -27,8 +27,9 @@ #include -void v3_parse_options(char *optstring); +void v3_parse_options(char *optstring); // this is init char *v3_lookup_option(char *option); +void v3_deinit_options(); #endif // ! __V3VEE__ diff --git a/palacios/include/palacios/vmm_scheduler.h b/palacios/include/palacios/vmm_scheduler.h index 61539ce..ec6a6f1 100644 --- a/palacios/include/palacios/vmm_scheduler.h +++ b/palacios/include/palacios/vmm_scheduler.h @@ -35,6 +35,7 @@ struct vm_scheduler_impl { int (*admit)(struct v3_vm_info *vm); int (*remap)(struct v3_vm_info *vm); int (*dvfs)(struct v3_vm_info *vm); + // should really have departure... }; void v3_schedule(struct guest_info *core); @@ -48,8 +49,13 @@ void v3_scheduler_remap_notify(struct v3_vm_info *vm); void v3_scheduler_dvfs_notify(struct v3_vm_info *vm); int V3_init_scheduling(); +int V3_deinit_scheduling(); + int v3_register_scheduler(struct vm_scheduler_impl *vm); struct vm_scheduler_impl *v3_scheduler_lookup(char *name); +struct vm_scheduler_impl *v3_unregister_scheduler(char *name); + int V3_enable_scheduler(); +int V3_disable_scheduler(); #endif /* __VMM_SCHEDULER_H__ */ diff --git a/palacios/src/devices/cga.c b/palacios/src/devices/cga.c index 1d23a20..0513b8c 100644 --- a/palacios/src/devices/cga.c +++ b/palacios/src/devices/cga.c @@ -1102,7 +1102,7 @@ int v3_cons_get_fb(struct vm_device * frontend_dev, uint8_t * dst, uint_t offset static int cga_free(struct video_internal * video_state) { if (video_state->framebuf_pa) { - PrintError(VM_NONE, VCORE_NONE, "Freeing framebuffer PA %p\n", (void *)(video_state->framebuf_pa)); + PrintDebug(VM_NONE, VCORE_NONE, "Freeing framebuffer PA %p\n", (void *)(video_state->framebuf_pa)); V3_FreePages((void *)(video_state->framebuf_pa), (FRAMEBUF_SIZE / 4096)); } diff --git a/palacios/src/palacios/vmm.c b/palacios/src/palacios/vmm.c index b49b75e..9337cdd 100644 --- a/palacios/src/palacios/vmm.c +++ b/palacios/src/palacios/vmm.c @@ -107,9 +107,14 @@ void Init_V3(struct v3_os_hooks * hooks, char * cpu_mask, int num_cpus, char *op V3_Print(VM_NONE, VCORE_NONE, "V3 Print statement to fix a Kitten page fault bug\n"); + // Set global variables. os_hooks = hooks; + if (num_cpus>V3_CONFIG_MAX_CPUS) { + PrintError(VM_NONE,VCORE_NONE, "Requesting as many as %d cpus, but Palacios is compiled for a maximum of %d. Only the first %d cpus will be considered\n", num_cpus, V3_CONFIG_MAX_CPUS, V3_CONFIG_MAX_CPUS); + } + // Determine the global machine type v3_mach_type = V3_INVALID_CPU; @@ -155,7 +160,7 @@ void Init_V3(struct v3_os_hooks * hooks, char * cpu_mask, int num_cpus, char *op if ((hooks) && (hooks->call_on_cpu)) { - for (i = 0; i < num_cpus; i++) { + for (i = 0; i < num_cpus && i < V3_CONFIG_MAX_CPUS; i++) { major = i / 8; minor = i % 8; @@ -176,19 +181,9 @@ void Init_V3(struct v3_os_hooks * hooks, char * cpu_mask, int num_cpus, char *op void Shutdown_V3() { int i; - V3_deinit_devices(); - V3_deinit_shdw_paging(); - - V3_deinit_extensions(); - -#ifdef V3_CONFIG_SYMMOD - V3_deinit_symmod(); -#endif - -#ifdef V3_CONFIG_CHECKPOINT - V3_deinit_checkpoint(); -#endif + // Reverse order of Init_V3 + // bring down CPUs if ((os_hooks) && (os_hooks->call_on_cpu)) { for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) { @@ -199,7 +194,32 @@ void Shutdown_V3() { } } +#ifdef V3_CONFIG_CHECKPOINT + V3_deinit_checkpoint(); +#endif + +#ifdef V3_CONFIG_SYMMOD + V3_deinit_symmod(); +#endif + + V3_disable_scheduler(); + + V3_disable_cpu_mapper(); + + V3_deinit_extensions(); + + V3_deinit_scheduling(); + + V3_deinit_cpu_mapper(); + + V3_deinit_shdw_paging(); + + V3_deinit_devices(); + v3_deinit_mem(); + + v3_deinit_options(); + } diff --git a/palacios/src/palacios/vmm_cpu_mapper.c b/palacios/src/palacios/vmm_cpu_mapper.c index b99c626..f3cb4ca 100644 --- a/palacios/src/palacios/vmm_cpu_mapper.c +++ b/palacios/src/palacios/vmm_cpu_mapper.c @@ -32,6 +32,7 @@ static char default_strategy[] = "default"; static struct hashtable * master_cpu_mapper_table = NULL; static int create_default_cpu_mapper(); +static int destroy_default_cpu_mapper(); static struct vm_cpu_mapper_impl *cpu_mapper = NULL; @@ -56,6 +57,13 @@ int V3_init_cpu_mapper() { } +int V3_deinit_cpu_mapper() { + + destroy_default_cpu_mapper(); + v3_free_htable(master_cpu_mapper_table, 1, 1); + return 0; +} + int v3_register_cpu_mapper(struct vm_cpu_mapper_impl *s) { PrintDebug(VM_NONE, VCORE_NONE,"Registering cpu_mapper (%s)\n", s->name); @@ -75,6 +83,21 @@ int v3_register_cpu_mapper(struct vm_cpu_mapper_impl *s) { return 0; } +struct vm_cpu_mapper_impl *v3_unregister_cpu_mapper(char *name) { + + PrintDebug(VM_NONE, VCORE_NONE,"Unregistering cpu_mapper (%s)\n",name); + + struct vm_cpu_mapper_impl *f = (struct vm_cpu_mapper_impl *) v3_htable_remove(master_cpu_mapper_table,(addr_t)(name),0); + + if (!f) { + PrintError(VM_NONE,VCORE_NONE,"Could not find cpu_mapper (%s)\n",name); + return NULL; + } else { + return f; + } +} + + struct vm_cpu_mapper_impl *v3_cpu_mapper_lookup(char *name) { return (struct vm_cpu_mapper_impl *)v3_htable_search(master_cpu_mapper_table, (addr_t)(name)); @@ -108,6 +131,15 @@ int V3_enable_cpu_mapper() { } } +int V3_disable_cpu_mapper() +{ + if (cpu_mapper->deinit) { + return cpu_mapper->deinit(); + } else { + return 0; + } +} + int v3_cpu_mapper_register_vm(struct v3_vm_info *vm,unsigned int cpu_mask) { if (cpu_mapper->vm_init) { return cpu_mapper->vm_init(vm,cpu_mask); @@ -220,3 +252,9 @@ static int create_default_cpu_mapper() v3_register_cpu_mapper(&default_mapper_impl); return 0; } + +static int destroy_default_cpu_mapper() +{ + v3_unregister_cpu_mapper(default_mapper_impl.name); + return 0; +} diff --git a/palacios/src/palacios/vmm_options.c b/palacios/src/palacios/vmm_options.c index 23b024e..69d70f6 100644 --- a/palacios/src/palacios/vmm_options.c +++ b/palacios/src/palacios/vmm_options.c @@ -46,6 +46,38 @@ static int option_eq_fn(addr_t key1, addr_t key2) { return (strcmp(name1, name2) == 0); } +// need to allocate these cleanly and separately so we can easily recover the +// storage +static int option_insert(char *key, char *val) +{ + char *k, *v; + + k = V3_Malloc(strlen(key)+1); + + if (!k) { + return -1; + } + + v = V3_Malloc(strlen(val)+1); + + if (!v) { + V3_Free(k); + return -1; + } + + strcpy(k,key); + strcpy(v,val); + + if (!v3_htable_insert(option_table, (addr_t)k, (addr_t)v)) { + V3_Free(v); + V3_Free(k); + return -1; + } + + return 0; +} + + void v3_parse_options(char *options) { char *currKey = NULL, *currVal = NULL; @@ -73,7 +105,7 @@ void v3_parse_options(char *options) if (!currVal) { currVal = truevalue; } - v3_htable_insert(option_table, (addr_t)currKey, (addr_t)currVal); + option_insert(currKey, currVal); parseKey = 1; currKey = NULL; currVal = NULL; @@ -99,11 +131,20 @@ void v3_parse_options(char *options) if (!currVal) { currVal = truevalue; } - v3_htable_insert(option_table, (addr_t)currKey, (addr_t)currVal); + option_insert(currKey, currVal); } + + V3_Free(option_storage); + return; } char *v3_lookup_option(char *key) { return (char *)v3_htable_search(option_table, (addr_t)(key)); } + + +void v3_deinit_options() +{ + v3_free_htable(option_table,1,1); // will free keys and values +} diff --git a/palacios/src/palacios/vmm_scheduler.c b/palacios/src/palacios/vmm_scheduler.c index cac3425..43230fc 100644 --- a/palacios/src/palacios/vmm_scheduler.c +++ b/palacios/src/palacios/vmm_scheduler.c @@ -32,6 +32,7 @@ static char default_strategy[] = "host"; static struct hashtable * master_scheduler_table = NULL; static int create_host_scheduler(); +static int destroy_host_scheduler(); static struct vm_scheduler_impl *scheduler = NULL; @@ -55,6 +56,13 @@ int V3_init_scheduling() { return create_host_scheduler(); } +int V3_deinit_scheduling() +{ + destroy_host_scheduler(); + v3_free_htable(master_scheduler_table,1,1); + return 0; +} + int v3_register_scheduler(struct vm_scheduler_impl *s) { @@ -75,6 +83,24 @@ int v3_register_scheduler(struct vm_scheduler_impl *s) { return 0; } + +struct vm_scheduler_impl *v3_unregister_scheduler(char *name) { + + PrintDebug(VM_NONE, VCORE_NONE,"Unregistering Scheduler (%s)\n",name); + + struct vm_scheduler_impl *f = (struct vm_scheduler_impl *) v3_htable_remove(master_scheduler_table,(addr_t)(name),0); + + if (!f) { + PrintError(VM_NONE,VCORE_NONE,"Could not find Scheduler (%s)\n",name); + return NULL; + } else { + return f; + } +} + + + + struct vm_scheduler_impl *v3_scheduler_lookup(char *name) { return (struct vm_scheduler_impl *)v3_htable_search(master_scheduler_table, (addr_t)(name)); @@ -108,6 +134,15 @@ int V3_enable_scheduler() { } } +int V3_disable_scheduler() +{ + if (scheduler->deinit) { + return scheduler->deinit(); + } else { + return 0; + } +} + int v3_scheduler_register_vm(struct v3_vm_info *vm) { if (scheduler->vm_init) { return scheduler->vm_init(vm); @@ -247,3 +282,9 @@ static int create_host_scheduler() v3_register_scheduler(&host_sched_impl); return 0; } + +static int destroy_host_scheduler() +{ + v3_unregister_scheduler(host_sched_impl.name); + return 0; +}