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.


8f5e5ac6711c47906a9e87255820cda1bd905daf
[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
30 #include <palacios/vmm_dev_mgr.h>
31
32
33 static struct hashtable * store_table = NULL;
34
35 struct v3_chkpt;
36
37 typedef enum {SAVE, LOAD} chkpt_mode_t;
38
39 struct chkpt_interface {
40     char name[128];
41     void * (*open_chkpt)(char * url, chkpt_mode_t mode);
42     int (*close_chkpt)(void * store_data);
43     
44     void * (*open_ctx)(void * store_data, void * parent_ctx, char * name);
45     int (*close_ctx)(void * store_data, void * ctx);
46     
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);
49 };
50
51
52 struct v3_chkpt {
53     struct v3_vm_info * vm;
54
55     struct chkpt_interface * interface;
56
57     void * store_data;
58 };
59
60
61
62
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));
66 }
67
68 static int store_eq_fn(addr_t key1, addr_t key2) {
69     char * name1 = (char *)key1;
70     char * name2 = (char *)key2;
71
72     return (strcmp(name1, name2) == 0);
73 }
74
75
76
77 #include "vmm_chkpt_stores.h"
78
79
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;
84     int i = 0;
85
86     store_table = v3_create_htable(0, store_hash_fn, store_eq_fn);
87
88     while (tmp_store != __stop__v3_chkpt_stores) {
89         V3_Print("Registering Checkpoint Backing Store (%s)\n", (*tmp_store)->name);
90
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);
93             return -1;
94         }
95
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);
98             return -1;
99         }
100
101         tmp_store = &(__start__v3_chkpt_stores[++i]);
102     }
103
104     return 0;
105 }
106
107 int V3_deinit_checkpoint() {
108     v3_free_htable(store_table, 0, 0);
109     return 0;
110 }
111
112
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";
115
116 static int chkpt_close(struct v3_chkpt * chkpt) {
117     chkpt->interface->close_chkpt(chkpt->store_data);
118
119     V3_Free(chkpt);
120
121     return 0;
122 }
123
124
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;
129
130     iface = (void *)v3_htable_search(store_table, (addr_t)store);
131     
132     if (iface == NULL) {
133         V3_Print("Error: Could not locate Checkpoint interface for store (%s)\n", store);
134         return NULL;
135     }
136
137     store_data = iface->open_chkpt(url, mode);
138
139     if (store_data == NULL) {
140         PrintError("Could not open url (%s) for backing store (%s)\n", url, store);
141         return NULL;
142     }
143
144
145     chkpt = V3_Malloc(sizeof(struct v3_chkpt));
146
147     if (!chkpt) {
148         PrintError("Could not allocate checkpoint state\n");
149         return NULL;
150     }
151
152     chkpt->interface = iface;
153     chkpt->vm = vm;
154     chkpt->store_data = store_data;
155     
156     return chkpt;
157 }
158
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;
162
163     memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
164
165     ctx->chkpt = chkpt;
166     ctx->parent = parent;
167
168     if (parent) {
169         parent_store_ctx = parent->store_ctx;
170     }
171
172     ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent_store_ctx, name);
173
174     return ctx;
175 }
176
177 int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
178     struct v3_chkpt * chkpt = ctx->chkpt;
179     int ret = 0;
180
181     ret = chkpt->interface->close_ctx(chkpt->store_data, ctx->store_ctx);
182
183     V3_Free(ctx);
184
185     return ret;
186 }
187
188
189 /* Temporary */
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))
192
193
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);
197 }
198
199
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);
203 }
204
205
206
207 static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
208
209     void * guest_mem_base = NULL;
210     void * ctx = NULL;
211     uint64_t ret = 0;
212
213     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
214
215     ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
216
217     ret = v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base);
218     v3_chkpt_close_ctx(ctx);
219
220     return ret;
221 }
222
223
224 static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
225     void * guest_mem_base = NULL;
226     void * ctx = NULL;
227     uint64_t ret = 0;
228
229     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
230
231     ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img");
232
233
234     ret = v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base);
235     v3_chkpt_close_ctx(ctx);
236
237     return ret;
238 }
239
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());
242     void * ctx = NULL;
243     
244     ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
245
246     switch (cpu_type) {
247         case V3_SVM_CPU:
248         case V3_SVM_REV3_CPU: {
249             v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
250             break;
251         }
252         case V3_VMX_CPU:
253         case V3_VMX_EPT_CPU:
254         case V3_VMX_EPT_UG_CPU: {
255             v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header);
256             break;
257         }
258         default:
259             PrintError("checkpoint not supported on this architecture\n");
260             v3_chkpt_close_ctx(ctx);
261             return -1;
262     }
263
264     v3_chkpt_close_ctx(ctx);
265             
266     return 0;
267 }
268
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());
271     void * ctx = NULL;
272     
273     ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
274
275     switch (cpu_type) {
276         case V3_SVM_CPU:
277         case V3_SVM_REV3_CPU: {
278             char header[strlen(svm_chkpt_header) + 1];
279          
280             v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header);
281
282             break;
283         }
284         case V3_VMX_CPU:
285         case V3_VMX_EPT_CPU:
286         case V3_VMX_EPT_UG_CPU: {
287             char header[strlen(vmx_chkpt_header) + 1];
288             
289             v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header);
290             
291             break;
292         }
293         default:
294             PrintError("checkpoint not supported on this architecture\n");
295             v3_chkpt_close_ctx(ctx);
296             return -1;
297     }
298
299     v3_chkpt_close_ctx(ctx);
300
301     return 0;
302 }
303
304
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());
307     void * ctx = NULL;
308     char key_name[16];
309     memset(key_name, 0, 16);
310
311     snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
312
313     ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
314
315     V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
316
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);
323
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);
330
331     PrintDebug("Finished reading guest_info information\n");
332
333     info->cpu_mode = v3_get_vm_cpu_mode(info);
334     info->mem_mode = v3_get_vm_mem_mode(info);
335
336
337     switch (cpu_type) {
338         case V3_SVM_CPU:
339         case V3_SVM_REV3_CPU: {
340             char key_name[16];
341
342             snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
343             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
344             
345             if (v3_svm_load_core(info, ctx) == -1) {
346                 PrintError("Failed to patch core %d\n", info->vcpu_id);
347                 return -1;
348             }
349
350             v3_chkpt_close_ctx(ctx);
351
352             break;
353         }
354         case V3_VMX_CPU:
355         case V3_VMX_EPT_CPU:
356         case V3_VMX_EPT_UG_CPU: {
357             char key_name[16];
358
359             snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
360             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
361             
362             if (v3_vmx_load_core(info, ctx) < 0) {
363                 PrintError("VMX checkpoint failed\n");
364                 return -1;
365             }
366
367             v3_chkpt_close_ctx(ctx);
368
369             break;
370         }
371         default:
372             PrintError("Invalid CPU Type (%d)\n", cpu_type);
373             return -1;
374     }
375
376     return 0;
377 }
378
379
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());
382     void * ctx = NULL;
383     char key_name[16];
384
385     memset(key_name, 0, 16);
386
387
388     snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
389
390     ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
391
392     V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
393
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);
400
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);
406
407     v3_chkpt_close_ctx(ctx);
408
409     //Architechture specific code
410     switch (cpu_type) {
411         case V3_SVM_CPU:
412         case V3_SVM_REV3_CPU: {
413             char key_name[16];
414             void * ctx = NULL;
415             
416             snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
417             
418             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
419             
420             if (v3_svm_save_core(info, ctx) == -1) {
421                 PrintError("VMCB Unable to be written\n");
422                 v3_chkpt_close_ctx(ctx);
423                 return -1;
424             }
425             
426             v3_chkpt_close_ctx(ctx);
427             break;
428         }
429         case V3_VMX_CPU:
430         case V3_VMX_EPT_CPU:
431         case V3_VMX_EPT_UG_CPU: {
432             char key_name[16];
433             void * ctx = NULL;
434
435             snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
436             
437             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
438
439             if (v3_vmx_save_core(info, ctx) == -1) {
440                 PrintError("VMX checkpoint failed\n");
441                 v3_chkpt_close_ctx(ctx);
442                 return -1;
443             }
444
445             v3_chkpt_close_ctx(ctx);
446
447             break;
448         }
449         default:
450             PrintError("Invalid CPU Type (%d)\n", cpu_type);
451             return -1;
452     }
453     
454     return 0;
455 }
456
457
458 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
459     struct v3_chkpt * chkpt = NULL;
460     int ret = 0;;
461     int i = 0;
462     
463     chkpt = chkpt_open(vm, store, url, SAVE);
464
465     if (chkpt == NULL) {
466         PrintError("Error creating checkpoint store\n");
467         return -1;
468     }
469
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);
473     }
474
475     if ((ret = save_memory(vm, chkpt)) == -1) {
476         PrintError("Unable to save memory\n");
477         goto out;
478     }
479     
480     /*
481     if ((ret = v3_chkpt_save_dev(vm)) == -1) {
482         PrintError("Unable to save devices\n");
483         goto out;
484     }
485     */
486
487     if ((ret = save_header(vm, chkpt)) == -1) {
488         PrintError("Unable to save header\n");
489         goto out;
490     }
491     
492     for (i = 0; i < vm->num_cores; i++){
493         
494         if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) {
495             PrintError("chkpt of core %d failed\n", i);
496             goto out;
497         }
498     }   
499     
500  out:
501     
502     /* Resume the guest if it was running */
503     if (vm->run_state == VM_RUNNING) {
504         v3_lower_barrier(vm);
505     }
506
507     chkpt_close(chkpt);
508
509     return ret;
510
511 }
512
513 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
514     struct v3_chkpt * chkpt = NULL;
515     int i = 0;
516     int ret = 0;
517     
518     chkpt = chkpt_open(vm, store, url, LOAD);
519
520     if (chkpt == NULL) {
521         PrintError("Error creating checkpoint store\n");
522         return -1;
523     }
524
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);
528     }
529
530     if ((ret = load_memory(vm, chkpt)) == -1) {
531         PrintError("Unable to save memory\n");
532         goto out;
533     }
534
535
536     /* Don't handle devices just yet
537     if (v3_chkpt_load_dev(vm) == -1) {
538         PrintError("Unable to load devies\n");
539     }
540
541     */
542
543     if ((ret = load_header(vm, chkpt)) == -1) {
544         PrintError("Unable to load header\n");
545         goto out;
546     }
547
548     //per core cloning
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);
552             goto out;
553         }
554     }
555
556  out:     
557
558     /* Resume the guest if it was running and we didn't just trash the state*/
559     if (vm->run_state == VM_RUNNING) {
560     
561         if (ret == -1) {
562             vm->run_state = VM_STOPPED;
563         }
564
565         /* We check the run state of the VM after every barrier 
566            So this will immediately halt the VM 
567         */
568         v3_lower_barrier(vm);
569     }
570
571     chkpt_close(chkpt);
572
573     return ret;
574 }
575
576
577