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.


Cleanup and sanity-checking of divide-by-zero and floating point use bugs (Coverity...
[palacios.git] / palacios / src / palacios / vmm_scheduler.c
index 0739575..506429b 100644 (file)
@@ -1,14 +1,15 @@
-/* 
+/*
  * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
  *
  * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
+ * and the University of New Mexico.  You can find out more at
  * http://www.v3vee.org
  *
  * Copyright (c) 2013, Oscar Mondragon <omondrag@cs.unm.edu>
- * Copyright (c) 2013, The V3VEE Project <http://www.v3vee.org> 
+ * Copyright (c) 2013, Patrick G. Bridges <bridges@cs.unm.edu>
+ * Copyright (c) 2013, The V3VEE Project <http://www.v3vee.org>
  * All rights reserved.
  *
  * Author: Oscar Mondragon <omondrag@cs.unm.edu>
@@ -31,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;
 
@@ -47,13 +49,22 @@ static int scheduler_eq_fn(addr_t key1, addr_t key2) {
 }
 
 int V3_init_scheduling() {
-   
+
      PrintDebug(VM_NONE, VCORE_NONE,"Initializing scheduler");
 
     master_scheduler_table = v3_create_htable(0, scheduler_hash_fn, scheduler_eq_fn);
     return create_host_scheduler();
 }
 
+int V3_deinit_scheduling()
+{
+    destroy_host_scheduler();
+    // important not to remove any keys or values since we don't know
+    // if they are malloced or other
+    v3_free_htable(master_scheduler_table,0,0);
+    return 0;
+}
+
 
 int v3_register_scheduler(struct vm_scheduler_impl *s) {
 
@@ -63,9 +74,7 @@ int v3_register_scheduler(struct vm_scheduler_impl *s) {
         PrintError(VM_NONE, VCORE_NONE, "Multiple instances of scheduler (%s)\n", s->name);
         return -1;
     }
-    PrintDebug(VM_NONE, VCORE_NONE,"Registering Scheduler (%s) 2\n", s->name);
 
-  
     if (v3_htable_insert(master_scheduler_table,
                          (addr_t)(s->name),
                          (addr_t)(s)) == 0) {
@@ -73,22 +82,53 @@ int v3_register_scheduler(struct vm_scheduler_impl *s) {
         return -1;
     }
 
-    PrintDebug(VM_NONE, VCORE_NONE,"Scheduler registered\n");
     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));
 }
 
 int V3_enable_scheduler() {
-    /* XXX Lookup the specified scheduler to use for palacios and use it */
-    scheduler = v3_scheduler_lookup(default_strategy);
+    char *sched_name;
+
+    scheduler = NULL;
+    sched_name = v3_lookup_option("scheduler");
+
+    if (sched_name) {
+       scheduler = v3_scheduler_lookup(sched_name);
+    }
+
+    if (!scheduler) {
+        scheduler = v3_scheduler_lookup(default_strategy);
+    }
+
     if (!scheduler) {
        PrintError(VM_NONE, VCORE_NONE,"Specified Palacios scheduler \"%s\" not found.\n", default_strategy);
        return -1;
     }
+
+    PrintDebug(VM_NONE, VCORE_NONE,"Scheduler %s found",scheduler->name);
+
     if (scheduler->init) {
        return scheduler->init();
     } else {
@@ -96,120 +136,150 @@ 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);
+       return scheduler->vm_init(vm);
     } else {
        return 0;
     }
 }
 int v3_scheduler_register_core(struct guest_info *core) {
     if (scheduler->core_init) {
-       return scheduler->core_init(core);
+       return scheduler->core_init(core);
     } else {
        return 0;
     }
 }
 int v3_scheduler_admit_vm(struct v3_vm_info *vm) {
     if (scheduler->admit) {
-       return scheduler->admit(vm);
+       return scheduler->admit(vm);
     } else {
        return 0;
     }
 }
 int v3_scheduler_notify_remap(struct v3_vm_info *vm) {
     if (scheduler->remap) {
-       return scheduler->remap(vm);
+       return scheduler->remap(vm);
     } else {
        return 0;
     }
 }
 int v3_scheduler_notify_dvfs(struct v3_vm_info *vm) {
     if (scheduler->dvfs) {
-       return scheduler->dvfs(vm);
+       return scheduler->dvfs(vm);
     } else {
        return 0;
     }
 }
 void v3_schedule(struct guest_info *core) {
     if (scheduler->schedule) {
-       scheduler->schedule(core);
+       scheduler->schedule(core);
     }
     return;
 }
 void v3_yield(struct guest_info *core, int usec) {
     if (scheduler->yield) {
-       scheduler->yield(core, usec);
-    } 
+       scheduler->yield(core, usec);
+    }
     return;
 }
 
 int host_sched_vm_init(struct v3_vm_info *vm)
 {
 
-    PrintDebug(vm, VCORE_NONE,"Sched. host_sched_init\n"); 
+    PrintDebug(vm, VCORE_NONE,"Sched. host_sched_init\n");
 
     char * schedule_hz_str = v3_cfg_val(vm->cfg_data->cfg, "schedule_hz");
-    uint32_t sched_hz = 100;   
+    uint32_t sched_hz = 100;
 
 
     if (schedule_hz_str) {
        sched_hz = atoi(schedule_hz_str);
+       if (sched_hz==0) { 
+           PrintError(vm, VCORE_NONE,"Cannot set Sched Hz to 0\n");
+           return -1;
+       }
     }
 
-    PrintDebug(vm, VCORE_NONE,"CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), 
+    PrintDebug(vm, VCORE_NONE,"CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(),
               (void *)(addr_t)sched_hz);
 
     uint64_t yield_cycle_period = (V3_CPU_KHZ() * 1000) / sched_hz;
-    vm->sched_priv_data = (void *)yield_cycle_period; 
+    vm->sched_priv_data = (void *)yield_cycle_period;
 
     return 0;
 }
 
 int host_sched_core_init(struct guest_info *core)
 {
-    PrintDebug(core->vm_info, core,"Sched. host_sched_core_init\n"); 
+    PrintDebug(core->vm_info, core,"Sched. host_sched_core_init\n");
 
-    uint64_t t = v3_get_host_time(&core->time_state); 
+    uint64_t t = v3_get_host_time(&core->time_state);
     core->sched_priv_data = (void *)t;
 
     return 0;
 }
 
+int host_sched_core_stop(struct guest_info *core){
+
+    v3_yield(NULL,-1);
+    return 0;
+}
+
+
 void host_sched_schedule(struct guest_info *core)
 {
     uint64_t cur_cycle;
     cur_cycle = v3_get_host_time(&core->time_state);
 
     if (cur_cycle > ( (uint64_t)core->sched_priv_data + (uint64_t)core->vm_info->sched_priv_data)) {
-       
+
         V3_Yield();
-      
+
+#if 0
         uint64_t yield_start_cycle = (uint64_t) core->sched_priv_data;
         yield_start_cycle +=  (uint64_t)core->vm_info->sched_priv_data;
         core->sched_priv_data = (void *)yield_start_cycle;
-      
+#else
+       core->sched_priv_data = (void*)v3_get_host_time(&(core->time_state));
+#endif
+
     }
 }
 
-/* 
- * unconditional cpu yield 
- * if the yielding thread is a guest context, the guest quantum is reset on resumption 
+/*
+ * unconditional cpu yield
+ * if the yielding thread is a guest context, the guest quantum is reset on resumption
  * Non guest context threads should call this function with a NULL argument
  *
  * usec <0  => the non-timed yield is used
  * usec >=0 => the timed yield is used, which also usually implies interruptible
  */
 void host_sched_yield(struct guest_info * core, int usec) {
-    uint64_t yield_start_cycle;
     if (usec < 0) {
         V3_Yield();
     } else {
         V3_Sleep(usec);
     }
-    yield_start_cycle = (uint64_t) core->sched_priv_data
-                        + (uint64_t)core->vm_info->sched_priv_data;
-    core->sched_priv_data = (void *)yield_start_cycle;
+    if (core){
+#if 0
+    uint64_t yield_start_cycle;
+         yield_start_cycle = (uint64_t) core->sched_priv_data
+                             + (uint64_t)core->vm_info->sched_priv_data;
+         core->sched_priv_data = (void *)yield_start_cycle;
+#else
+       core->sched_priv_data = (void*)v3_get_host_time(&(core->time_state));
+#endif
+    }
 }
 
 
@@ -217,6 +287,31 @@ int host_sched_admit(struct v3_vm_info *vm){
     return 0;
 }
 
+int v3_scheduler_free_vm(struct v3_vm_info *vm) {
+    if (scheduler->vm_deinit) {
+       return scheduler->vm_deinit(vm);
+    } else {
+       return 0;
+    }
+}
+
+int v3_scheduler_free_core(struct guest_info *core) {
+    if (scheduler->core_deinit) {
+       return scheduler->core_deinit(core);
+    } else {
+       return 0;
+    }
+}
+
+
+int v3_scheduler_stop_core(struct guest_info *core){
+    if (scheduler->core_stop) {
+       return scheduler->core_stop(core);
+    } else {
+       return 0;
+    }
+}
+
 static struct vm_scheduler_impl host_sched_impl = {
     .name = "host",
     .init = NULL,
@@ -224,6 +319,7 @@ static struct vm_scheduler_impl host_sched_impl = {
     .vm_init = host_sched_vm_init,
     .vm_deinit = NULL,
     .core_init = host_sched_core_init,
+    .core_stop = host_sched_core_stop,
     .core_deinit = NULL,
     .schedule = host_sched_schedule,
     .yield = host_sched_yield,
@@ -237,3 +333,10 @@ 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);
+       // no deletion of this since it's a pointer to a global var
+       return 0;
+}