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);
190 #define V3_CHKPT_STD_SAVE(ctx,x) v3_chkpt_save(ctx,#x,sizeof(x),&(x))
191 #define V3_CHKPT_STD_LOAD(ctx,x) v3_chkpt_load(ctx,#x,sizeof(x),&(x))
194 int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
195 struct v3_chkpt * chkpt = ctx->chkpt;
196 return chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf);
200 int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
201 struct v3_chkpt * chkpt = ctx->chkpt;
202 return chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf);
207 static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
209 void * guest_mem_base = NULL;
213 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
215 ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
217 ret = v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base);
218 v3_chkpt_close_ctx(ctx);
224 static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
225 void * guest_mem_base = NULL;
229 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
231 ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img");
234 ret = v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base);
235 v3_chkpt_close_ctx(ctx);
240 int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
241 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
244 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
248 case V3_SVM_REV3_CPU: {
249 v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
254 case V3_VMX_EPT_UG_CPU: {
255 v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header);
259 PrintError("checkpoint not supported on this architecture\n");
260 v3_chkpt_close_ctx(ctx);
264 v3_chkpt_close_ctx(ctx);
269 static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
270 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
273 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
277 case V3_SVM_REV3_CPU: {
278 char header[strlen(svm_chkpt_header) + 1];
280 v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header);
286 case V3_VMX_EPT_UG_CPU: {
287 char header[strlen(vmx_chkpt_header) + 1];
289 v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header);
294 PrintError("checkpoint not supported on this architecture\n");
295 v3_chkpt_close_ctx(ctx);
299 v3_chkpt_close_ctx(ctx);
305 static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
306 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
309 memset(key_name, 0, 16);
311 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
313 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
315 V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
317 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0);
318 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr2);
319 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr4);
320 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr8);
321 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.rflags);
322 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.efer);
324 V3_CHKPT_STD_LOAD(ctx, info->dbg_regs);
325 V3_CHKPT_STD_LOAD(ctx, info->segments);
326 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr3);
327 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr0);
328 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_efer);
329 v3_chkpt_close_ctx(ctx);
331 PrintDebug("Finished reading guest_info information\n");
333 info->cpu_mode = v3_get_vm_cpu_mode(info);
334 info->mem_mode = v3_get_vm_mem_mode(info);
339 case V3_SVM_REV3_CPU: {
342 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
343 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
345 if (v3_svm_load_core(info, ctx) == -1) {
346 PrintError("Failed to patch core %d\n", info->vcpu_id);
350 v3_chkpt_close_ctx(ctx);
356 case V3_VMX_EPT_UG_CPU: {
359 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
360 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
362 if (v3_vmx_load_core(info, ctx) < 0) {
363 PrintError("VMX checkpoint failed\n");
367 v3_chkpt_close_ctx(ctx);
372 PrintError("Invalid CPU Type (%d)\n", cpu_type);
380 static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
381 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
385 memset(key_name, 0, 16);
388 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
390 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
392 V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
394 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
395 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr2);
396 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr4);
397 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr8);
398 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.rflags);
399 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.efer);
401 V3_CHKPT_STD_SAVE(ctx, info->dbg_regs);
402 V3_CHKPT_STD_SAVE(ctx, info->segments);
403 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr3);
404 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr0);
405 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_efer);
407 v3_chkpt_close_ctx(ctx);
409 //Architechture specific code
412 case V3_SVM_REV3_CPU: {
416 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
418 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
420 if (v3_svm_save_core(info, ctx) == -1) {
421 PrintError("VMCB Unable to be written\n");
422 v3_chkpt_close_ctx(ctx);
426 v3_chkpt_close_ctx(ctx);
431 case V3_VMX_EPT_UG_CPU: {
435 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
437 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
439 if (v3_vmx_save_core(info, ctx) == -1) {
440 PrintError("VMX checkpoint failed\n");
441 v3_chkpt_close_ctx(ctx);
445 v3_chkpt_close_ctx(ctx);
450 PrintError("Invalid CPU Type (%d)\n", cpu_type);
458 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
459 struct v3_chkpt * chkpt = NULL;
463 chkpt = chkpt_open(vm, store, url, SAVE);
466 PrintError("Error creating checkpoint store\n");
470 /* If this guest is running we need to block it while the checkpoint occurs */
471 if (vm->run_state == VM_RUNNING) {
472 while (v3_raise_barrier(vm, NULL) == -1);
475 if ((ret = save_memory(vm, chkpt)) == -1) {
476 PrintError("Unable to save memory\n");
481 if ((ret = v3_chkpt_save_dev(vm)) == -1) {
482 PrintError("Unable to save devices\n");
487 if ((ret = save_header(vm, chkpt)) == -1) {
488 PrintError("Unable to save header\n");
492 for (i = 0; i < vm->num_cores; i++){
494 if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) {
495 PrintError("chkpt of core %d failed\n", i);
502 /* Resume the guest if it was running */
503 if (vm->run_state == VM_RUNNING) {
504 v3_lower_barrier(vm);
513 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
514 struct v3_chkpt * chkpt = NULL;
518 chkpt = chkpt_open(vm, store, url, LOAD);
521 PrintError("Error creating checkpoint store\n");
525 /* If this guest is running we need to block it while the checkpoint occurs */
526 if (vm->run_state == VM_RUNNING) {
527 while (v3_raise_barrier(vm, NULL) == -1);
530 if ((ret = load_memory(vm, chkpt)) == -1) {
531 PrintError("Unable to save memory\n");
536 /* Don't handle devices just yet
537 if (v3_chkpt_load_dev(vm) == -1) {
538 PrintError("Unable to load devies\n");
543 if ((ret = load_header(vm, chkpt)) == -1) {
544 PrintError("Unable to load header\n");
549 for (i = 0; i < vm->num_cores; i++) {
550 if ((ret = load_core(&(vm->cores[i]), chkpt)) == -1) {
551 PrintError("Error loading core state (core=%d)\n", i);
558 /* Resume the guest if it was running and we didn't just trash the state*/
559 if (vm->run_state == VM_RUNNING) {
562 vm->run_state = VM_STOPPED;
565 /* We check the run state of the VM after every barrier
566 So this will immediately halt the VM
568 v3_lower_barrier(vm);