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.


ef4bec1191b7b8d214f5d581c8c59edf7c66031a
[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 #include "vmm_chkpt_stores.h"
62
63
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";
66
67 static int chkpt_close(struct v3_chkpt * chkpt) {
68     chkpt->interface->close_chkpt(chkpt->store_data);
69
70     V3_Free(chkpt);
71
72     return 0;
73 }
74
75
76 static struct v3_chkpt * chkpt_open(char * store, char * url, chkpt_mode_t mode) {
77     
78     // search for checkpoint interface
79
80     PrintError("Not yet implemented\n");
81     return NULL;
82 }
83
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));
86
87     memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
88
89     ctx->chkpt = chkpt;
90     ctx->parent = parent;
91
92     ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent->store_ctx, name);
93
94     return ctx;
95 }
96
97 int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
98     struct v3_chkpt * chkpt = ctx->chkpt;
99     int ret = 0;
100
101     ret = chkpt->interface->close_ctx(chkpt->store_data, ctx->store_ctx);
102
103     V3_Free(ctx);
104
105     return ret;
106 }
107
108
109 /* Temporary */
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))
112
113
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);
117 }
118
119
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);
123 }
124
125
126
127 static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
128
129     void * guest_mem_base = NULL;
130     void * ctx = NULL;
131     uint64_t ret = 0;
132
133     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
134
135     ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
136
137     ret = v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base);
138     v3_chkpt_close_ctx(ctx);
139
140     if (ret == 0) {
141         PrintError("Error Loading VM Memory\n");
142         return -1;
143     }
144
145     return 0;
146 }
147
148
149 static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
150     void * guest_mem_base = NULL;
151     void * ctx = NULL;
152     uint64_t ret = 0;
153
154     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
155
156     ctx = v3_chkpt_open_ctx(chkpt, NULL,  "memory_img");
157
158
159     ret = v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base);
160     v3_chkpt_close_ctx(ctx);
161
162     if (ret == 0) {
163         PrintError("Error Saving VM Memory\n");
164         return -1;
165     }
166
167     return 0;
168 }
169
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());
172     void * ctx = NULL;
173     
174     ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
175
176     switch (cpu_type) {
177         case V3_SVM_CPU:
178         case V3_SVM_REV3_CPU: {
179             v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
180             break;
181         }
182         case V3_VMX_CPU:
183         case V3_VMX_EPT_CPU:
184         case V3_VMX_EPT_UG_CPU: {
185             v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header);
186             break;
187         }
188         default:
189             PrintError("checkpoint not supported on this architecture\n");
190             v3_chkpt_close_ctx(ctx);
191             return -1;
192     }
193
194     v3_chkpt_close_ctx(ctx);
195             
196     return 0;
197 }
198
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());
201     void * ctx = NULL;
202     
203     ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
204
205     switch (cpu_type) {
206         case V3_SVM_CPU:
207         case V3_SVM_REV3_CPU: {
208             char header[strlen(svm_chkpt_header) + 1];
209          
210             v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header);
211
212             break;
213         }
214         case V3_VMX_CPU:
215         case V3_VMX_EPT_CPU:
216         case V3_VMX_EPT_UG_CPU: {
217             char header[strlen(vmx_chkpt_header) + 1];
218             
219             v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header);
220             
221             break;
222         }
223         default:
224             PrintError("checkpoint not supported on this architecture\n");
225             v3_chkpt_close_ctx(ctx);
226             return -1;
227     }
228
229     v3_chkpt_close_ctx(ctx);
230
231     return 0;
232 }
233
234
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());
237     void * ctx = NULL;
238     char key_name[16];
239     memset(key_name, 0, 16);
240
241     snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
242
243     ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
244
245     V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
246
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);
253
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);
260
261     PrintDebug("Finished reading guest_info information\n");
262
263     info->cpu_mode = v3_get_vm_cpu_mode(info);
264     info->mem_mode = v3_get_vm_mem_mode(info);
265
266
267     switch (cpu_type) {
268         case V3_SVM_CPU:
269         case V3_SVM_REV3_CPU: {
270             char key_name[16];
271
272             snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
273             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
274             
275             if (v3_svm_load_core(info, ctx) == -1) {
276                 PrintError("Failed to patch core %d\n", info->vcpu_id);
277                 return -1;
278             }
279
280             v3_chkpt_close_ctx(ctx);
281
282             break;
283         }
284         case V3_VMX_CPU:
285         case V3_VMX_EPT_CPU:
286         case V3_VMX_EPT_UG_CPU: {
287             char key_name[16];
288
289             snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
290             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
291             
292             if (v3_vmx_load_core(info, ctx) < 0) {
293                 PrintError("VMX checkpoint failed\n");
294                 return -1;
295             }
296
297             v3_chkpt_close_ctx(ctx);
298
299             break;
300         }
301         default:
302             PrintError("Invalid CPU Type (%d)\n", cpu_type);
303             return -1;
304     }
305
306     return 0;
307 }
308
309
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());
312     void * ctx = NULL;
313     char key_name[16];
314
315     memset(key_name, 0, 16);
316
317
318     snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
319
320     ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
321
322     V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
323
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);
330
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);
336
337     v3_chkpt_close_ctx(ctx);
338
339     //Architechture specific code
340     switch (cpu_type) {
341         case V3_SVM_CPU:
342         case V3_SVM_REV3_CPU: {
343             char key_name[16];
344             void * ctx = NULL;
345             
346             snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
347             
348             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
349             
350             if (v3_svm_save_core(info, ctx) == -1) {
351                 PrintError("VMCB Unable to be written\n");
352                 v3_chkpt_close_ctx(ctx);
353                 return -1;
354             }
355             
356             v3_chkpt_close_ctx(ctx);
357             break;
358         }
359         case V3_VMX_CPU:
360         case V3_VMX_EPT_CPU:
361         case V3_VMX_EPT_UG_CPU: {
362             char key_name[16];
363             void * ctx = NULL;
364
365             snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
366             
367             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
368
369             if (v3_vmx_save_core(info, ctx) == -1) {
370                 PrintError("VMX checkpoint failed\n");
371                 v3_chkpt_close_ctx(ctx);
372                 return -1;
373             }
374
375             v3_chkpt_close_ctx(ctx);
376
377             break;
378         }
379         default:
380             PrintError("Invalid CPU Type (%d)\n", cpu_type);
381             return -1;
382     }
383     
384     return 0;
385 }
386
387
388 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
389     struct v3_chkpt * chkpt = NULL;
390     int ret = 0;;
391     int i = 0;
392     
393     chkpt = chkpt_open(store, url, SAVE);
394
395     if (chkpt == NULL) {
396         PrintError("Error creating checkpoint store\n");
397         return -1;
398     }
399
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);
403     }
404
405     if ((ret = save_memory(vm, chkpt)) == -1) {
406         PrintError("Unable to save memory\n");
407         goto out;
408     }
409     
410     /*
411     if ((ret = v3_chkpt_save_dev(vm)) == -1) {
412         PrintError("Unable to save devices\n");
413         goto out;
414     }
415     */
416
417     if ((ret = save_header(vm, chkpt)) == -1) {
418         PrintError("Unable to save header\n");
419         goto out;
420     }
421     
422     for (i = 0; i < vm->num_cores; i++){
423         
424         if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) {
425             PrintError("chkpt of core %d failed\n", i);
426             goto out;
427         }
428     }   
429     
430  out:
431     
432     /* Resume the guest if it was running */
433     if (vm->run_state == VM_RUNNING) {
434         v3_lower_barrier(vm);
435     }
436
437     chkpt_close(chkpt);
438
439     return ret;
440
441 }
442
443 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
444     struct v3_chkpt * chkpt = NULL;
445     int i = 0;
446     int ret = 0;
447     
448     chkpt = chkpt_open(store, url, LOAD);
449
450     if (chkpt == NULL) {
451         PrintError("Error creating checkpoint store\n");
452         return -1;
453     }
454
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);
458     }
459
460     if ((ret = load_memory(vm, chkpt)) == -1) {
461         PrintError("Unable to save memory\n");
462         goto out;
463     }
464
465
466     /* Don't handle devices just yet
467     if (v3_chkpt_load_dev(vm) == -1) {
468         PrintError("Unable to load devies\n");
469     }
470
471     */
472
473     if ((ret = load_header(vm, chkpt)) == -1) {
474         PrintError("Unable to load header\n");
475         goto out;
476     }
477
478     //per core cloning
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);
482             goto out;
483         }
484     }
485
486  out:     
487
488     /* Resume the guest if it was running and we didn't just trash the state*/
489     if (vm->run_state == VM_RUNNING) {
490     
491         if (ret == -1) {
492             vm->run_state = VM_STOPPED;
493         }
494
495         /* We check the run state of the VM after every barrier 
496            So this will immediately halt the VM 
497         */
498         v3_lower_barrier(vm);
499     }
500
501     chkpt_close(chkpt);
502
503     return ret;
504 }
505
506
507
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));
511 }
512
513 static int store_eq_fn(addr_t key1, addr_t key2) {
514     char * name1 = (char *)key1;
515     char * name2 = (char *)key2;
516
517     return (strcmp(name1, name2) == 0);
518 }
519
520
521
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;
526     int i = 0;
527
528     store_table = v3_create_htable(0, store_hash_fn, store_eq_fn);
529
530     while (tmp_store != __stop__v3_chkpt_stores) {
531         V3_Print("Registering Extension (%s)\n", (*tmp_store)->name);
532
533         if (v3_htable_search(store_table, (addr_t)((*tmp_store)->name))) {
534             PrintError("Multiple instances of Extension (%s)\n", (*tmp_store)->name);
535             return -1;
536         }
537
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);
540             return -1;
541         }
542
543         tmp_store = &(__start__v3_chkpt_stores[++i]);
544     }
545
546     return 0;
547 }