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_load_vm(struct v3_vm_info * vm, char * store, char * url) {
390 struct v3_chkpt * chkpt = NULL;
392 chkpt = chkpt_open(store, url, LOAD);
395 if (load_memory(vm, chkpt) == -1) {
396 PrintError("Unable to save memory\n");
400 //raising the barrier requires VM to be in VM_RUNNING state
401 vm->run_state = VM_RUNNING;
403 /* Don't handle devices just yet
404 if (v3_chkpt_load_dev(vm) == -1) {
405 PrintError("Unable to load devies\n");
410 if (load_header(vm, chkpt) == -1) {
411 PrintError("Unable to load header\n");
415 for (i = 0; i < vm->num_cores; i++) {
416 if (load_core(&(vm->cores[i]), chkpt) == -1) {
428 static uint_t store_hash_fn(addr_t key) {
429 char * name = (char *)key;
430 return v3_hash_buffer((uint8_t *)name, strlen(name));
433 static int store_eq_fn(addr_t key1, addr_t key2) {
434 char * name1 = (char *)key1;
435 char * name2 = (char *)key2;
437 return (strcmp(name1, name2) == 0);
442 int V3_init_checkpoint() {
443 extern struct chkpt_interface * __start__v3_chkpt_stores[];
444 extern struct chkpt_interface * __stop__v3_chkpt_stores[];
445 struct chkpt_interface ** tmp_store = __start__v3_chkpt_stores;
448 store_table = v3_create_htable(0, store_hash_fn, store_eq_fn);
450 while (tmp_store != __stop__v3_chkpt_stores) {
451 V3_Print("Registering Extension (%s)\n", (*tmp_store)->name);
453 if (v3_htable_search(store_table, (addr_t)((*tmp_store)->name))) {
454 PrintError("Multiple instances of Extension (%s)\n", (*tmp_store)->name);
458 if (v3_htable_insert(store_table, (addr_t)((*tmp_store)->name), (addr_t)(*tmp_store)) == 0) {
459 PrintError("Could not register Extension (%s)\n", (*tmp_store)->name);
463 tmp_store = &(__start__v3_chkpt_stores[++i]);