*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);
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);
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
};
}
+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));
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
};
}
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;
}
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
};
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
};
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;
}
-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);
} else if (cmd > ctrl->cmd) {
n = n->rb_right;
} else {
- return ctrl;
+ return n;
}
}
}
+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;
+}
+
+
struct global_ctrl * get_global_ctrl(unsigned int cmd);
+int remove_global_ctrl(unsigned int cmd);
#define register_extension(ext) \
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;
}
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
};
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__ */
#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__
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);
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__ */
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));
}
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;
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;
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++) {
}
}
+#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();
+
}
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;
}
+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);
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));
}
}
+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);
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;
+}
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;
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;
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
+}
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;
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) {
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_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);
v3_register_scheduler(&host_sched_impl);
return 0;
}
+
+static int destroy_host_scheduler()
+{
+ v3_unregister_scheduler(host_sched_impl.name);
+ return 0;
+}