X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_checkpoint.c;h=ef99cdf4e25eda5a976cfbb1bb2f754465224127;hb=2501786527fbddda7b8d2ef7218b683b6e21ca83;hp=ef4bec1191b7b8d214f5d581c8c59edf7c66031a;hpb=793f9cd53a472668dbeb16341085e5512484485c;p=palacios.releases.git diff --git a/palacios/src/palacios/vmm_checkpoint.c b/palacios/src/palacios/vmm_checkpoint.c index ef4bec1..ef99cdf 100644 --- a/palacios/src/palacios/vmm_checkpoint.c +++ b/palacios/src/palacios/vmm_checkpoint.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -58,9 +59,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 +123,64 @@ 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; + } + + 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; + } + - PrintError("Not yet implemented\n"); - 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; + + + if (!ctx) { + PrintError("Unable to allocate context\n"); + return 0; + } 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); + + if (!(ctx->store_ctx)) { + PrintError("Warning: opening underlying representation returned null\n"); + } return ctx; } @@ -106,19 +197,20 @@ 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) { struct v3_chkpt * chkpt = ctx->chkpt; - return chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf); + + return chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf); + } int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) { struct v3_chkpt * chkpt = ctx->chkpt; + return chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf); } @@ -133,14 +225,19 @@ static int load_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"); - - 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"); + + if (!ctx) { + PrintError("Unable to open context for memory load\n"); + return -1; + } + + if (v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base) == -1) { + PrintError("Unable to load all of memory (requested=%llu bytes, result=%llu bytes\n",(uint64_t)(vm->mem_size),ret); + v3_chkpt_close_ctx(ctx); return -1; } + + v3_chkpt_close_ctx(ctx); return 0; } @@ -153,36 +250,52 @@ 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"); + if (!ctx) { + PrintError("Unable to open context to save memory\n"); + return -1; + } - 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"); + if (v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base) == -1) { + PrintError("Unable to load all of memory (requested=%llu, received=%llu)\n",(uint64_t)(vm->mem_size),ret); + v3_chkpt_close_ctx(ctx); return -1; } + v3_chkpt_close_ctx(ctx); + return 0; } int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { - v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU()); + extern v3_cpu_arch_t v3_mach_type; void * ctx = NULL; ctx = v3_chkpt_open_ctx(chkpt, NULL, "header"); + if (!ctx) { + PrintError("Cannot open context to save header\n"); + return -1; + } - switch (cpu_type) { + switch (v3_mach_type) { case V3_SVM_CPU: case V3_SVM_REV3_CPU: { - v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header); + if (v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header) == -1) { + PrintError("Could not save all of SVM header\n"); + v3_chkpt_close_ctx(ctx); + return -1; + } break; } case V3_VMX_CPU: case V3_VMX_EPT_CPU: case V3_VMX_EPT_UG_CPU: { - v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header); + if (v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header) == -1) { + PrintError("Could not save all of VMX header\n"); + v3_chkpt_close_ctx(ctx); + return -1; + } break; } default: @@ -197,17 +310,23 @@ int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { } 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()); + extern v3_cpu_arch_t v3_mach_type; void * ctx = NULL; ctx = v3_chkpt_open_ctx(chkpt, NULL, "header"); - switch (cpu_type) { + switch (v3_mach_type) { case V3_SVM_CPU: case V3_SVM_REV3_CPU: { char header[strlen(svm_chkpt_header) + 1]; - v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header); + if (v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header) == -1) { + PrintError("Could not load all of SVM header\n"); + v3_chkpt_close_ctx(ctx); + return -1; + } + + header[strlen(svm_chkpt_header)] = 0; break; } @@ -216,7 +335,13 @@ static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { case V3_VMX_EPT_UG_CPU: { char header[strlen(vmx_chkpt_header) + 1]; - v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header); + if (v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header) == -1) { + PrintError("Could not load all of VMX header\n"); + v3_chkpt_close_ctx(ctx); + return -1; + } + + header[strlen(vmx_chkpt_header)] = 0; break; } @@ -225,23 +350,33 @@ static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { v3_chkpt_close_ctx(ctx); return -1; } - + v3_chkpt_close_ctx(ctx); - + return 0; } static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) { - v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU()); + extern v3_cpu_arch_t v3_mach_type; void * ctx = NULL; char key_name[16]; + memset(key_name, 0, 16); snprintf(key_name, 16, "guest_info%d", info->vcpu_id); ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name); + if (!ctx) { + PrintError("Could not open context to load core\n"); + return -1; + } + + // These really need to have error checking + + v3_chkpt_load_64(ctx, "RIP", &(info->rip)); + V3_CHKPT_STD_LOAD(ctx, info->vm_regs); V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0); @@ -256,6 +391,7 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) { V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr3); V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr0); V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_efer); + v3_chkpt_close_ctx(ctx); PrintDebug("Finished reading guest_info information\n"); @@ -263,17 +399,37 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) { info->cpu_mode = v3_get_vm_cpu_mode(info); info->mem_mode = v3_get_vm_mem_mode(info); + if (info->shdw_pg_mode == SHADOW_PAGING) { + if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) { + if (v3_activate_shadow_pt(info) == -1) { + PrintError("Failed to activate shadow page tables\n"); + return -1; + } + } else { + if (v3_activate_passthrough_pt(info) == -1) { + PrintError("Failed to activate passthrough page tables\n"); + return -1; + } + } + } - switch (cpu_type) { + + switch (v3_mach_type) { case V3_SVM_CPU: case V3_SVM_REV3_CPU: { char key_name[16]; snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id); ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name); + + if (!ctx) { + PrintError("Could not open context to load SVM core\n"); + return -1; + } if (v3_svm_load_core(info, ctx) == -1) { PrintError("Failed to patch core %d\n", info->vcpu_id); + v3_chkpt_close_ctx(ctx); return -1; } @@ -287,10 +443,17 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) { char key_name[16]; snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id); + ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name); + + if (!ctx) { + PrintError("Could not open context to load VMX core\n"); + return -1; + } if (v3_vmx_load_core(info, ctx) < 0) { PrintError("VMX checkpoint failed\n"); + v3_chkpt_close_ctx(ctx); return -1; } @@ -299,25 +462,38 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) { break; } default: - PrintError("Invalid CPU Type (%d)\n", cpu_type); + PrintError("Invalid CPU Type (%d)\n", v3_mach_type); return -1; } + v3_print_guest_state(info); + 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()); + extern v3_cpu_arch_t v3_mach_type; void * ctx = NULL; char key_name[16]; memset(key_name, 0, 16); + v3_print_guest_state(info); + snprintf(key_name, 16, "guest_info%d", info->vcpu_id); ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name); + + if (!ctx) { + PrintError("Unable to open context to save core\n"); + return -1; + } + + + // Error checking of all this needs to happen + v3_chkpt_save_64(ctx, "RIP", &(info->rip)); V3_CHKPT_STD_SAVE(ctx, info->vm_regs); @@ -337,7 +513,7 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) { v3_chkpt_close_ctx(ctx); //Architechture specific code - switch (cpu_type) { + switch (v3_mach_type) { case V3_SVM_CPU: case V3_SVM_REV3_CPU: { char key_name[16]; @@ -346,6 +522,11 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) { snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id); ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name); + + if (!ctx) { + PrintError("Could not open context to store SVM core\n"); + return -1; + } if (v3_svm_save_core(info, ctx) == -1) { PrintError("VMCB Unable to be written\n"); @@ -365,6 +546,11 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) { snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id); ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name); + + if (!ctx) { + PrintError("Could not open context to store VMX core\n"); + return -1; + } if (v3_vmx_save_core(info, ctx) == -1) { PrintError("VMX checkpoint failed\n"); @@ -377,7 +563,7 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) { break; } default: - PrintError("Invalid CPU Type (%d)\n", cpu_type); + PrintError("Invalid CPU Type (%d)\n", v3_mach_type); return -1; } @@ -390,10 +576,10 @@ int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) { int ret = 0;; int i = 0; - chkpt = chkpt_open(store, url, SAVE); + chkpt = chkpt_open(vm, store, url, SAVE); if (chkpt == NULL) { - PrintError("Error creating checkpoint store\n"); + PrintError("Error creating checkpoint store for url %s\n",url); return -1; } @@ -407,12 +593,12 @@ int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) { goto out; } - /* - if ((ret = v3_chkpt_save_dev(vm)) == -1) { + + if ((ret = v3_save_vm_devices(vm, chkpt)) == -1) { PrintError("Unable to save devices\n"); goto out; } - */ + if ((ret = save_header(vm, chkpt)) == -1) { PrintError("Unable to save header\n"); @@ -420,12 +606,11 @@ int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) { } 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: @@ -445,7 +630,7 @@ int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) { int i = 0; int ret = 0; - chkpt = chkpt_open(store, url, LOAD); + chkpt = chkpt_open(vm, store, url, LOAD); if (chkpt == NULL) { PrintError("Error creating checkpoint store\n"); @@ -463,12 +648,11 @@ int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) { } - /* Don't handle devices just yet - if (v3_chkpt_load_dev(vm) == -1) { + if ((ret = v3_load_vm_devices(vm, chkpt)) == -1) { PrintError("Unable to load devies\n"); + goto out; } - */ if ((ret = load_header(vm, chkpt)) == -1) { PrintError("Unable to load header\n"); @@ -483,7 +667,7 @@ int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) { } } - out: + out: /* Resume the guest if it was running and we didn't just trash the state*/ if (vm->run_state == VM_RUNNING) { @@ -505,43 +689,3 @@ int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) { -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); -} - - - -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 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 (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; - } - - tmp_store = &(__start__v3_chkpt_stores[++i]); - } - - return 0; -}