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;
164 memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
167 ctx->parent = parent;
170 parent_store_ctx = parent->store_ctx;
173 ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent_store_ctx, name);
178 int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
179 struct v3_chkpt * chkpt = ctx->chkpt;
182 ret = chkpt->interface->close_ctx(chkpt->store_data, ctx->store_ctx);
193 int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
194 struct v3_chkpt * chkpt = ctx->chkpt;
195 return chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf);
199 int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
200 struct v3_chkpt * chkpt = ctx->chkpt;
201 return chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf);
206 static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
208 void * guest_mem_base = NULL;
212 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
214 ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
216 ret = v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base);
217 v3_chkpt_close_ctx(ctx);
223 static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
224 void * guest_mem_base = NULL;
228 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
230 ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img");
233 ret = v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base);
234 v3_chkpt_close_ctx(ctx);
239 int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
240 extern v3_cpu_arch_t v3_mach_type;
243 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
245 switch (v3_mach_type) {
247 case V3_SVM_REV3_CPU: {
248 v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
253 case V3_VMX_EPT_UG_CPU: {
254 v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header);
258 PrintError("checkpoint not supported on this architecture\n");
259 v3_chkpt_close_ctx(ctx);
263 v3_chkpt_close_ctx(ctx);
268 static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
269 extern v3_cpu_arch_t v3_mach_type;
272 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
274 switch (v3_mach_type) {
276 case V3_SVM_REV3_CPU: {
277 char header[strlen(svm_chkpt_header) + 1];
279 v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header);
285 case V3_VMX_EPT_UG_CPU: {
286 char header[strlen(vmx_chkpt_header) + 1];
288 v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header);
293 PrintError("checkpoint not supported on this architecture\n");
294 v3_chkpt_close_ctx(ctx);
298 v3_chkpt_close_ctx(ctx);
304 static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
305 extern v3_cpu_arch_t v3_mach_type;
308 memset(key_name, 0, 16);
310 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
312 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
314 v3_chkpt_load_64(ctx, "RIP", &(info->rip));
316 V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
318 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0);
319 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr2);
320 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr4);
321 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr8);
322 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.rflags);
323 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.efer);
325 V3_CHKPT_STD_LOAD(ctx, info->dbg_regs);
326 V3_CHKPT_STD_LOAD(ctx, info->segments);
327 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr3);
328 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr0);
329 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_efer);
330 v3_chkpt_close_ctx(ctx);
332 PrintDebug("Finished reading guest_info information\n");
334 info->cpu_mode = v3_get_vm_cpu_mode(info);
335 info->mem_mode = v3_get_vm_mem_mode(info);
337 if (info->shdw_pg_mode == SHADOW_PAGING) {
338 if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) {
339 if (v3_activate_shadow_pt(info) == -1) {
340 PrintError("Failed to activate shadow page tables\n");
344 if (v3_activate_passthrough_pt(info) == -1) {
345 PrintError("Failed to activate passthrough page tables\n");
352 switch (v3_mach_type) {
354 case V3_SVM_REV3_CPU: {
357 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
358 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
360 if (v3_svm_load_core(info, ctx) == -1) {
361 PrintError("Failed to patch core %d\n", info->vcpu_id);
365 v3_chkpt_close_ctx(ctx);
371 case V3_VMX_EPT_UG_CPU: {
374 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
375 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
377 if (v3_vmx_load_core(info, ctx) < 0) {
378 PrintError("VMX checkpoint failed\n");
382 v3_chkpt_close_ctx(ctx);
387 PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
391 v3_print_guest_state(info);
397 static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
398 extern v3_cpu_arch_t v3_mach_type;
402 memset(key_name, 0, 16);
404 v3_print_guest_state(info);
407 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
409 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
411 v3_chkpt_save_64(ctx, "RIP", &(info->rip));
413 V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
415 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
416 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr2);
417 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr4);
418 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr8);
419 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.rflags);
420 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.efer);
422 V3_CHKPT_STD_SAVE(ctx, info->dbg_regs);
423 V3_CHKPT_STD_SAVE(ctx, info->segments);
424 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr3);
425 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr0);
426 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_efer);
428 v3_chkpt_close_ctx(ctx);
430 //Architechture specific code
431 switch (v3_mach_type) {
433 case V3_SVM_REV3_CPU: {
437 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
439 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
441 if (v3_svm_save_core(info, ctx) == -1) {
442 PrintError("VMCB Unable to be written\n");
443 v3_chkpt_close_ctx(ctx);
447 v3_chkpt_close_ctx(ctx);
452 case V3_VMX_EPT_UG_CPU: {
456 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
458 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
460 if (v3_vmx_save_core(info, ctx) == -1) {
461 PrintError("VMX checkpoint failed\n");
462 v3_chkpt_close_ctx(ctx);
466 v3_chkpt_close_ctx(ctx);
471 PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
479 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
480 struct v3_chkpt * chkpt = NULL;
484 chkpt = chkpt_open(vm, store, url, SAVE);
487 PrintError("Error creating checkpoint store\n");
491 /* If this guest is running we need to block it while the checkpoint occurs */
492 if (vm->run_state == VM_RUNNING) {
493 while (v3_raise_barrier(vm, NULL) == -1);
496 if ((ret = save_memory(vm, chkpt)) == -1) {
497 PrintError("Unable to save memory\n");
502 if ((ret = v3_save_vm_devices(vm, chkpt)) == -1) {
503 PrintError("Unable to save devices\n");
508 if ((ret = save_header(vm, chkpt)) == -1) {
509 PrintError("Unable to save header\n");
513 for (i = 0; i < vm->num_cores; i++){
514 if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) {
515 PrintError("chkpt of core %d failed\n", i);
522 /* Resume the guest if it was running */
523 if (vm->run_state == VM_RUNNING) {
524 v3_lower_barrier(vm);
533 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
534 struct v3_chkpt * chkpt = NULL;
538 chkpt = chkpt_open(vm, store, url, LOAD);
541 PrintError("Error creating checkpoint store\n");
545 /* If this guest is running we need to block it while the checkpoint occurs */
546 if (vm->run_state == VM_RUNNING) {
547 while (v3_raise_barrier(vm, NULL) == -1);
550 if ((ret = load_memory(vm, chkpt)) == -1) {
551 PrintError("Unable to save memory\n");
556 if ((ret = v3_load_vm_devices(vm, chkpt)) == -1) {
557 PrintError("Unable to load devies\n");
562 if ((ret = load_header(vm, chkpt)) == -1) {
563 PrintError("Unable to load header\n");
568 for (i = 0; i < vm->num_cores; i++) {
569 if ((ret = load_core(&(vm->cores[i]), chkpt)) == -1) {
570 PrintError("Error loading core state (core=%d)\n", i);
577 /* Resume the guest if it was running and we didn't just trash the state*/
578 if (vm->run_state == VM_RUNNING) {
581 vm->run_state = VM_STOPPED;
584 /* We check the run state of the VM after every barrier
585 So this will immediately halt the VM
587 v3_lower_barrier(vm);