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.


ded6171a9c06dae61759022b47e004b570cb08a6
[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_load_vm(struct v3_vm_info * vm, char * store, char * url) {
389     int i = 0;
390     struct v3_chkpt * chkpt = NULL;
391     
392     chkpt = chkpt_open(store, url, LOAD);
393
394
395     if (load_memory(vm, chkpt) == -1) {
396         PrintError("Unable to save memory\n");
397         return -1;
398     }
399
400     //raising the barrier requires VM to be in VM_RUNNING state
401     vm->run_state = VM_RUNNING;
402
403     /* Don't handle devices just yet
404     if (v3_chkpt_load_dev(vm) == -1) {
405         PrintError("Unable to load devies\n");
406     }
407
408     */
409
410     if (load_header(vm, chkpt) == -1) {
411         PrintError("Unable to load header\n");
412     }
413
414     //per core cloning
415     for (i = 0; i < vm->num_cores; i++) {
416         if (load_core(&(vm->cores[i]), chkpt) == -1) {
417             return -1;
418         }
419     }
420
421     chkpt_close(chkpt);
422
423     return 0;
424 }
425
426
427
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));
431 }
432
433 static int store_eq_fn(addr_t key1, addr_t key2) {
434     char * name1 = (char *)key1;
435     char * name2 = (char *)key2;
436
437     return (strcmp(name1, name2) == 0);
438 }
439
440
441
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;
446     int i = 0;
447
448     store_table = v3_create_htable(0, store_hash_fn, store_eq_fn);
449
450     while (tmp_store != __stop__v3_chkpt_stores) {
451         V3_Print("Registering Extension (%s)\n", (*tmp_store)->name);
452
453         if (v3_htable_search(store_table, (addr_t)((*tmp_store)->name))) {
454             PrintError("Multiple instances of Extension (%s)\n", (*tmp_store)->name);
455             return -1;
456         }
457
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);
460             return -1;
461         }
462
463         tmp_store = &(__start__v3_chkpt_stores[++i]);
464     }
465
466     return 0;
467 }