Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


bug fix to check for illegal memory ranges
[palacios.git] / palacios / src / palacios / vmm_checkpoint.c
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
13  *
14  * Author: Madhav Suresh <madhav@u.northwestern.edu>
15  *         Arefin Huq <fig@arefin.net>
16  *
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */
21
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>
30
31 #include <palacios/vmm_dev_mgr.h>
32
33
34 static struct hashtable * store_table = NULL;
35
36 struct v3_chkpt;
37
38 typedef enum {SAVE, LOAD} chkpt_mode_t;
39
40 struct chkpt_interface {
41     char name[128];
42     void * (*open_chkpt)(char * url, chkpt_mode_t mode);
43     int (*close_chkpt)(void * store_data);
44     
45     void * (*open_ctx)(void * store_data, void * parent_ctx, char * name);
46     int (*close_ctx)(void * store_data, void * ctx);
47     
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);
50 };
51
52
53 struct v3_chkpt {
54     struct v3_vm_info * vm;
55
56     struct chkpt_interface * interface;
57
58     void * store_data;
59 };
60
61
62
63
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));
67 }
68
69 static int store_eq_fn(addr_t key1, addr_t key2) {
70     char * name1 = (char *)key1;
71     char * name2 = (char *)key2;
72
73     return (strcmp(name1, name2) == 0);
74 }
75
76
77
78 #include "vmm_chkpt_stores.h"
79
80
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;
85     int i = 0;
86
87     store_table = v3_create_htable(0, store_hash_fn, store_eq_fn);
88
89     while (tmp_store != __stop__v3_chkpt_stores) {
90         V3_Print("Registering Checkpoint Backing Store (%s)\n", (*tmp_store)->name);
91
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);
94             return -1;
95         }
96
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);
99             return -1;
100         }
101
102         tmp_store = &(__start__v3_chkpt_stores[++i]);
103     }
104
105     return 0;
106 }
107
108 int V3_deinit_checkpoint() {
109     v3_free_htable(store_table, 0, 0);
110     return 0;
111 }
112
113
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";
116
117 static int chkpt_close(struct v3_chkpt * chkpt) {
118     chkpt->interface->close_chkpt(chkpt->store_data);
119
120     V3_Free(chkpt);
121
122     return 0;
123 }
124
125
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;
130
131     iface = (void *)v3_htable_search(store_table, (addr_t)store);
132     
133     if (iface == NULL) {
134         V3_Print("Error: Could not locate Checkpoint interface for store (%s)\n", store);
135         return NULL;
136     }
137
138     store_data = iface->open_chkpt(url, mode);
139
140     if (store_data == NULL) {
141         PrintError("Could not open url (%s) for backing store (%s)\n", url, store);
142         return NULL;
143     }
144
145
146     chkpt = V3_Malloc(sizeof(struct v3_chkpt));
147
148     if (!chkpt) {
149         PrintError("Could not allocate checkpoint state\n");
150         return NULL;
151     }
152
153     chkpt->interface = iface;
154     chkpt->vm = vm;
155     chkpt->store_data = store_data;
156     
157     return chkpt;
158 }
159
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;
163
164     memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
165
166     ctx->chkpt = chkpt;
167     ctx->parent = parent;
168
169     if (parent) {
170         parent_store_ctx = parent->store_ctx;
171     }
172
173     ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent_store_ctx, name);
174
175     return ctx;
176 }
177
178 int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
179     struct v3_chkpt * chkpt = ctx->chkpt;
180     int ret = 0;
181
182     ret = chkpt->interface->close_ctx(chkpt->store_data, ctx->store_ctx);
183
184     V3_Free(ctx);
185
186     return ret;
187 }
188
189
190
191
192
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);
196 }
197
198
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);
202 }
203
204
205
206 static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
207
208     void * guest_mem_base = NULL;
209     void * ctx = NULL;
210     uint64_t ret = 0;
211
212     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
213
214     ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
215
216     ret = v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base);
217     v3_chkpt_close_ctx(ctx);
218
219     return ret;
220 }
221
222
223 static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
224     void * guest_mem_base = NULL;
225     void * ctx = NULL;
226     uint64_t ret = 0;
227
228     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
229
230     ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img");
231
232
233     ret = v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base);
234     v3_chkpt_close_ctx(ctx);
235
236     return ret;
237 }
238
239 int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
240     extern v3_cpu_arch_t v3_mach_type;
241     void * ctx = NULL;
242     
243     ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
244
245     switch (v3_mach_type) {
246         case V3_SVM_CPU:
247         case V3_SVM_REV3_CPU: {
248             v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
249             break;
250         }
251         case V3_VMX_CPU:
252         case V3_VMX_EPT_CPU:
253         case V3_VMX_EPT_UG_CPU: {
254             v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header);
255             break;
256         }
257         default:
258             PrintError("checkpoint not supported on this architecture\n");
259             v3_chkpt_close_ctx(ctx);
260             return -1;
261     }
262
263     v3_chkpt_close_ctx(ctx);
264             
265     return 0;
266 }
267
268 static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
269     extern v3_cpu_arch_t v3_mach_type;
270     void * ctx = NULL;
271     
272     ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
273
274     switch (v3_mach_type) {
275         case V3_SVM_CPU:
276         case V3_SVM_REV3_CPU: {
277             char header[strlen(svm_chkpt_header) + 1];
278          
279             v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header);
280
281             break;
282         }
283         case V3_VMX_CPU:
284         case V3_VMX_EPT_CPU:
285         case V3_VMX_EPT_UG_CPU: {
286             char header[strlen(vmx_chkpt_header) + 1];
287             
288             v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header);
289             
290             break;
291         }
292         default:
293             PrintError("checkpoint not supported on this architecture\n");
294             v3_chkpt_close_ctx(ctx);
295             return -1;
296     }
297
298     v3_chkpt_close_ctx(ctx);
299
300     return 0;
301 }
302
303
304 static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
305     extern v3_cpu_arch_t v3_mach_type;
306     void * ctx = NULL;
307     char key_name[16];
308     memset(key_name, 0, 16);
309
310     snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
311
312     ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
313
314     v3_chkpt_load_64(ctx, "RIP", &(info->rip));
315
316     V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
317
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);
324
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);
331
332     PrintDebug("Finished reading guest_info information\n");
333
334     info->cpu_mode = v3_get_vm_cpu_mode(info);
335     info->mem_mode = v3_get_vm_mem_mode(info);
336
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");
341                 return -1;
342             }
343         } else {
344             if (v3_activate_passthrough_pt(info) == -1) {
345                 PrintError("Failed to activate passthrough page tables\n");
346                 return -1;
347             }
348         }
349     }
350
351
352     switch (v3_mach_type) {
353         case V3_SVM_CPU:
354         case V3_SVM_REV3_CPU: {
355             char key_name[16];
356
357             snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
358             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
359             
360             if (v3_svm_load_core(info, ctx) == -1) {
361                 PrintError("Failed to patch core %d\n", info->vcpu_id);
362                 return -1;
363             }
364
365             v3_chkpt_close_ctx(ctx);
366
367             break;
368         }
369         case V3_VMX_CPU:
370         case V3_VMX_EPT_CPU:
371         case V3_VMX_EPT_UG_CPU: {
372             char key_name[16];
373
374             snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
375             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
376             
377             if (v3_vmx_load_core(info, ctx) < 0) {
378                 PrintError("VMX checkpoint failed\n");
379                 return -1;
380             }
381
382             v3_chkpt_close_ctx(ctx);
383
384             break;
385         }
386         default:
387             PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
388             return -1;
389     }
390
391     v3_print_guest_state(info);
392
393     return 0;
394 }
395
396
397 static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
398     extern v3_cpu_arch_t v3_mach_type;
399     void * ctx = NULL;
400     char key_name[16];
401
402     memset(key_name, 0, 16);
403
404     v3_print_guest_state(info);
405
406
407     snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
408
409     ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
410
411     v3_chkpt_save_64(ctx, "RIP", &(info->rip));
412
413     V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
414
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);
421
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);
427
428     v3_chkpt_close_ctx(ctx);
429
430     //Architechture specific code
431     switch (v3_mach_type) {
432         case V3_SVM_CPU:
433         case V3_SVM_REV3_CPU: {
434             char key_name[16];
435             void * ctx = NULL;
436             
437             snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
438             
439             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
440             
441             if (v3_svm_save_core(info, ctx) == -1) {
442                 PrintError("VMCB Unable to be written\n");
443                 v3_chkpt_close_ctx(ctx);
444                 return -1;
445             }
446             
447             v3_chkpt_close_ctx(ctx);
448             break;
449         }
450         case V3_VMX_CPU:
451         case V3_VMX_EPT_CPU:
452         case V3_VMX_EPT_UG_CPU: {
453             char key_name[16];
454             void * ctx = NULL;
455
456             snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
457             
458             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
459
460             if (v3_vmx_save_core(info, ctx) == -1) {
461                 PrintError("VMX checkpoint failed\n");
462                 v3_chkpt_close_ctx(ctx);
463                 return -1;
464             }
465
466             v3_chkpt_close_ctx(ctx);
467
468             break;
469         }
470         default:
471             PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
472             return -1;
473     }
474     
475     return 0;
476 }
477
478
479 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
480     struct v3_chkpt * chkpt = NULL;
481     int ret = 0;;
482     int i = 0;
483     
484     chkpt = chkpt_open(vm, store, url, SAVE);
485
486     if (chkpt == NULL) {
487         PrintError("Error creating checkpoint store\n");
488         return -1;
489     }
490
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);
494     }
495
496     if ((ret = save_memory(vm, chkpt)) == -1) {
497         PrintError("Unable to save memory\n");
498         goto out;
499     }
500     
501     
502     if ((ret = v3_save_vm_devices(vm, chkpt)) == -1) {
503         PrintError("Unable to save devices\n");
504         goto out;
505     }
506     
507
508     if ((ret = save_header(vm, chkpt)) == -1) {
509         PrintError("Unable to save header\n");
510         goto out;
511     }
512     
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);
516             goto out;
517         }
518     }
519     
520  out:
521     
522     /* Resume the guest if it was running */
523     if (vm->run_state == VM_RUNNING) {
524         v3_lower_barrier(vm);
525     }
526
527     chkpt_close(chkpt);
528
529     return ret;
530
531 }
532
533 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
534     struct v3_chkpt * chkpt = NULL;
535     int i = 0;
536     int ret = 0;
537     
538     chkpt = chkpt_open(vm, store, url, LOAD);
539
540     if (chkpt == NULL) {
541         PrintError("Error creating checkpoint store\n");
542         return -1;
543     }
544
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);
548     }
549
550     if ((ret = load_memory(vm, chkpt)) == -1) {
551         PrintError("Unable to save memory\n");
552         goto out;
553     }
554
555
556     if ((ret = v3_load_vm_devices(vm, chkpt)) == -1) {
557         PrintError("Unable to load devies\n");
558         goto out;
559     }
560
561
562     if ((ret = load_header(vm, chkpt)) == -1) {
563         PrintError("Unable to load header\n");
564         goto out;
565     }
566
567     //per core cloning
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);
571             goto out;
572         }
573     }
574
575  out:
576
577     /* Resume the guest if it was running and we didn't just trash the state*/
578     if (vm->run_state == VM_RUNNING) {
579     
580         if (ret == -1) {
581             vm->run_state = VM_STOPPED;
582         }
583
584         /* We check the run state of the VM after every barrier 
585            So this will immediately halt the VM 
586         */
587         v3_lower_barrier(vm);
588     }
589
590     chkpt_close(chkpt);
591
592     return ret;
593 }
594
595
596