2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2011, Madhav Suresh <madhav@u.northwestern.edu>
11 * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Madhav Suresh <madhav@u.northwestern.edu>
15 * Arefin Huq <fig@arefin.net>
18 * This is free software. You are permitted to use,
19 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_sprintf.h>
24 #include <palacios/vm_guest.h>
25 #include <palacios/svm.h>
26 #include <palacios/vmx.h>
27 #include <palacios/vmm_checkpoint.h>
28 #include <palacios/vmm_hashtable.h>
30 #include <palacios/vmm_dev_mgr.h>
33 static struct hashtable * store_table = NULL;
37 typedef enum {SAVE, LOAD} chkpt_mode_t;
39 struct chkpt_interface {
41 void * (*open_chkpt)(char * url, chkpt_mode_t mode);
42 int (*close_chkpt)(void * store_data);
44 void * (*open_ctx)(void * store_data, void * parent_ctx, char * name);
45 int (*close_ctx)(void * store_data, void * ctx);
47 int (*save)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
48 int (*load)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
53 struct v3_vm_info * vm;
55 struct chkpt_interface * interface;
63 static uint_t store_hash_fn(addr_t key) {
64 char * name = (char *)key;
65 return v3_hash_buffer((uint8_t *)name, strlen(name));
68 static int store_eq_fn(addr_t key1, addr_t key2) {
69 char * name1 = (char *)key1;
70 char * name2 = (char *)key2;
72 return (strcmp(name1, name2) == 0);
77 #include "vmm_chkpt_stores.h"
80 int V3_init_checkpoint() {
81 extern struct chkpt_interface * __start__v3_chkpt_stores[];
82 extern struct chkpt_interface * __stop__v3_chkpt_stores[];
83 struct chkpt_interface ** tmp_store = __start__v3_chkpt_stores;
86 store_table = v3_create_htable(0, store_hash_fn, store_eq_fn);
88 while (tmp_store != __stop__v3_chkpt_stores) {
89 V3_Print("Registering Checkpoint Backing Store (%s)\n", (*tmp_store)->name);
91 if (v3_htable_search(store_table, (addr_t)((*tmp_store)->name))) {
92 PrintError("Multiple instances of Checkpoint backing Store (%s)\n", (*tmp_store)->name);
96 if (v3_htable_insert(store_table, (addr_t)((*tmp_store)->name), (addr_t)(*tmp_store)) == 0) {
97 PrintError("Could not register Checkpoint backing store (%s)\n", (*tmp_store)->name);
101 tmp_store = &(__start__v3_chkpt_stores[++i]);
107 int V3_deinit_checkpoint() {
108 v3_free_htable(store_table, 0, 0);
113 static char svm_chkpt_header[] = "v3vee palacios checkpoint version: x.x, SVM x.x";
114 static char vmx_chkpt_header[] = "v3vee palacios checkpoint version: x.x, VMX x.x";
116 static int chkpt_close(struct v3_chkpt * chkpt) {
117 chkpt->interface->close_chkpt(chkpt->store_data);
125 static struct v3_chkpt * chkpt_open(struct v3_vm_info * vm, char * store, char * url, chkpt_mode_t mode) {
126 struct chkpt_interface * iface = NULL;
127 struct v3_chkpt * chkpt = NULL;
128 void * store_data = NULL;
130 iface = (void *)v3_htable_search(store_table, (addr_t)store);
133 V3_Print("Error: Could not locate Checkpoint interface for store (%s)\n", store);
137 store_data = iface->open_chkpt(url, mode);
139 if (store_data == NULL) {
140 PrintError("Could not open url (%s) for backing store (%s)\n", url, store);
145 chkpt = V3_Malloc(sizeof(struct v3_chkpt));
148 PrintError("Could not allocate checkpoint state\n");
152 chkpt->interface = iface;
154 chkpt->store_data = store_data;
159 struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, struct v3_chkpt_ctx * parent, char * name) {
160 struct v3_chkpt_ctx * ctx = V3_Malloc(sizeof(struct v3_chkpt_ctx));
161 void * parent_store_ctx = NULL;
163 memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
166 ctx->parent = parent;
169 parent_store_ctx = parent->store_ctx;
172 ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent_store_ctx, name);
177 int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
178 struct v3_chkpt * chkpt = ctx->chkpt;
181 ret = chkpt->interface->close_ctx(chkpt->store_data, ctx->store_ctx);
192 int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
193 struct v3_chkpt * chkpt = ctx->chkpt;
194 return chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf);
198 int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
199 struct v3_chkpt * chkpt = ctx->chkpt;
200 return chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf);
205 static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
207 void * guest_mem_base = NULL;
211 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
213 ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
215 ret = v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base);
216 v3_chkpt_close_ctx(ctx);
222 static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
223 void * guest_mem_base = NULL;
227 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
229 ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img");
232 ret = v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base);
233 v3_chkpt_close_ctx(ctx);
238 int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
239 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
242 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
246 case V3_SVM_REV3_CPU: {
247 v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
252 case V3_VMX_EPT_UG_CPU: {
253 v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header);
257 PrintError("checkpoint not supported on this architecture\n");
258 v3_chkpt_close_ctx(ctx);
262 v3_chkpt_close_ctx(ctx);
267 static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
268 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
271 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
275 case V3_SVM_REV3_CPU: {
276 char header[strlen(svm_chkpt_header) + 1];
278 v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header);
284 case V3_VMX_EPT_UG_CPU: {
285 char header[strlen(vmx_chkpt_header) + 1];
287 v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header);
292 PrintError("checkpoint not supported on this architecture\n");
293 v3_chkpt_close_ctx(ctx);
297 v3_chkpt_close_ctx(ctx);
303 static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
304 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
307 memset(key_name, 0, 16);
309 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
311 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
313 V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
315 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0);
316 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr2);
317 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr4);
318 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr8);
319 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.rflags);
320 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.efer);
322 V3_CHKPT_STD_LOAD(ctx, info->dbg_regs);
323 V3_CHKPT_STD_LOAD(ctx, info->segments);
324 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr3);
325 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr0);
326 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_efer);
327 v3_chkpt_close_ctx(ctx);
329 PrintDebug("Finished reading guest_info information\n");
331 info->cpu_mode = v3_get_vm_cpu_mode(info);
332 info->mem_mode = v3_get_vm_mem_mode(info);
337 case V3_SVM_REV3_CPU: {
340 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
341 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
343 if (v3_svm_load_core(info, ctx) == -1) {
344 PrintError("Failed to patch core %d\n", info->vcpu_id);
348 v3_chkpt_close_ctx(ctx);
354 case V3_VMX_EPT_UG_CPU: {
357 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
358 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
360 if (v3_vmx_load_core(info, ctx) < 0) {
361 PrintError("VMX checkpoint failed\n");
365 v3_chkpt_close_ctx(ctx);
370 PrintError("Invalid CPU Type (%d)\n", cpu_type);
378 static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
379 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
383 memset(key_name, 0, 16);
386 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
388 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
390 V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
392 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
393 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr2);
394 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr4);
395 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr8);
396 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.rflags);
397 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.efer);
399 V3_CHKPT_STD_SAVE(ctx, info->dbg_regs);
400 V3_CHKPT_STD_SAVE(ctx, info->segments);
401 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr3);
402 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr0);
403 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_efer);
405 v3_chkpt_close_ctx(ctx);
407 //Architechture specific code
410 case V3_SVM_REV3_CPU: {
414 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
416 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
418 if (v3_svm_save_core(info, ctx) == -1) {
419 PrintError("VMCB Unable to be written\n");
420 v3_chkpt_close_ctx(ctx);
424 v3_chkpt_close_ctx(ctx);
429 case V3_VMX_EPT_UG_CPU: {
433 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
435 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
437 if (v3_vmx_save_core(info, ctx) == -1) {
438 PrintError("VMX checkpoint failed\n");
439 v3_chkpt_close_ctx(ctx);
443 v3_chkpt_close_ctx(ctx);
448 PrintError("Invalid CPU Type (%d)\n", cpu_type);
456 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
457 struct v3_chkpt * chkpt = NULL;
461 chkpt = chkpt_open(vm, store, url, SAVE);
464 PrintError("Error creating checkpoint store\n");
468 /* If this guest is running we need to block it while the checkpoint occurs */
469 if (vm->run_state == VM_RUNNING) {
470 while (v3_raise_barrier(vm, NULL) == -1);
473 if ((ret = save_memory(vm, chkpt)) == -1) {
474 PrintError("Unable to save memory\n");
479 if ((ret = v3_save_vm_devices(vm, chkpt)) == -1) {
480 PrintError("Unable to save devices\n");
485 if ((ret = save_header(vm, chkpt)) == -1) {
486 PrintError("Unable to save header\n");
490 for (i = 0; i < vm->num_cores; i++){
491 if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) {
492 PrintError("chkpt of core %d failed\n", i);
499 /* Resume the guest if it was running */
500 if (vm->run_state == VM_RUNNING) {
501 v3_lower_barrier(vm);
510 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
511 struct v3_chkpt * chkpt = NULL;
515 chkpt = chkpt_open(vm, store, url, LOAD);
518 PrintError("Error creating checkpoint store\n");
522 /* If this guest is running we need to block it while the checkpoint occurs */
523 if (vm->run_state == VM_RUNNING) {
524 while (v3_raise_barrier(vm, NULL) == -1);
527 if ((ret = load_memory(vm, chkpt)) == -1) {
528 PrintError("Unable to save memory\n");
533 if ((ret = v3_load_vm_devices(vm, chkpt)) == -1) {
534 PrintError("Unable to load devies\n");
539 if ((ret = load_header(vm, chkpt)) == -1) {
540 PrintError("Unable to load header\n");
545 for (i = 0; i < vm->num_cores; i++) {
546 if ((ret = load_core(&(vm->cores[i]), chkpt)) == -1) {
547 PrintError("Error loading core state (core=%d)\n", i);
554 /* Resume the guest if it was running and we didn't just trash the state*/
555 if (vm->run_state == VM_RUNNING) {
558 vm->run_state = VM_STOPPED;
561 /* We check the run state of the VM after every barrier
562 So this will immediately halt the VM
564 v3_lower_barrier(vm);