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.


added device checkpoint hooks
[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
190
191
192 int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
193     struct v3_chkpt * chkpt = ctx->chkpt;    
194     return chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf);
195 }
196
197
198 int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
199     struct v3_chkpt * chkpt = ctx->chkpt;    
200     return chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf);
201 }
202
203
204
205 static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
206
207     void * guest_mem_base = NULL;
208     void * ctx = NULL;
209     uint64_t ret = 0;
210
211     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
212
213     ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
214
215     ret = v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base);
216     v3_chkpt_close_ctx(ctx);
217
218     return ret;
219 }
220
221
222 static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
223     void * guest_mem_base = NULL;
224     void * ctx = NULL;
225     uint64_t ret = 0;
226
227     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
228
229     ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img");
230
231
232     ret = v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base);
233     v3_chkpt_close_ctx(ctx);
234
235     return ret;
236 }
237
238 int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
239     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
240     void * ctx = NULL;
241     
242     ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
243
244     switch (cpu_type) {
245         case V3_SVM_CPU:
246         case V3_SVM_REV3_CPU: {
247             v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
248             break;
249         }
250         case V3_VMX_CPU:
251         case V3_VMX_EPT_CPU:
252         case V3_VMX_EPT_UG_CPU: {
253             v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header);
254             break;
255         }
256         default:
257             PrintError("checkpoint not supported on this architecture\n");
258             v3_chkpt_close_ctx(ctx);
259             return -1;
260     }
261
262     v3_chkpt_close_ctx(ctx);
263             
264     return 0;
265 }
266
267 static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
268     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
269     void * ctx = NULL;
270     
271     ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
272
273     switch (cpu_type) {
274         case V3_SVM_CPU:
275         case V3_SVM_REV3_CPU: {
276             char header[strlen(svm_chkpt_header) + 1];
277          
278             v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header);
279
280             break;
281         }
282         case V3_VMX_CPU:
283         case V3_VMX_EPT_CPU:
284         case V3_VMX_EPT_UG_CPU: {
285             char header[strlen(vmx_chkpt_header) + 1];
286             
287             v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header);
288             
289             break;
290         }
291         default:
292             PrintError("checkpoint not supported on this architecture\n");
293             v3_chkpt_close_ctx(ctx);
294             return -1;
295     }
296
297     v3_chkpt_close_ctx(ctx);
298
299     return 0;
300 }
301
302
303 static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
304     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
305     void * ctx = NULL;
306     char key_name[16];
307     memset(key_name, 0, 16);
308
309     snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
310
311     ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
312
313     V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
314
315     V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0);
316     V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr2);
317     V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr4);
318     V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr8);
319     V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.rflags);
320     V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.efer);
321
322     V3_CHKPT_STD_LOAD(ctx, info->dbg_regs);
323     V3_CHKPT_STD_LOAD(ctx, info->segments);
324     V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr3);
325     V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr0);
326     V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_efer);
327     v3_chkpt_close_ctx(ctx);
328
329     PrintDebug("Finished reading guest_info information\n");
330
331     info->cpu_mode = v3_get_vm_cpu_mode(info);
332     info->mem_mode = v3_get_vm_mem_mode(info);
333
334
335     switch (cpu_type) {
336         case V3_SVM_CPU:
337         case V3_SVM_REV3_CPU: {
338             char key_name[16];
339
340             snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
341             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
342             
343             if (v3_svm_load_core(info, ctx) == -1) {
344                 PrintError("Failed to patch core %d\n", info->vcpu_id);
345                 return -1;
346             }
347
348             v3_chkpt_close_ctx(ctx);
349
350             break;
351         }
352         case V3_VMX_CPU:
353         case V3_VMX_EPT_CPU:
354         case V3_VMX_EPT_UG_CPU: {
355             char key_name[16];
356
357             snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
358             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
359             
360             if (v3_vmx_load_core(info, ctx) < 0) {
361                 PrintError("VMX checkpoint failed\n");
362                 return -1;
363             }
364
365             v3_chkpt_close_ctx(ctx);
366
367             break;
368         }
369         default:
370             PrintError("Invalid CPU Type (%d)\n", cpu_type);
371             return -1;
372     }
373
374     return 0;
375 }
376
377
378 static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
379     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
380     void * ctx = NULL;
381     char key_name[16];
382
383     memset(key_name, 0, 16);
384
385
386     snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
387
388     ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
389
390     V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
391
392     V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
393     V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr2);
394     V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr4);
395     V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr8);
396     V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.rflags);
397     V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.efer);
398
399     V3_CHKPT_STD_SAVE(ctx, info->dbg_regs);
400     V3_CHKPT_STD_SAVE(ctx, info->segments);
401     V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr3);
402     V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr0);
403     V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_efer);
404
405     v3_chkpt_close_ctx(ctx);
406
407     //Architechture specific code
408     switch (cpu_type) {
409         case V3_SVM_CPU:
410         case V3_SVM_REV3_CPU: {
411             char key_name[16];
412             void * ctx = NULL;
413             
414             snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
415             
416             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
417             
418             if (v3_svm_save_core(info, ctx) == -1) {
419                 PrintError("VMCB Unable to be written\n");
420                 v3_chkpt_close_ctx(ctx);
421                 return -1;
422             }
423             
424             v3_chkpt_close_ctx(ctx);
425             break;
426         }
427         case V3_VMX_CPU:
428         case V3_VMX_EPT_CPU:
429         case V3_VMX_EPT_UG_CPU: {
430             char key_name[16];
431             void * ctx = NULL;
432
433             snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
434             
435             ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
436
437             if (v3_vmx_save_core(info, ctx) == -1) {
438                 PrintError("VMX checkpoint failed\n");
439                 v3_chkpt_close_ctx(ctx);
440                 return -1;
441             }
442
443             v3_chkpt_close_ctx(ctx);
444
445             break;
446         }
447         default:
448             PrintError("Invalid CPU Type (%d)\n", cpu_type);
449             return -1;
450     }
451     
452     return 0;
453 }
454
455
456 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
457     struct v3_chkpt * chkpt = NULL;
458     int ret = 0;;
459     int i = 0;
460     
461     chkpt = chkpt_open(vm, store, url, SAVE);
462
463     if (chkpt == NULL) {
464         PrintError("Error creating checkpoint store\n");
465         return -1;
466     }
467
468     /* If this guest is running we need to block it while the checkpoint occurs */
469     if (vm->run_state == VM_RUNNING) {
470         while (v3_raise_barrier(vm, NULL) == -1);
471     }
472
473     if ((ret = save_memory(vm, chkpt)) == -1) {
474         PrintError("Unable to save memory\n");
475         goto out;
476     }
477     
478     /*
479     if ((ret = v3_chkpt_save_dev(vm)) == -1) {
480         PrintError("Unable to save devices\n");
481         goto out;
482     }
483     */
484
485     if ((ret = save_header(vm, chkpt)) == -1) {
486         PrintError("Unable to save header\n");
487         goto out;
488     }
489     
490     for (i = 0; i < vm->num_cores; i++){
491         if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) {
492             PrintError("chkpt of core %d failed\n", i);
493             goto out;
494         }
495     }
496     
497  out:
498     
499     /* Resume the guest if it was running */
500     if (vm->run_state == VM_RUNNING) {
501         v3_lower_barrier(vm);
502     }
503
504     chkpt_close(chkpt);
505
506     return ret;
507
508 }
509
510 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
511     struct v3_chkpt * chkpt = NULL;
512     int i = 0;
513     int ret = 0;
514     
515     chkpt = chkpt_open(vm, store, url, LOAD);
516
517     if (chkpt == NULL) {
518         PrintError("Error creating checkpoint store\n");
519         return -1;
520     }
521
522     /* If this guest is running we need to block it while the checkpoint occurs */
523     if (vm->run_state == VM_RUNNING) {
524         while (v3_raise_barrier(vm, NULL) == -1);
525     }
526
527     if ((ret = load_memory(vm, chkpt)) == -1) {
528         PrintError("Unable to save memory\n");
529         goto out;
530     }
531
532
533     /* Don't handle devices just yet
534     if (v3_chkpt_load_dev(vm) == -1) {
535         PrintError("Unable to load devies\n");
536     }
537
538     */
539
540     if ((ret = load_header(vm, chkpt)) == -1) {
541         PrintError("Unable to load header\n");
542         goto out;
543     }
544
545     //per core cloning
546     for (i = 0; i < vm->num_cores; i++) {
547         if ((ret = load_core(&(vm->cores[i]), chkpt)) == -1) {
548             PrintError("Error loading core state (core=%d)\n", i);
549             goto out;
550         }
551     }
552
553  out:     
554
555     /* Resume the guest if it was running and we didn't just trash the state*/
556     if (vm->run_state == VM_RUNNING) {
557     
558         if (ret == -1) {
559             vm->run_state = VM_STOPPED;
560         }
561
562         /* We check the run state of the VM after every barrier 
563            So this will immediately halt the VM 
564         */
565         v3_lower_barrier(vm);
566     }
567
568     chkpt_close(chkpt);
569
570     return ret;
571 }
572
573
574