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;
61 #include "vmm_chkpt_stores.h"
64 static char svm_chkpt_header[] = "v3vee palacios checkpoint version: x.x, SVM x.x";
65 static char vmx_chkpt_header[] = "v3vee palacios checkpoint version: x.x, VMX x.x";
67 static int chkpt_close(struct v3_chkpt * chkpt) {
68 chkpt->interface->close_chkpt(chkpt->store_data);
76 static struct v3_chkpt * chkpt_open(char * store, char * url, chkpt_mode_t mode) {
78 // search for checkpoint interface
80 PrintError("Not yet implemented\n");
84 struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, struct v3_chkpt_ctx * parent, char * name) {
85 struct v3_chkpt_ctx * ctx = V3_Malloc(sizeof(struct v3_chkpt_ctx));
87 memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
92 ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent->store_ctx, name);
97 int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
98 struct v3_chkpt * chkpt = ctx->chkpt;
101 ret = chkpt->interface->close_ctx(chkpt->store_data, ctx->store_ctx);
110 #define V3_CHKPT_STD_SAVE(ctx,x) v3_chkpt_save(ctx,#x,sizeof(x),&(x))
111 #define V3_CHKPT_STD_LOAD(ctx,x) v3_chkpt_load(ctx,#x,sizeof(x),&(x))
114 int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
115 struct v3_chkpt * chkpt = ctx->chkpt;
116 return chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf);
120 int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
121 struct v3_chkpt * chkpt = ctx->chkpt;
122 return chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf);
127 static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
129 void * guest_mem_base = NULL;
133 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
135 ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
137 ret = v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base);
138 v3_chkpt_close_ctx(ctx);
141 PrintError("Error Loading VM Memory\n");
149 static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
150 void * guest_mem_base = NULL;
154 guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
156 ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
159 ret = v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base);
160 v3_chkpt_close_ctx(ctx);
163 PrintError("Error Saving VM Memory\n");
170 int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
171 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
174 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
178 case V3_SVM_REV3_CPU: {
179 v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
184 case V3_VMX_EPT_UG_CPU: {
185 v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header);
189 PrintError("checkpoint not supported on this architecture\n");
190 v3_chkpt_close_ctx(ctx);
194 v3_chkpt_close_ctx(ctx);
199 static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
200 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
203 ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
207 case V3_SVM_REV3_CPU: {
208 char header[strlen(svm_chkpt_header) + 1];
210 v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header);
216 case V3_VMX_EPT_UG_CPU: {
217 char header[strlen(vmx_chkpt_header) + 1];
219 v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header);
224 PrintError("checkpoint not supported on this architecture\n");
225 v3_chkpt_close_ctx(ctx);
229 v3_chkpt_close_ctx(ctx);
235 static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
236 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
239 memset(key_name, 0, 16);
241 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
243 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
245 V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
247 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0);
248 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr2);
249 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr4);
250 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr8);
251 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.rflags);
252 V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.efer);
254 V3_CHKPT_STD_LOAD(ctx, info->dbg_regs);
255 V3_CHKPT_STD_LOAD(ctx, info->segments);
256 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr3);
257 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr0);
258 V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_efer);
259 v3_chkpt_close_ctx(ctx);
261 PrintDebug("Finished reading guest_info information\n");
263 info->cpu_mode = v3_get_vm_cpu_mode(info);
264 info->mem_mode = v3_get_vm_mem_mode(info);
269 case V3_SVM_REV3_CPU: {
272 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
273 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
275 if (v3_svm_load_core(info, ctx) == -1) {
276 PrintError("Failed to patch core %d\n", info->vcpu_id);
280 v3_chkpt_close_ctx(ctx);
286 case V3_VMX_EPT_UG_CPU: {
289 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
290 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
292 if (v3_vmx_load_core(info, ctx) < 0) {
293 PrintError("VMX checkpoint failed\n");
297 v3_chkpt_close_ctx(ctx);
302 PrintError("Invalid CPU Type (%d)\n", cpu_type);
310 static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
311 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
315 memset(key_name, 0, 16);
318 snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
320 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
322 V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
324 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
325 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr2);
326 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr4);
327 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr8);
328 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.rflags);
329 V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.efer);
331 V3_CHKPT_STD_SAVE(ctx, info->dbg_regs);
332 V3_CHKPT_STD_SAVE(ctx, info->segments);
333 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr3);
334 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr0);
335 V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_efer);
337 v3_chkpt_close_ctx(ctx);
339 //Architechture specific code
342 case V3_SVM_REV3_CPU: {
346 snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
348 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
350 if (v3_svm_save_core(info, ctx) == -1) {
351 PrintError("VMCB Unable to be written\n");
352 v3_chkpt_close_ctx(ctx);
356 v3_chkpt_close_ctx(ctx);
361 case V3_VMX_EPT_UG_CPU: {
365 snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
367 ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
369 if (v3_vmx_save_core(info, ctx) == -1) {
370 PrintError("VMX checkpoint failed\n");
371 v3_chkpt_close_ctx(ctx);
375 v3_chkpt_close_ctx(ctx);
380 PrintError("Invalid CPU Type (%d)\n", cpu_type);
388 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
389 struct v3_chkpt * chkpt = NULL;
393 chkpt = chkpt_open(store, url, SAVE);
396 PrintError("Error creating checkpoint store\n");
400 /* If this guest is running we need to block it while the checkpoint occurs */
401 if (vm->run_state == VM_RUNNING) {
402 while (v3_raise_barrier(vm, NULL) == -1);
405 if ((ret = save_memory(vm, chkpt)) == -1) {
406 PrintError("Unable to save memory\n");
411 if ((ret = v3_chkpt_save_dev(vm)) == -1) {
412 PrintError("Unable to save devices\n");
417 if ((ret = save_header(vm, chkpt)) == -1) {
418 PrintError("Unable to save header\n");
422 for (i = 0; i < vm->num_cores; i++){
424 if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) {
425 PrintError("chkpt of core %d failed\n", i);
432 /* Resume the guest if it was running */
433 if (vm->run_state == VM_RUNNING) {
434 v3_lower_barrier(vm);
443 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
444 struct v3_chkpt * chkpt = NULL;
448 chkpt = chkpt_open(store, url, LOAD);
451 PrintError("Error creating checkpoint store\n");
455 /* If this guest is running we need to block it while the checkpoint occurs */
456 if (vm->run_state == VM_RUNNING) {
457 while (v3_raise_barrier(vm, NULL) == -1);
460 if ((ret = load_memory(vm, chkpt)) == -1) {
461 PrintError("Unable to save memory\n");
466 /* Don't handle devices just yet
467 if (v3_chkpt_load_dev(vm) == -1) {
468 PrintError("Unable to load devies\n");
473 if ((ret = load_header(vm, chkpt)) == -1) {
474 PrintError("Unable to load header\n");
479 for (i = 0; i < vm->num_cores; i++) {
480 if ((ret = load_core(&(vm->cores[i]), chkpt)) == -1) {
481 PrintError("Error loading core state (core=%d)\n", i);
488 /* Resume the guest if it was running and we didn't just trash the state*/
489 if (vm->run_state == VM_RUNNING) {
492 vm->run_state = VM_STOPPED;
495 /* We check the run state of the VM after every barrier
496 So this will immediately halt the VM
498 v3_lower_barrier(vm);
508 static uint_t store_hash_fn(addr_t key) {
509 char * name = (char *)key;
510 return v3_hash_buffer((uint8_t *)name, strlen(name));
513 static int store_eq_fn(addr_t key1, addr_t key2) {
514 char * name1 = (char *)key1;
515 char * name2 = (char *)key2;
517 return (strcmp(name1, name2) == 0);
522 int V3_init_checkpoint() {
523 extern struct chkpt_interface * __start__v3_chkpt_stores[];
524 extern struct chkpt_interface * __stop__v3_chkpt_stores[];
525 struct chkpt_interface ** tmp_store = __start__v3_chkpt_stores;
528 store_table = v3_create_htable(0, store_hash_fn, store_eq_fn);
530 while (tmp_store != __stop__v3_chkpt_stores) {
531 V3_Print("Registering Extension (%s)\n", (*tmp_store)->name);
533 if (v3_htable_search(store_table, (addr_t)((*tmp_store)->name))) {
534 PrintError("Multiple instances of Extension (%s)\n", (*tmp_store)->name);
538 if (v3_htable_insert(store_table, (addr_t)((*tmp_store)->name), (addr_t)(*tmp_store)) == 0) {
539 PrintError("Could not register Extension (%s)\n", (*tmp_store)->name);
543 tmp_store = &(__start__v3_chkpt_stores[++i]);