#include <palacios/vmx.h>
#include <palacios/vmm_checkpoint.h>
#include <palacios/vmm_hashtable.h>
+#include <palacios/vmm_direct_paging.h>
#include <palacios/vmm_dev_mgr.h>
};
+
+
+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";
}
-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;
}
}
-/* 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);
}
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;
}
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:
}
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;
}
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;
}
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);
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");
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;
}
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;
}
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);
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];
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");
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");
break;
}
default:
- PrintError("Invalid CPU Type (%d)\n", cpu_type);
+ PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
return -1;
}
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;
}
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");
}
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:
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");
}
- /* 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");
}
}
- out:
+ out:
/* Resume the guest if it was running and we didn't just trash the state*/
if (vm->run_state == VM_RUNNING) {
-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;
-}