#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;
+ }
+
+
+ chkpt = V3_Malloc(sizeof(struct v3_chkpt));
+
+ if (!chkpt) {
+ PrintError("Could not allocate checkpoint state\n");
+ return NULL;
+ }
- PrintError("Not yet implemented\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;
}
}
-/* 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) {
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;
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) {
- 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: {
v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
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());
+ 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];
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);
ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+ 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);
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];
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);
+ v3_chkpt_save_64(ctx, "RIP", &(info->rip));
+
V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
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];
break;
}
default:
- PrintError("Invalid CPU Type (%d)\n", cpu_type);
+ PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
return -1;
}
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 (load_header(vm, chkpt) == -1) {
- PrintError("Unable to load header\n");
+ if ((ret = save_memory(vm, chkpt)) == -1) {
+ PrintError("Unable to save memory\n");
+ goto out;
+ }
+
+
+ if ((ret = v3_save_vm_devices(vm, chkpt)) == -1) {
+ PrintError("Unable to save devices\n");
+ goto out;
}
+
- //per core cloning
- for (i = 0; i < vm->num_cores; i++) {
- if (load_core(&(vm->cores[i]), chkpt) == -1) {
- return -1;
+ if ((ret = save_header(vm, chkpt)) == -1) {
+ PrintError("Unable to save header\n");
+ goto out;
+ }
+
+ 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);
+ if ((ret = v3_load_vm_devices(vm, chkpt)) == -1) {
+ PrintError("Unable to load devies\n");
+ goto out;
+ }
- 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;
}
+
+
+