X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_checkpoint.c;h=fbe922de75442585d183e5d013d5c2e5dae39df8;hb=5d1bbcc86de011e3f0d115b6f10fd8645cdf855e;hp=ded6171a9c06dae61759022b47e004b570cb08a6;hpb=6ee36e0a7e4585bd0e4235eeb60644fffe230af3;p=palacios.git diff --git a/palacios/src/palacios/vmm_checkpoint.c b/palacios/src/palacios/vmm_checkpoint.c index ded6171..fbe922d 100644 --- a/palacios/src/palacios/vmm_checkpoint.c +++ b/palacios/src/palacios/vmm_checkpoint.c @@ -58,9 +58,58 @@ struct v3_chkpt { }; + + +static uint_t store_hash_fn(addr_t key) { + char * name = (char *)key; + return v3_hash_buffer((uint8_t *)name, strlen(name)); +} + +static int store_eq_fn(addr_t key1, addr_t key2) { + char * name1 = (char *)key1; + char * name2 = (char *)key2; + + return (strcmp(name1, name2) == 0); +} + + + #include "vmm_chkpt_stores.h" +int V3_init_checkpoint() { + extern struct chkpt_interface * __start__v3_chkpt_stores[]; + extern struct chkpt_interface * __stop__v3_chkpt_stores[]; + struct chkpt_interface ** tmp_store = __start__v3_chkpt_stores; + int i = 0; + + store_table = v3_create_htable(0, store_hash_fn, store_eq_fn); + + while (tmp_store != __stop__v3_chkpt_stores) { + V3_Print("Registering Checkpoint Backing Store (%s)\n", (*tmp_store)->name); + + if (v3_htable_search(store_table, (addr_t)((*tmp_store)->name))) { + PrintError("Multiple instances of Checkpoint backing Store (%s)\n", (*tmp_store)->name); + return -1; + } + + if (v3_htable_insert(store_table, (addr_t)((*tmp_store)->name), (addr_t)(*tmp_store)) == 0) { + PrintError("Could not register Checkpoint backing store (%s)\n", (*tmp_store)->name); + return -1; + } + + tmp_store = &(__start__v3_chkpt_stores[++i]); + } + + return 0; +} + +int V3_deinit_checkpoint() { + v3_free_htable(store_table, 0, 0); + return 0; +} + + static char svm_chkpt_header[] = "v3vee palacios checkpoint version: x.x, SVM x.x"; static char vmx_chkpt_header[] = "v3vee palacios checkpoint version: x.x, VMX x.x"; @@ -73,23 +122,54 @@ static int chkpt_close(struct v3_chkpt * chkpt) { } -static struct v3_chkpt * chkpt_open(char * store, char * url, chkpt_mode_t mode) { +static struct v3_chkpt * chkpt_open(struct v3_vm_info * vm, char * store, char * url, chkpt_mode_t mode) { + struct chkpt_interface * iface = NULL; + struct v3_chkpt * chkpt = NULL; + void * store_data = NULL; + + iface = (void *)v3_htable_search(store_table, (addr_t)store); - // search for checkpoint interface + if (iface == NULL) { + V3_Print("Error: Could not locate Checkpoint interface for store (%s)\n", store); + return NULL; + } - PrintError("Not yet implemented\n"); - return NULL; + store_data = iface->open_chkpt(url, mode); + + if (store_data == NULL) { + PrintError("Could not open url (%s) for backing store (%s)\n", url, store); + return NULL; + } + + + chkpt = V3_Malloc(sizeof(struct v3_chkpt)); + + if (!chkpt) { + PrintError("Could not allocate checkpoint state\n"); + return NULL; + } + + chkpt->interface = iface; + chkpt->vm = vm; + chkpt->store_data = store_data; + + return chkpt; } struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, struct v3_chkpt_ctx * parent, char * name) { struct v3_chkpt_ctx * ctx = V3_Malloc(sizeof(struct v3_chkpt_ctx)); + void * parent_store_ctx = NULL; memset(ctx, 0, sizeof(struct v3_chkpt_ctx)); ctx->chkpt = chkpt; ctx->parent = parent; - ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent->store_ctx, name); + if (parent) { + parent_store_ctx = parent->store_ctx; + } + + ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent_store_ctx, name); return ctx; } @@ -106,9 +186,7 @@ int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) { } -/* Temporary */ -#define V3_CHKPT_STD_SAVE(ctx,x) v3_chkpt_save(ctx,#x,sizeof(x),&(x)) -#define V3_CHKPT_STD_LOAD(ctx,x) v3_chkpt_load(ctx,#x,sizeof(x),&(x)) + int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) { @@ -137,15 +215,10 @@ static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { ret = v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base); v3_chkpt_close_ctx(ctx); - if (ret == 0) { - PrintError("Error Loading VM Memory\n"); - return -1; - } - - return 0; + return ret; } -/* + static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { void * guest_mem_base = NULL; void * ctx = NULL; @@ -153,18 +226,13 @@ static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr); - ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img"); + ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img"); ret = v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base); v3_chkpt_close_ctx(ctx); - if (ret == 0) { - PrintError("Error Saving VM Memory\n"); - return -1; - } - - return 0; + return ret; } int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { @@ -195,7 +263,7 @@ int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { return 0; } -*/ + static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU()); void * ctx = NULL; @@ -306,7 +374,7 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) { return 0; } -/* + static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) { v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU()); void * ctx = NULL; @@ -383,85 +451,124 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) { return 0; } -*/ -int v3_load_vm(struct v3_vm_info * vm, char * store, char * url) { - int i = 0; + +int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) { struct v3_chkpt * chkpt = NULL; + int ret = 0;; + int i = 0; - chkpt = chkpt_open(store, url, LOAD); + chkpt = chkpt_open(vm, store, url, SAVE); - - if (load_memory(vm, chkpt) == -1) { - PrintError("Unable to save memory\n"); + if (chkpt == NULL) { + PrintError("Error creating checkpoint store\n"); return -1; } - //raising the barrier requires VM to be in VM_RUNNING state - vm->run_state = VM_RUNNING; - - /* Don't handle devices just yet - if (v3_chkpt_load_dev(vm) == -1) { - PrintError("Unable to load devies\n"); + /* If this guest is running we need to block it while the checkpoint occurs */ + if (vm->run_state == VM_RUNNING) { + while (v3_raise_barrier(vm, NULL) == -1); } + if ((ret = save_memory(vm, chkpt)) == -1) { + PrintError("Unable to save memory\n"); + goto out; + } + + /* + if ((ret = v3_chkpt_save_dev(vm)) == -1) { + PrintError("Unable to save devices\n"); + goto out; + } */ - if (load_header(vm, chkpt) == -1) { - PrintError("Unable to load header\n"); + if ((ret = save_header(vm, chkpt)) == -1) { + PrintError("Unable to save header\n"); + goto out; } - - //per core cloning - for (i = 0; i < vm->num_cores; i++) { - if (load_core(&(vm->cores[i]), chkpt) == -1) { - return -1; + + for (i = 0; i < vm->num_cores; i++){ + if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) { + PrintError("chkpt of core %d failed\n", i); + goto out; } } + + out: + + /* Resume the guest if it was running */ + if (vm->run_state == VM_RUNNING) { + v3_lower_barrier(vm); + } chkpt_close(chkpt); - return 0; -} - - + return ret; -static uint_t store_hash_fn(addr_t key) { - char * name = (char *)key; - return v3_hash_buffer((uint8_t *)name, strlen(name)); } -static int store_eq_fn(addr_t key1, addr_t key2) { - char * name1 = (char *)key1; - char * name2 = (char *)key2; +int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) { + struct v3_chkpt * chkpt = NULL; + int i = 0; + int ret = 0; + + chkpt = chkpt_open(vm, store, url, LOAD); - return (strcmp(name1, name2) == 0); -} + if (chkpt == NULL) { + PrintError("Error creating checkpoint store\n"); + return -1; + } + /* If this guest is running we need to block it while the checkpoint occurs */ + if (vm->run_state == VM_RUNNING) { + while (v3_raise_barrier(vm, NULL) == -1); + } + if ((ret = load_memory(vm, chkpt)) == -1) { + PrintError("Unable to save memory\n"); + goto out; + } -int V3_init_checkpoint() { - extern struct chkpt_interface * __start__v3_chkpt_stores[]; - extern struct chkpt_interface * __stop__v3_chkpt_stores[]; - struct chkpt_interface ** tmp_store = __start__v3_chkpt_stores; - int i = 0; - store_table = v3_create_htable(0, store_hash_fn, store_eq_fn); + /* Don't handle devices just yet + if (v3_chkpt_load_dev(vm) == -1) { + PrintError("Unable to load devies\n"); + } - while (tmp_store != __stop__v3_chkpt_stores) { - V3_Print("Registering Extension (%s)\n", (*tmp_store)->name); + */ - if (v3_htable_search(store_table, (addr_t)((*tmp_store)->name))) { - PrintError("Multiple instances of Extension (%s)\n", (*tmp_store)->name); - return -1; + if ((ret = load_header(vm, chkpt)) == -1) { + PrintError("Unable to load header\n"); + goto out; + } + + //per core cloning + for (i = 0; i < vm->num_cores; i++) { + if ((ret = load_core(&(vm->cores[i]), chkpt)) == -1) { + PrintError("Error loading core state (core=%d)\n", i); + goto out; } + } - if (v3_htable_insert(store_table, (addr_t)((*tmp_store)->name), (addr_t)(*tmp_store)) == 0) { - PrintError("Could not register Extension (%s)\n", (*tmp_store)->name); - return -1; + out: + + /* Resume the guest if it was running and we didn't just trash the state*/ + if (vm->run_state == VM_RUNNING) { + + if (ret == -1) { + vm->run_state = VM_STOPPED; } - tmp_store = &(__start__v3_chkpt_stores[++i]); + /* We check the run state of the VM after every barrier + So this will immediately halt the VM + */ + v3_lower_barrier(vm); } - return 0; + chkpt_close(chkpt); + + return ret; } + + +