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.


Cleaned up deinitialization of VMM and free of VMs
Peter Dinda [Thu, 19 Sep 2013 22:25:42 +0000 (17:25 -0500)]
18 files changed:
linux_module/buddy.c
linux_module/iface-console.c
linux_module/iface-host-dev.c
linux_module/iface-host-pci.c
linux_module/iface-pmu.c
linux_module/iface-pwrstat.c
linux_module/linux-exts.c
linux_module/linux-exts.h
linux_module/main.c
linux_module/mcheck.c
palacios/include/palacios/vmm_cpu_mapper.h
palacios/include/palacios/vmm_options.h
palacios/include/palacios/vmm_scheduler.h
palacios/src/devices/cga.c
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_cpu_mapper.c
palacios/src/palacios/vmm_options.c
palacios/src/palacios/vmm_scheduler.c

index ea5b705..37f3fec 100644 (file)
@@ -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);
index 9364496..0f5bd23 100644 (file)
@@ -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
 };
index b9d754d..23a3a09 100644 (file)
@@ -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
 };
index d9622c9..48097d8 100644 (file)
@@ -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;
 }
index 2650069..990fb29 100644 (file)
@@ -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
 };
index 2ae1f54..a823946 100644 (file)
@@ -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
 };
index 7b09021..19160bb 100644 (file)
@@ -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;
+}
+
+
 
 
 
index 289d68a..a6b7301 100644 (file)
@@ -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)                                        \
index 99ec9e8..4d09399 100644 (file)
@@ -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;
        }
index 9cdc04b..cbb06d7 100644 (file)
@@ -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
 };
index 3724bb8..625afc9 100644 (file)
@@ -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__ */
index 16dab9a..6034569 100644 (file)
@@ -27,8 +27,9 @@
 #include <palacios/vmm.h>
 
 
-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__
 
index 61539ce..ec6a6f1 100644 (file)
@@ -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__ */
index 1d23a20..0513b8c 100644 (file)
@@ -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));
     }
 
index b49b75e..9337cdd 100644 (file)
@@ -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();
+    
 
 }
 
index b99c626..f3cb4ca 100644 (file)
@@ -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;
+}
index 23b024e..69d70f6 100644 (file)
@@ -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
+}
index cac3425..43230fc 100644 (file)
@@ -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;
+}