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>
29 #include <palacios/vmm_direct_paging.h>
30 #include <palacios/vmm_debug.h>
32 #include <palacios/vmm_dev_mgr.h>
35 static struct hashtable * store_table = NULL;
39 typedef enum {SAVE, LOAD} chkpt_mode_t;
41 struct chkpt_interface {
43 void * (*open_chkpt)(char * url, chkpt_mode_t mode);
44 int (*close_chkpt)(void * store_data);
46 void * (*open_ctx)(void * store_data, void * parent_ctx, char * name);
47 int (*close_ctx)(void * store_data, void * ctx);
49 int (*save)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
50 int (*load)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
55 struct v3_vm_info * vm;
57 struct chkpt_interface * interface;
65 static uint_t store_hash_fn(addr_t key) {
66 char * name = (char *)key;
67 return v3_hash_buffer((uint8_t *)name, strlen(name));
70 static int store_eq_fn(addr_t key1, addr_t key2) {
71 char * name1 = (char *)key1;
72 char * name2 = (char *)key2;
74 return (strcmp(name1, name2) == 0);
79 #include "vmm_chkpt_stores.h"
82 int V3_init_checkpoint() {
83 extern struct chkpt_interface * __start__v3_chkpt_stores[];
84 extern struct chkpt_interface * __stop__v3_chkpt_stores[];
85 struct chkpt_interface ** tmp_store = __start__v3_chkpt_stores;
88 store_table = v3_create_htable(0, store_hash_fn, store_eq_fn);
90 while (tmp_store != __stop__v3_chkpt_stores) {
91 V3_Print("Registering Checkpoint Backing Store (%s)\n", (*tmp_store)->name);
93 if (v3_htable_search(store_table, (addr_t)((*tmp_store)->name))) {
94 PrintError("Multiple instances of Checkpoint backing Store (%s)\n", (*tmp_store)->name);
98 if (v3_htable_insert(store_table, (addr_t)((*tmp_store)->name), (addr_t)(*tmp_store)) == 0) {
99 PrintError("Could not register Checkpoint backing store (%s)\n", (*tmp_store)->name);
103 tmp_store = &(__start__v3_chkpt_stores[++i]);
109 int V3_deinit_checkpoint() {
110 v3_free_htable(store_table, 0, 0);
115 static char svm_chkpt_header[] = "v3vee palacios checkpoint version: x.x, SVM x.x";
116 static char vmx_chkpt_header[] = "v3vee palacios checkpoint version: x.x, VMX x.x";
118 static int chkpt_close(struct v3_chkpt * chkpt) {
119 chkpt->interface->close_chkpt(chkpt->store_data);
127 static struct v3_chkpt * chkpt_open(struct v3_vm_info * vm, char * store, char * url, chkpt_mode_t mode) {
128 struct chkpt_interface * iface = NULL;
129 struct v3_chkpt * chkpt = NULL;
130 void * store_data = NULL;
132 iface = (void *)v3_htable_search(store_table, (addr_t)store);
135 V3_Print("Error: Could not locate Checkpoint interface for store (%s)\n", store);
139 store_data = iface->open_chkpt(url, mode);
141 if (store_data == NULL) {
142 PrintError("Could not open url (%s) for backing store (%s)\n", url, store);
147 chkpt = V3_Malloc(sizeof(struct v3_chkpt));
150 PrintError("Could not allocate checkpoint state\n");
154 chkpt->interface = iface;
156 chkpt->store_data = store_data;
161 struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, struct v3_chkpt_ctx * parent, char * name) {
162 struct v3_chkpt_ctx * ctx = V3_Malloc(sizeof(struct v3_chkpt_ctx));
163 void * parent_store_ctx = NULL;
167 PrintError("Unable to allocate context\n");
171 memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
174 ctx->parent = parent;
177 parent_store_ctx = parent->store_ctx;
180 ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent_store_ctx, name);
182 if (!(ctx->store_ctx)) {
183 PrintError("Warning: opening underlying representation returned null\n");
189 int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
190 struct v3_chkpt * chkpt = ctx->chkpt;
193 ret = chkpt->interface->close_ctx(chkpt->store_data, ctx->store_ctx);
204 int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
205 struct v3_chkpt * chkpt = ctx->chkpt;
207 return chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf);
212 int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
213 struct v3_chkpt * chkpt = ctx->chkpt;
215 return chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf);
220 static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
222 void * guest_mem_base = NULL;
226 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
228 ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
231 PrintError("Unable to open context for memory load\n");
235 if (v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base) == -1) {
236 PrintError("Unable to load all of memory (requested=%llu bytes, result=%llu bytes\n",(uint64_t)(vm->mem_size),ret);
237 v3_chkpt_close_ctx(ctx);
241 v3_chkpt_close_ctx(ctx);
247 static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
248 void * guest_mem_base = NULL;
252 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
254 ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img");
257 PrintError("Unable to open context to save memory\n");
261 if (v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base) == -1) {
262 PrintError("Unable to load all of memory (requested=%llu, received=%llu)\n",(uint64_t)(vm->mem_size),ret);
263 v3_chkpt_close_ctx(ctx);
267 v3_chkpt_close_ctx(ctx);
272 int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
273 extern v3_cpu_arch_t v3_mach_type;
276 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
278 PrintError("Cannot open context to save header\n");
282 switch (v3_mach_type) {
284 case V3_SVM_REV3_CPU: {
285 if (v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header) == -1) {
286 PrintError("Could not save all of SVM header\n");
287 v3_chkpt_close_ctx(ctx);
294 case V3_VMX_EPT_UG_CPU: {
295 if (v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header) == -1) {
296 PrintError("Could not save all of VMX header\n");
297 v3_chkpt_close_ctx(ctx);
303 PrintError("checkpoint not supported on this architecture\n");
304 v3_chkpt_close_ctx(ctx);
308 v3_chkpt_close_ctx(ctx);
313 static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
314 extern v3_cpu_arch_t v3_mach_type;
317 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
319 switch (v3_mach_type) {
321 case V3_SVM_REV3_CPU: {
322 char header[strlen(svm_chkpt_header) + 1];
324 if (v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header) == -1) {
325 PrintError("Could not load all of SVM header\n");
326 v3_chkpt_close_ctx(ctx);
330 header[strlen(svm_chkpt_header)] = 0;
336 case V3_VMX_EPT_UG_CPU: {
337 char header[strlen(vmx_chkpt_header) + 1];
339 if (v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header) == -1) {
340 PrintError("Could not load all of VMX header\n");
341 v3_chkpt_close_ctx(ctx);
345 header[strlen(vmx_chkpt_header)] = 0;
350 PrintError("checkpoint not supported on this architecture\n");
351 v3_chkpt_close_ctx(ctx);
355 v3_chkpt_close_ctx(ctx);
361 static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
362 extern v3_cpu_arch_t v3_mach_type;
366 memset(key_name, 0, 16);
368 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
370 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
373 PrintError("Could not open context to load core\n");
377 // These really need to have error checking
379 v3_chkpt_load_64(ctx, "RIP", &(info->rip));
381 V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
383 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0);
384 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr2);
385 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr4);
386 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr8);
387 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.rflags);
388 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.efer);
390 V3_CHKPT_STD_LOAD(ctx, info->dbg_regs);
391 V3_CHKPT_STD_LOAD(ctx, info->segments);
392 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr3);
393 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr0);
394 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_efer);
396 v3_chkpt_close_ctx(ctx);
398 PrintDebug("Finished reading guest_info information\n");
400 info->cpu_mode = v3_get_vm_cpu_mode(info);
401 info->mem_mode = v3_get_vm_mem_mode(info);
403 if (info->shdw_pg_mode == SHADOW_PAGING) {
404 if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) {
405 if (v3_activate_shadow_pt(info) == -1) {
406 PrintError("Failed to activate shadow page tables\n");
410 if (v3_activate_passthrough_pt(info) == -1) {
411 PrintError("Failed to activate passthrough page tables\n");
418 switch (v3_mach_type) {
420 case V3_SVM_REV3_CPU: {
423 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
424 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
427 PrintError("Could not open context to load SVM core\n");
431 if (v3_svm_load_core(info, ctx) == -1) {
432 PrintError("Failed to patch core %d\n", info->vcpu_id);
433 v3_chkpt_close_ctx(ctx);
437 v3_chkpt_close_ctx(ctx);
443 case V3_VMX_EPT_UG_CPU: {
446 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
448 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
451 PrintError("Could not open context to load VMX core\n");
455 if (v3_vmx_load_core(info, ctx) < 0) {
456 PrintError("VMX checkpoint failed\n");
457 v3_chkpt_close_ctx(ctx);
461 v3_chkpt_close_ctx(ctx);
466 PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
470 v3_print_guest_state(info);
476 static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
477 extern v3_cpu_arch_t v3_mach_type;
481 memset(key_name, 0, 16);
483 v3_print_guest_state(info);
486 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
488 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
491 PrintError("Unable to open context to save core\n");
496 // Error checking of all this needs to happen
497 v3_chkpt_save_64(ctx, "RIP", &(info->rip));
499 V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
501 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
502 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr2);
503 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr4);
504 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr8);
505 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.rflags);
506 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.efer);
508 V3_CHKPT_STD_SAVE(ctx, info->dbg_regs);
509 V3_CHKPT_STD_SAVE(ctx, info->segments);
510 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr3);
511 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr0);
512 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_efer);
514 v3_chkpt_close_ctx(ctx);
516 //Architechture specific code
517 switch (v3_mach_type) {
519 case V3_SVM_REV3_CPU: {
523 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
525 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
528 PrintError("Could not open context to store SVM core\n");
532 if (v3_svm_save_core(info, ctx) == -1) {
533 PrintError("VMCB Unable to be written\n");
534 v3_chkpt_close_ctx(ctx);
538 v3_chkpt_close_ctx(ctx);
543 case V3_VMX_EPT_UG_CPU: {
547 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
549 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
552 PrintError("Could not open context to store VMX core\n");
556 if (v3_vmx_save_core(info, ctx) == -1) {
557 PrintError("VMX checkpoint failed\n");
558 v3_chkpt_close_ctx(ctx);
562 v3_chkpt_close_ctx(ctx);
567 PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
575 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
576 struct v3_chkpt * chkpt = NULL;
580 chkpt = chkpt_open(vm, store, url, SAVE);
583 PrintError("Error creating checkpoint store for url %s\n",url);
587 /* If this guest is running we need to block it while the checkpoint occurs */
588 if (vm->run_state == VM_RUNNING) {
589 while (v3_raise_barrier(vm, NULL) == -1);
592 if ((ret = save_memory(vm, chkpt)) == -1) {
593 PrintError("Unable to save memory\n");
598 if ((ret = v3_save_vm_devices(vm, chkpt)) == -1) {
599 PrintError("Unable to save devices\n");
604 if ((ret = save_header(vm, chkpt)) == -1) {
605 PrintError("Unable to save header\n");
609 for (i = 0; i < vm->num_cores; i++){
610 if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) {
611 PrintError("chkpt of core %d failed\n", i);
618 /* Resume the guest if it was running */
619 if (vm->run_state == VM_RUNNING) {
620 v3_lower_barrier(vm);
629 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
630 struct v3_chkpt * chkpt = NULL;
634 chkpt = chkpt_open(vm, store, url, LOAD);
637 PrintError("Error creating checkpoint store\n");
641 /* If this guest is running we need to block it while the checkpoint occurs */
642 if (vm->run_state == VM_RUNNING) {
643 while (v3_raise_barrier(vm, NULL) == -1);
646 if ((ret = load_memory(vm, chkpt)) == -1) {
647 PrintError("Unable to save memory\n");
652 if ((ret = v3_load_vm_devices(vm, chkpt)) == -1) {
653 PrintError("Unable to load devies\n");
658 if ((ret = load_header(vm, chkpt)) == -1) {
659 PrintError("Unable to load header\n");
664 for (i = 0; i < vm->num_cores; i++) {
665 if ((ret = load_core(&(vm->cores[i]), chkpt)) == -1) {
666 PrintError("Error loading core state (core=%d)\n", i);
673 /* Resume the guest if it was running and we didn't just trash the state*/
674 if (vm->run_state == VM_RUNNING) {
677 vm->run_state = VM_STOPPED;
680 /* We check the run state of the VM after every barrier
681 So this will immediately halt the VM
683 v3_lower_barrier(vm);