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>
31 #include <palacios/vmm_dev_mgr.h>
34 static struct hashtable * store_table = NULL;
38 typedef enum {SAVE, LOAD} chkpt_mode_t;
40 struct chkpt_interface {
42 void * (*open_chkpt)(char * url, chkpt_mode_t mode);
43 int (*close_chkpt)(void * store_data);
45 void * (*open_ctx)(void * store_data, void * parent_ctx, char * name);
46 int (*close_ctx)(void * store_data, void * ctx);
48 int (*save)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
49 int (*load)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
54 struct v3_vm_info * vm;
56 struct chkpt_interface * interface;
64 static uint_t store_hash_fn(addr_t key) {
65 char * name = (char *)key;
66 return v3_hash_buffer((uint8_t *)name, strlen(name));
69 static int store_eq_fn(addr_t key1, addr_t key2) {
70 char * name1 = (char *)key1;
71 char * name2 = (char *)key2;
73 return (strcmp(name1, name2) == 0);
78 #include "vmm_chkpt_stores.h"
81 int V3_init_checkpoint() {
82 extern struct chkpt_interface * __start__v3_chkpt_stores[];
83 extern struct chkpt_interface * __stop__v3_chkpt_stores[];
84 struct chkpt_interface ** tmp_store = __start__v3_chkpt_stores;
87 store_table = v3_create_htable(0, store_hash_fn, store_eq_fn);
89 while (tmp_store != __stop__v3_chkpt_stores) {
90 V3_Print("Registering Checkpoint Backing Store (%s)\n", (*tmp_store)->name);
92 if (v3_htable_search(store_table, (addr_t)((*tmp_store)->name))) {
93 PrintError("Multiple instances of Checkpoint backing Store (%s)\n", (*tmp_store)->name);
97 if (v3_htable_insert(store_table, (addr_t)((*tmp_store)->name), (addr_t)(*tmp_store)) == 0) {
98 PrintError("Could not register Checkpoint backing store (%s)\n", (*tmp_store)->name);
102 tmp_store = &(__start__v3_chkpt_stores[++i]);
108 int V3_deinit_checkpoint() {
109 v3_free_htable(store_table, 0, 0);
114 static char svm_chkpt_header[] = "v3vee palacios checkpoint version: x.x, SVM x.x";
115 static char vmx_chkpt_header[] = "v3vee palacios checkpoint version: x.x, VMX x.x";
117 static int chkpt_close(struct v3_chkpt * chkpt) {
118 chkpt->interface->close_chkpt(chkpt->store_data);
126 static struct v3_chkpt * chkpt_open(struct v3_vm_info * vm, char * store, char * url, chkpt_mode_t mode) {
127 struct chkpt_interface * iface = NULL;
128 struct v3_chkpt * chkpt = NULL;
129 void * store_data = NULL;
131 iface = (void *)v3_htable_search(store_table, (addr_t)store);
134 V3_Print("Error: Could not locate Checkpoint interface for store (%s)\n", store);
138 store_data = iface->open_chkpt(url, mode);
140 if (store_data == NULL) {
141 PrintError("Could not open url (%s) for backing store (%s)\n", url, store);
146 chkpt = V3_Malloc(sizeof(struct v3_chkpt));
149 PrintError("Could not allocate checkpoint state\n");
153 chkpt->interface = iface;
155 chkpt->store_data = store_data;
160 struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, struct v3_chkpt_ctx * parent, char * name) {
161 struct v3_chkpt_ctx * ctx = V3_Malloc(sizeof(struct v3_chkpt_ctx));
162 void * parent_store_ctx = NULL;
166 PrintError("Unable to allocate context\n");
170 memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
173 ctx->parent = parent;
176 parent_store_ctx = parent->store_ctx;
179 ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent_store_ctx, name);
181 if (!(ctx->store_ctx)) {
182 PrintError("Warning: opening underlying representation returned null\n");
188 int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
189 struct v3_chkpt * chkpt = ctx->chkpt;
192 ret = chkpt->interface->close_ctx(chkpt->store_data, ctx->store_ctx);
203 int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
204 struct v3_chkpt * chkpt = ctx->chkpt;
206 return chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf);
211 int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
212 struct v3_chkpt * chkpt = ctx->chkpt;
214 return chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf);
219 static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
221 void * guest_mem_base = NULL;
225 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
227 ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
230 PrintError("Unable to open context for memory load\n");
234 if (v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base) == -1) {
235 PrintError("Unable to load all of memory (requested=%llu bytes, result=%llu bytes\n",(uint64_t)(vm->mem_size),ret);
236 v3_chkpt_close_ctx(ctx);
240 v3_chkpt_close_ctx(ctx);
246 static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
247 void * guest_mem_base = NULL;
251 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
253 ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img");
256 PrintError("Unable to open context to save memory\n");
260 if (v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base) == -1) {
261 PrintError("Unable to load all of memory (requested=%llu, received=%llu)\n",(uint64_t)(vm->mem_size),ret);
262 v3_chkpt_close_ctx(ctx);
266 v3_chkpt_close_ctx(ctx);
271 int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
272 extern v3_cpu_arch_t v3_mach_type;
275 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
277 PrintError("Cannot open context to save header\n");
281 switch (v3_mach_type) {
283 case V3_SVM_REV3_CPU: {
284 if (v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header) == -1) {
285 PrintError("Could not save all of SVM header\n");
286 v3_chkpt_close_ctx(ctx);
293 case V3_VMX_EPT_UG_CPU: {
294 if (v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header) == -1) {
295 PrintError("Could not save all of VMX header\n");
296 v3_chkpt_close_ctx(ctx);
302 PrintError("checkpoint not supported on this architecture\n");
303 v3_chkpt_close_ctx(ctx);
307 v3_chkpt_close_ctx(ctx);
312 static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
313 extern v3_cpu_arch_t v3_mach_type;
316 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
318 switch (v3_mach_type) {
320 case V3_SVM_REV3_CPU: {
321 char header[strlen(svm_chkpt_header) + 1];
323 if (v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header) == -1) {
324 PrintError("Could not load all of SVM header\n");
325 v3_chkpt_close_ctx(ctx);
329 header[strlen(svm_chkpt_header)] = 0;
335 case V3_VMX_EPT_UG_CPU: {
336 char header[strlen(vmx_chkpt_header) + 1];
338 if (v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header) == -1) {
339 PrintError("Could not load all of VMX header\n");
340 v3_chkpt_close_ctx(ctx);
344 header[strlen(vmx_chkpt_header)] = 0;
349 PrintError("checkpoint not supported on this architecture\n");
350 v3_chkpt_close_ctx(ctx);
354 v3_chkpt_close_ctx(ctx);
360 static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
361 extern v3_cpu_arch_t v3_mach_type;
365 memset(key_name, 0, 16);
367 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
369 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
372 PrintError("Could not open context to load core\n");
376 // These really need to have error checking
378 v3_chkpt_load_64(ctx, "RIP", &(info->rip));
380 V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
382 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0);
383 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr2);
384 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr4);
385 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr8);
386 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.rflags);
387 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.efer);
389 V3_CHKPT_STD_LOAD(ctx, info->dbg_regs);
390 V3_CHKPT_STD_LOAD(ctx, info->segments);
391 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr3);
392 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr0);
393 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_efer);
395 v3_chkpt_close_ctx(ctx);
397 PrintDebug("Finished reading guest_info information\n");
399 info->cpu_mode = v3_get_vm_cpu_mode(info);
400 info->mem_mode = v3_get_vm_mem_mode(info);
402 if (info->shdw_pg_mode == SHADOW_PAGING) {
403 if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) {
404 if (v3_activate_shadow_pt(info) == -1) {
405 PrintError("Failed to activate shadow page tables\n");
409 if (v3_activate_passthrough_pt(info) == -1) {
410 PrintError("Failed to activate passthrough page tables\n");
417 switch (v3_mach_type) {
419 case V3_SVM_REV3_CPU: {
422 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
423 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
426 PrintError("Could not open context to load SVM core\n");
430 if (v3_svm_load_core(info, ctx) == -1) {
431 PrintError("Failed to patch core %d\n", info->vcpu_id);
432 v3_chkpt_close_ctx(ctx);
436 v3_chkpt_close_ctx(ctx);
442 case V3_VMX_EPT_UG_CPU: {
445 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
447 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
450 PrintError("Could not open context to load VMX core\n");
454 if (v3_vmx_load_core(info, ctx) < 0) {
455 PrintError("VMX checkpoint failed\n");
456 v3_chkpt_close_ctx(ctx);
460 v3_chkpt_close_ctx(ctx);
465 PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
469 v3_print_guest_state(info);
475 static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
476 extern v3_cpu_arch_t v3_mach_type;
480 memset(key_name, 0, 16);
482 v3_print_guest_state(info);
485 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
487 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
490 PrintError("Unable to open context to save core\n");
495 // Error checking of all this needs to happen
496 v3_chkpt_save_64(ctx, "RIP", &(info->rip));
498 V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
500 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
501 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr2);
502 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr4);
503 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr8);
504 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.rflags);
505 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.efer);
507 V3_CHKPT_STD_SAVE(ctx, info->dbg_regs);
508 V3_CHKPT_STD_SAVE(ctx, info->segments);
509 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr3);
510 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr0);
511 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_efer);
513 v3_chkpt_close_ctx(ctx);
515 //Architechture specific code
516 switch (v3_mach_type) {
518 case V3_SVM_REV3_CPU: {
522 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
524 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
527 PrintError("Could not open context to store SVM core\n");
531 if (v3_svm_save_core(info, ctx) == -1) {
532 PrintError("VMCB Unable to be written\n");
533 v3_chkpt_close_ctx(ctx);
537 v3_chkpt_close_ctx(ctx);
542 case V3_VMX_EPT_UG_CPU: {
546 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
548 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
551 PrintError("Could not open context to store VMX core\n");
555 if (v3_vmx_save_core(info, ctx) == -1) {
556 PrintError("VMX checkpoint failed\n");
557 v3_chkpt_close_ctx(ctx);
561 v3_chkpt_close_ctx(ctx);
566 PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
574 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
575 struct v3_chkpt * chkpt = NULL;
579 chkpt = chkpt_open(vm, store, url, SAVE);
582 PrintError("Error creating checkpoint store for url %s\n",url);
586 /* If this guest is running we need to block it while the checkpoint occurs */
587 if (vm->run_state == VM_RUNNING) {
588 while (v3_raise_barrier(vm, NULL) == -1);
591 if ((ret = save_memory(vm, chkpt)) == -1) {
592 PrintError("Unable to save memory\n");
597 if ((ret = v3_save_vm_devices(vm, chkpt)) == -1) {
598 PrintError("Unable to save devices\n");
603 if ((ret = save_header(vm, chkpt)) == -1) {
604 PrintError("Unable to save header\n");
608 for (i = 0; i < vm->num_cores; i++){
609 if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) {
610 PrintError("chkpt of core %d failed\n", i);
617 /* Resume the guest if it was running */
618 if (vm->run_state == VM_RUNNING) {
619 v3_lower_barrier(vm);
628 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
629 struct v3_chkpt * chkpt = NULL;
633 chkpt = chkpt_open(vm, store, url, LOAD);
636 PrintError("Error creating checkpoint store\n");
640 /* If this guest is running we need to block it while the checkpoint occurs */
641 if (vm->run_state == VM_RUNNING) {
642 while (v3_raise_barrier(vm, NULL) == -1);
645 if ((ret = load_memory(vm, chkpt)) == -1) {
646 PrintError("Unable to save memory\n");
651 if ((ret = v3_load_vm_devices(vm, chkpt)) == -1) {
652 PrintError("Unable to load devies\n");
657 if ((ret = load_header(vm, chkpt)) == -1) {
658 PrintError("Unable to load header\n");
663 for (i = 0; i < vm->num_cores; i++) {
664 if ((ret = load_core(&(vm->cores[i]), chkpt)) == -1) {
665 PrintError("Error loading core state (core=%d)\n", i);
672 /* Resume the guest if it was running and we didn't just trash the state*/
673 if (vm->run_state == VM_RUNNING) {
676 vm->run_state = VM_STOPPED;
679 /* We check the run state of the VM after every barrier
680 So this will immediately halt the VM
682 v3_lower_barrier(vm);