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.


Implementation of revised checkpoint/migrate interface model
Peter Dinda [Wed, 26 Dec 2012 17:13:16 +0000 (11:13 -0600)]
palacios/include/palacios/vmm_checkpoint.h
palacios/src/palacios/vmm_checkpoint.c
palacios/src/palacios/vmm_chkpt_stores.h

index 14af67a..a861026 100644 (file)
@@ -13,6 +13,7 @@
  *
  * Authors: Madhav Suresh <madhav@u.northwestern.edu>
  *          Mark Cartwright <mcartwright@gmail.com> (live migration)
+ *          Peter Dinda <pdinda@northwestern.edu> (store interface changes)
  *
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
 #include <palacios/vmm.h>
 
 
+/*
+  This code implements both checkpointing and live migration.  The
+  main difference between these two is how the memory of the VM is
+  transfered.
+
+  A checkpoint is written to/read from a checkpoint store.  A
+  checkpoint store is conceptually an unseekable stream.  This allows
+  us to reuse the same model for things like:
+
+  - checkpoint to memory
+  - checkpoint to directory of files
+  - checkpoint to gem5
+  - checkpoint to network
+  - live migrate over network
+  
+  To save data to a checkpoint store, you first open a context on the
+  checkpoint store, then you save data to the context. The data
+  consists of blobs tagged with strings.
+
+  Only a single context can be open at a time, and a context cannot be
+  reopened once it has been closed.  These invariants are also essential
+  to maximizing compatability with different implementations. 
+
+  The result of these constraints is that the stream that the
+  checkpoint store records will look like:
+
+  [contextname1][tag1len][tag1]][datalen][data][tag2len][tag2][datalen][data]....
+  [contextname2][tag1len][tag1]][datalen][data][tag2len][tag2][datalen][data]....
+  ...
+
+  The code implemented here assures that
+  [tag?len][tag?][datalen][data] is written as shown above.  The
+  checkpoint store handles [contextname?] internally. For example, it
+  might use the context names as files for a checkpoint, or it might
+  communicate the context names over a network stream.
+
+  To add checkpointing to your code, the primary thing you need to do
+  is implement save and load functions.   For a device, you then add them
+  to your dev_ops structure.   The save function takes an context.  
+  You then write on this context using one of the following functions/macros:
+
+  1. v3_chkpt_save(context, tag, datalen, dataptr);
+  2. V3_CHKPT_SAVE(context, tag, data, faillabel);
+  3. V3_CHKPT_SAVE_AUTOTAG(context, data, faillabel)
+  
+  Here (2) is a macro that computes the data length from sizeof(data)
+  while (3) does the same, and uses as the tag the name of the variable data.
+  We strongly recommend the use of (2). 
+  
+  These functions and macros will return -1 if the save is unsuccessful.
+  The faillabel argumnent is optional, if supplied and an error occurs,
+  the macro will goto the label. 
+
+  Some classes of devices, for example IDE HDs and CD-ROMs, and PCI
+  devices have a class-specific component and a device-specific
+  component.  For such devices, the class implementation (e.g., IDE, PCI) 
+  will provide a class-specific save function that should be called first
+  in the device's save function.  For example:
+
+  #include <devices/pci.h>
+  
+  static int my_device_save(struct v3_chkpt_ctx *ctx, void *priv) 
+  { 
+     struct my_device *dev = priv;
+
+     if (v3_pci_save(ctx, dev->pci)<0) { 
+        goto fail;
+     }
+
+     V3_CHKPT_SAVE(ctx, "myfoo", dev->foo, failout),;
+     V3_CHKPT_SAVE(ctx, "mybar", dev->bar, failout);
+
+     // Success
+     return 0;
+
+failout:
+
+     PrintError("Failed to save device\n");
+     return -1;
+
+  }     
+
+  The load side is symmetric. 
+
+*/
+
 struct v3_chkpt;
 
 
 struct v3_chkpt_ctx {
-    struct v3_chkpt * chkpt;
-    struct v3_chkpt_ctx * parent;
-    void * store_ctx;
+  struct v3_chkpt * chkpt;
+  void *store_ctx;
 };
 
-/* Temporary */
-#define  V3_CHKPT_STD_SAVE(ctx,x) v3_chkpt_save(ctx,#x,sizeof(x),&(x))
-#define  V3_CHKPT_STD_LOAD(ctx,x) v3_chkpt_load(ctx,#x,sizeof(x),&(x))
-
-
-
-int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf);
-int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf);
-
-static inline int v3_chkpt_save_64(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
-    return v3_chkpt_save(ctx, tag, 8, buf);
-}
-static inline int v3_chkpt_save_32(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
-    return v3_chkpt_save(ctx, tag, 4, buf);
-}
-static inline int v3_chkpt_save_16(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
-    return v3_chkpt_save(ctx, tag, 2, buf);
-}
-static inline int v3_chkpt_save_8(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
-    return v3_chkpt_save(ctx, tag, 1, buf);
-}
-
-static inline int v3_chkpt_load_64(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
-    return v3_chkpt_load(ctx, tag, 8, buf);
-}
-static inline int v3_chkpt_load_32(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
-    return v3_chkpt_load(ctx, tag, 4, buf);
-}
-static inline int v3_chkpt_load_16(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
-    return v3_chkpt_load(ctx, tag, 2, buf);
-}
-static inline int v3_chkpt_load_8(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
-    return v3_chkpt_load(ctx, tag, 1, buf);
-}
-
-
-
-int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx);
-struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, struct v3_chkpt_ctx * parent, char * name);
+
+
+/*
+ * You do not need to look behind this curtain
+ */
+#define SELECT(x,A,FUNC, ...) FUNC
+#define V3_CHKPT_SAVE_BASE(context, tag, data)  v3_chkpt_save(context,tag,sizeof(data),&(data))
+#define V3_CHKPT_SAVE_LABELED(context, tag, data, faillabel)   (({if (V3_CHKPT_SAVE_BASE(context,tag,data)<0) { goto faillabel; } 0; }), 0)
+#define V3_CHKPT_LOAD_BASE(context, tag, data)  v3_chkpt_load(context,tag,sizeof(data),&(data))
+#define V3_CHKPT_LOAD_LABELED(context, tag, data, faillabel)   (({if (V3_CHKPT_LOAD_BASE(context,tag,data)<0) { goto faillabel; } 0; }), 0)
+/*
+ * Safe to open your eyes again
+ */
+
+
+//
+// Functions and macros to save to a context
+//
+//
+int     v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf);
+#define V3_CHKPT_SAVE(context, tag, data, ...) SELECT(,##__VA_ARGS__,V3_CHKPT_SAVE_LABELED(context,tag,data,__VA_ARGS__),V3_CHKPT_SAVE_BASE(context,tag,data))
+#define V3_CHKPT_SAVE_AUTOTAG(context, data, ...) V3_CHKPT_SAVE(context, #data ,data,__VA_ARGS__)
+
+//
+// Funtions and macros to load from a context
+// 
+//
+int     v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf);
+#define V3_CHKPT_LOAD(context, tag, data, ...) SELECT(,##__VA_ARGS__,V3_CHKPT_LOAD_LABELED(context,tag,data,__VA_ARGS__),V3_CHKPT_LOAD_BASE(context,tag,data))
+#define V3_CHKPT_LOAD_AUTOTAG(context, data, ...) V3_CHKPT_LOAD(context, #data ,data,__VA_ARGS__)
+
+
+struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, char * name);
+int                   v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx);
 
 int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url);
 int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url);
index 9a49149..0d8facf 100644 (file)
@@ -13,6 +13,7 @@
  *
  * Author: Madhav Suresh <madhav@u.northwestern.edu>
  *        Arefin Huq <fig@arefin.net>
+ *         Peter Dinda <pdinda@northwestern.edu> (store interface changes)
  *
  *
  * This is free software.  You are permitted to use,
@@ -50,24 +51,39 @@ struct v3_chkpt;
 typedef enum {SAVE, LOAD} chkpt_mode_t;
 
 struct chkpt_interface {
-    char name[128];
-    void * (*open_chkpt)(char * url, chkpt_mode_t mode);
-    int (*close_chkpt)(void * store_data);
-    
-    void * (*open_ctx)(void * store_data, void * parent_ctx, char * name);
-    int (*close_ctx)(void * store_data, void * ctx);
-    
-    int (*save)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
-    int (*load)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
+  char name[128];
+  // Opening a checkpoint should return a pointer to the internal representation
+  // of the checkpoint in the store.  This will be passed back
+  // as "store_data".  Return NULL if the context cannot be opened
+  void * (*open_chkpt)(char * url, chkpt_mode_t mode);
+  // Closing the checkpoint should return -1 on failure, 0 on success
+  int    (*close_chkpt)(void * store_data);
+  
+  // Opening a context on the checkpoint with a given name should return
+  // a pointer to an internal representation of the context.  This pointer
+  // is then passed back as "ctx". 
+  // We will open only a single context at a time.  
+  void * (*open_ctx)(void * store_data, char *name);
+  // Closing the context should return -1 on failure, 0 on success
+  int    (*close_ctx)(void * store_data, void * ctx);
+  
+  // Save and load include a tagged data buffer.  These are 
+  // "all or nothing" writes and reads.  
+  // return -1 on failure, and 0 on success
+  // 
+  int (*save)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
+  int (*load)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
 };
 
 
 struct v3_chkpt {
-    struct v3_vm_info * vm;
-
-    struct chkpt_interface * interface;
-
-    void * store_data;
+  struct v3_vm_info * vm;
+  
+  struct v3_chkpt_ctx *current_ctx;
+  
+  struct chkpt_interface * interface;
+  
+  void * store_data;
 };
 
 
@@ -127,11 +143,23 @@ static char svm_chkpt_header[] = "v3vee palacios checkpoint version: x.x, SVM x.
 static char vmx_chkpt_header[] = "v3vee palacios checkpoint version: x.x, VMX x.x";
 
 static int chkpt_close(struct v3_chkpt * chkpt) {
-    chkpt->interface->close_chkpt(chkpt->store_data);
+  if (chkpt) { 
+    int rc;
+
+    rc = chkpt->interface->close_chkpt(chkpt->store_data);
 
     V3_Free(chkpt);
 
-    return 0;
+    if (rc!=0) { 
+      PrintError("Internal store failed to close valid checkpoint\n");
+      return -1;
+    } else {
+      return 0;
+    }
+  } else {
+    PrintError("Attempt to close null checkpoint\n");
+    return -1;
+  }
 }
 
 
@@ -156,53 +184,72 @@ static struct v3_chkpt * chkpt_open(struct v3_vm_info * vm, char * store, char *
 
 
     chkpt = V3_Malloc(sizeof(struct v3_chkpt));
-
+    
     if (!chkpt) {
-       PrintError("Could not allocate checkpoint state\n");
+       PrintError("Could not allocate checkpoint state, closing checkpoint\n");
+       iface->close_chkpt(store_data);
        return NULL;
     }
 
+    memset(chkpt,0,sizeof(struct v3_chkpt));
+
     chkpt->interface = iface;
     chkpt->vm = vm;
     chkpt->store_data = store_data;
+    chkpt->current_ctx = NULL;
     
     return chkpt;
 }
 
-struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, struct v3_chkpt_ctx * parent, char * name) {
-    struct v3_chkpt_ctx * ctx = V3_Malloc(sizeof(struct v3_chkpt_ctx));
-    void * parent_store_ctx = NULL;
-
-
-    if (!ctx) { 
-       PrintError("Unable to allocate context\n");
-       return 0;
-    }
+struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, char * name) {
+  struct v3_chkpt_ctx * ctx;
 
-    memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
+  if (chkpt->current_ctx) { 
+    PrintError("Attempt to open context %s before old context has been closed\n", name);
+    return NULL;
+  }
 
-    ctx->chkpt = chkpt;
-    ctx->parent = parent;
+  ctx = V3_Malloc(sizeof(struct v3_chkpt_ctx));
 
-    if (parent) {
-       parent_store_ctx = parent->store_ctx;
-    }
-
-    ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent_store_ctx, name);
+  if (!ctx) { 
+    PrintError("Unable to allocate context\n");
+    return 0;
+  }
+  
+  memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
+  
+  ctx->chkpt = chkpt;
+  ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, name);
+
+  if (!(ctx->store_ctx)) {
+    PrintError("Underlying store failed to open context %s\n",name);
+    V3_Free(ctx);
+    return NULL;
+  }
 
-    if (!(ctx->store_ctx)) {
-       PrintError("Warning: opening underlying representation returned null\n");
-    }
+  chkpt->current_ctx = ctx;
 
-    return ctx;
+  return ctx;
 }
 
 int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
     struct v3_chkpt * chkpt = ctx->chkpt;
     int ret = 0;
 
+    if (chkpt->current_ctx != ctx) { 
+      PrintError("Attempt to close a context that is not the current context on the store\n");
+      return -1;
+    }
+
     ret = chkpt->interface->close_ctx(chkpt->store_data, ctx->store_ctx);
 
+    if (ret) { 
+      PrintError("Failed to close context on store, closing device-independent context anyway - bad\n");
+      ret = -1;
+    }
+
+    chkpt->current_ctx=NULL;
+
     V3_Free(ctx);
 
     return ret;
@@ -214,16 +261,51 @@ int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
 
 int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
     struct v3_chkpt * chkpt = ctx->chkpt;    
-    
-    return  chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf);
+    int rc;
+
+    if (!ctx) { 
+      PrintError("Attempt to save tag %s on null context\n",tag);
+      return -1;
+    }
+
+    if (chkpt->current_ctx != ctx) { 
+      PrintError("Attempt to save on context that is not the current context for the store\n");
+      return -1;
+    }
+
+    rc = chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag , len, buf);
 
+    if (rc) { 
+      PrintError("Underlying store failed to save tag %s on valid context\n",tag);
+      return -1;
+    } else {
+      return 0;
+    }
 }
 
 
 int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
     struct v3_chkpt * chkpt = ctx->chkpt;    
+    int rc;
+
+    if (!ctx) { 
+      PrintError("Attempt to load tag %s from null context\n",tag);
+      return -1;
+    }
     
-    return chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf);
+    if (chkpt->current_ctx != ctx) { 
+      PrintError("Attempt to load from context that is not the current context for the store\n");
+      return -1;
+    }
+
+    rc = chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf);
+
+    if (rc) { 
+      PrintError("Underlying store failed to load tag %s from valid context\n",tag);
+      return -1;
+    } else {
+      return 0;
+    }
 }
 
 
@@ -236,14 +318,14 @@ static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
 
     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
 
-    ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
+    ctx = v3_chkpt_open_ctx(chkpt, "memory_img");
     
     if (!ctx) { 
        PrintError("Unable to open context for memory load\n");
        return -1;
     }
                     
-    if (v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base) == -1) {
+    if (v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base)) {
        PrintError("Unable to load all of memory (requested=%llu bytes, result=%llu bytes\n",(uint64_t)(vm->mem_size),ret);
        v3_chkpt_close_ctx(ctx);
        return -1;
@@ -262,15 +344,15 @@ static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
 
     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
 
-    ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img");
+    ctx = v3_chkpt_open_ctx(chkpt, "memory_img");
 
     if (!ctx) { 
        PrintError("Unable to open context to save memory\n");
        return -1;
     }
 
-    if (v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base) == -1) {
-       PrintError("Unable to load all of memory (requested=%llu, received=%llu)\n",(uint64_t)(vm->mem_size),ret);
+    if (v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base)) {
+       PrintError("Unable to save all of memory (requested=%llu, received=%llu)\n",(uint64_t)(vm->mem_size),ret);
        v3_chkpt_close_ctx(ctx);  
        return -1;
     }
@@ -375,7 +457,7 @@ static int save_inc_memory(struct v3_vm_info * vm,
     
     PrintDebug("Saving incremental memory.\n");
 
-    ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_bitmap_bits");
+    ctx = v3_chkpt_open_ctx(chkpt,"memory_bitmap_bits");
 
     if (!ctx) { 
        PrintError("Cannot open context for dirty memory bitmap\n");
@@ -386,7 +468,7 @@ static int save_inc_memory(struct v3_vm_info * vm,
     if (v3_chkpt_save(ctx,
                      "memory_bitmap_bits",
                      bitmap_num_bytes,
-                     mod_pgs_to_send->bits) == -1) {
+                     mod_pgs_to_send->bits)) {
        PrintError("Unable to write all of the dirty memory bitmap\n");
        v3_chkpt_close_ctx(ctx);
        return -1;
@@ -400,7 +482,7 @@ static int save_inc_memory(struct v3_vm_info * vm,
     for (i = 0; i < mod_pgs_to_send->num_bits; i++) {
         if (v3_bitmap_check(mod_pgs_to_send, i)) {
            // PrintDebug("Sending memory page %d.\n",i);
-            ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_page");
+            ctx = v3_chkpt_open_ctx(chkpt, "memory_page");
            if (!ctx) { 
                PrintError("Unable to open context to send memory page\n");
                return -1;
@@ -408,7 +490,7 @@ static int save_inc_memory(struct v3_vm_info * vm,
             if (v3_chkpt_save(ctx, 
                              "memory_page", 
                              page_size_bytes,
-                             guest_mem_base + (page_size_bytes * i)) == -1) {
+                             guest_mem_base + (page_size_bytes * i))) {
                PrintError("Unable to send a memory page\n");
                v3_chkpt_close_ctx(ctx);
                return -1;
@@ -441,7 +523,7 @@ static int load_inc_memory(struct v3_vm_info * vm,
 
     guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
 
-    ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_bitmap_bits");
+    ctx = v3_chkpt_open_ctx(chkpt, "memory_bitmap_bits");
 
     if (!ctx) { 
        PrintError("Cannot open context to receive memory bitmap\n");
@@ -451,7 +533,7 @@ static int load_inc_memory(struct v3_vm_info * vm,
     if (v3_chkpt_load(ctx,
                      "memory_bitmap_bits",
                      bitmap_num_bytes,
-                     mod_pgs->bits) == -1) {
+                     mod_pgs->bits)) {
        PrintError("Did not receive all of memory bitmap\n");
        v3_chkpt_close_ctx(ctx);
        return -1;
@@ -464,7 +546,7 @@ static int load_inc_memory(struct v3_vm_info * vm,
         if (v3_bitmap_check(mod_pgs, i)) {
             PrintDebug("Loading page %d\n", i);
             empty_bitmap = false;
-            ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_page");
+            ctx = v3_chkpt_open_ctx(chkpt, "memory_page");
            if (!ctx) { 
                PrintError("Cannot open context to receive memory page\n");
                return -1;
@@ -473,7 +555,7 @@ static int load_inc_memory(struct v3_vm_info * vm,
             if (v3_chkpt_load(ctx, 
                              "memory_page", 
                              page_size_bytes,
-                             guest_mem_base + (page_size_bytes * i)) == -1) {
+                             guest_mem_base + (page_size_bytes * i))) {
                PrintError("Did not receive all of memory page\n");
                v3_chkpt_close_ctx(ctx);
                return -1;
@@ -499,7 +581,7 @@ int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
     extern v3_cpu_arch_t v3_mach_type;
     void * ctx = NULL;
     
-    ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
+    ctx = v3_chkpt_open_ctx(chkpt, "header");
     if (!ctx) { 
        PrintError("Cannot open context to save header\n");
        return -1;
@@ -508,7 +590,7 @@ int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
     switch (v3_mach_type) {
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU: {
-           if (v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header) == -1) { 
+           if (v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header)) { 
                PrintError("Could not save all of SVM header\n");
                v3_chkpt_close_ctx(ctx);
                return -1;
@@ -518,7 +600,7 @@ int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
        case V3_VMX_CPU:
        case V3_VMX_EPT_CPU:
        case V3_VMX_EPT_UG_CPU: {
-           if (v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header) == -1) { 
+           if (v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header)) { 
                PrintError("Could not save all of VMX header\n");
                v3_chkpt_close_ctx(ctx);
                return -1;
@@ -540,14 +622,14 @@ static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
     extern v3_cpu_arch_t v3_mach_type;
     void * ctx = NULL;
     
-    ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
+    ctx = v3_chkpt_open_ctx(chkpt, "header");
 
     switch (v3_mach_type) {
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU: {
            char header[strlen(svm_chkpt_header) + 1];
         
-           if (v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header) == -1) {
+           if (v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header)) {
                PrintError("Could not load all of SVM header\n");
                v3_chkpt_close_ctx(ctx);
                return -1;
@@ -562,7 +644,7 @@ static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
        case V3_VMX_EPT_UG_CPU: {
            char header[strlen(vmx_chkpt_header) + 1];
            
-           if (v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header) == -1) {
+           if (v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header)) {
                PrintError("Could not load all of VMX header\n");
                v3_chkpt_close_ctx(ctx);
                return -1;
@@ -593,31 +675,28 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
 
     snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
 
-    ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+    ctx = v3_chkpt_open_ctx(chkpt, key_name);
 
     if (!ctx) { 
        PrintError("Could not open context to load core\n");
        return -1;
     }
 
-    // These really need to have error checking
-
-    v3_chkpt_load_64(ctx, "RIP", &(info->rip));
+    V3_CHKPT_LOAD(ctx, "RIP", info->rip, loadfailout);
+    V3_CHKPT_LOAD(ctx, "GPRS", info->vm_regs, loadfailout);
 
-    V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
+    V3_CHKPT_LOAD(ctx, "CR0", info->ctrl_regs.cr0, loadfailout);
+    V3_CHKPT_LOAD(ctx, "CR2", info->ctrl_regs.cr2, loadfailout);
+    V3_CHKPT_LOAD(ctx, "CR4", info->ctrl_regs.cr4, loadfailout);
+    V3_CHKPT_LOAD(ctx, "APIC_TPR", info->ctrl_regs.apic_tpr, loadfailout);
+    V3_CHKPT_LOAD(ctx, "RFLAGS", info->ctrl_regs.rflags, loadfailout);
+    V3_CHKPT_LOAD(ctx, "EFER", info->ctrl_regs.efer, loadfailout);
 
-    V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0);
-    V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr2);
-    V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr4);
-    V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.apic_tpr);
-    V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.rflags);
-    V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.efer);
-
-    V3_CHKPT_STD_LOAD(ctx, info->dbg_regs);
-    V3_CHKPT_STD_LOAD(ctx, info->segments);
-    V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr3);
-    V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr0);
-    V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_efer);
+    V3_CHKPT_LOAD(ctx, "DBRS", info->dbg_regs, loadfailout);
+    V3_CHKPT_LOAD(ctx, "SEGS", info->segments, loadfailout);
+    V3_CHKPT_LOAD(ctx, "GUEST_CR3", info->shdw_pg_state.guest_cr3, loadfailout);
+    V3_CHKPT_LOAD(ctx, "GUEST_CRO", info->shdw_pg_state.guest_cr0, loadfailout);
+    V3_CHKPT_LOAD(ctx, "GUEST_EFER", info->shdw_pg_state.guest_efer, loadfailout);
 
     v3_chkpt_close_ctx(ctx);
 
@@ -647,17 +726,16 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
            char key_name[16];
 
            snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
-           ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+           ctx = v3_chkpt_open_ctx(chkpt, key_name);
 
            if (!ctx) { 
                PrintError("Could not open context to load SVM core\n");
                return -1;
            }
            
-           if (v3_svm_load_core(info, ctx) == -1) {
+           if (v3_svm_load_core(info, ctx) < 0 ) {
                PrintError("Failed to patch core %d\n", info->vcpu_id);
-               v3_chkpt_close_ctx(ctx);
-               return -1;
+               goto loadfailout;
            }
 
            v3_chkpt_close_ctx(ctx);
@@ -671,7 +749,7 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
 
            snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
 
-           ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+           ctx = v3_chkpt_open_ctx(chkpt, key_name);
 
            if (!ctx) { 
                PrintError("Could not open context to load VMX core\n");
@@ -680,8 +758,7 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
            
            if (v3_vmx_load_core(info, ctx) < 0) {
                PrintError("VMX checkpoint failed\n");
-               v3_chkpt_close_ctx(ctx);
-               return -1;
+               goto loadfailout;
            }
 
            v3_chkpt_close_ctx(ctx);
@@ -693,9 +770,17 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
            return -1;
     }
 
+    PrintDebug("Load of core succeeded\n");
+
     v3_print_guest_state(info);
 
     return 0;
+
+ loadfailout:
+    PrintError("Failed to load core due to bad context load\n");
+    v3_chkpt_close_ctx(ctx);
+    return -1;
+
 }
 
 
@@ -704,14 +789,16 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
     void * ctx = NULL;
     char key_name[16];
 
-    memset(key_name, 0, 16);
+    PrintDebug("Saving core\n");
 
     v3_print_guest_state(info);
 
+    memset(key_name, 0, 16);
+
 
     snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
 
-    ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+    ctx = v3_chkpt_open_ctx(chkpt, key_name);
     
     if (!ctx) { 
        PrintError("Unable to open context to save core\n");
@@ -719,23 +806,21 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
     }
 
 
-    // Error checking of all this needs to happen
-    v3_chkpt_save_64(ctx, "RIP", &(info->rip));
+    V3_CHKPT_SAVE(ctx, "RIP", info->rip, savefailout);
+    V3_CHKPT_SAVE(ctx, "GPRS", info->vm_regs, savefailout);
 
-    V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
+    V3_CHKPT_SAVE(ctx, "CR0", info->ctrl_regs.cr0, savefailout);
+    V3_CHKPT_SAVE(ctx, "CR2", info->ctrl_regs.cr2, savefailout);
+    V3_CHKPT_SAVE(ctx, "CR4", info->ctrl_regs.cr4, savefailout);
+    V3_CHKPT_SAVE(ctx, "APIC_TPR", info->ctrl_regs.apic_tpr, savefailout);
+    V3_CHKPT_SAVE(ctx, "RFLAGS", info->ctrl_regs.rflags, savefailout);
+    V3_CHKPT_SAVE(ctx, "EFER", info->ctrl_regs.efer, savefailout);
 
-    V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
-    V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr2);
-    V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr4);
-    V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.apic_tpr);
-    V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.rflags);
-    V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.efer);
-
-    V3_CHKPT_STD_SAVE(ctx, info->dbg_regs);
-    V3_CHKPT_STD_SAVE(ctx, info->segments);
-    V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr3);
-    V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr0);
-    V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_efer);
+    V3_CHKPT_SAVE(ctx, "DBRS", info->dbg_regs, savefailout);
+    V3_CHKPT_SAVE(ctx, "SEGS", info->segments, savefailout);
+    V3_CHKPT_SAVE(ctx, "GUEST_CR3", info->shdw_pg_state.guest_cr3, savefailout);
+    V3_CHKPT_SAVE(ctx, "GUEST_CRO", info->shdw_pg_state.guest_cr0, savefailout);
+    V3_CHKPT_SAVE(ctx, "GUEST_EFER", info->shdw_pg_state.guest_efer, savefailout);
 
     v3_chkpt_close_ctx(ctx);
 
@@ -744,21 +829,19 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU: {
            char key_name[16];
-           void * ctx = NULL;
            
            snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
            
-           ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+           ctx = v3_chkpt_open_ctx(chkpt, key_name);
 
            if (!ctx) { 
                PrintError("Could not open context to store SVM core\n");
                return -1;
            }
            
-           if (v3_svm_save_core(info, ctx) == -1) {
+           if (v3_svm_save_core(info, ctx) < 0) {
                PrintError("VMCB Unable to be written\n");
-               v3_chkpt_close_ctx(ctx);
-               return -1;
+               goto savefailout;
            }
            
            v3_chkpt_close_ctx(ctx);
@@ -768,11 +851,10 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
        case V3_VMX_EPT_CPU:
        case V3_VMX_EPT_UG_CPU: {
            char key_name[16];
-           void * ctx = NULL;
 
            snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
            
-           ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+           ctx = v3_chkpt_open_ctx(chkpt, key_name);
            
            if (!ctx) { 
                PrintError("Could not open context to store VMX core\n");
@@ -781,8 +863,7 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
 
            if (v3_vmx_save_core(info, ctx) == -1) {
                PrintError("VMX checkpoint failed\n");
-               v3_chkpt_close_ctx(ctx);
-               return -1;
+               goto savefailout;
            }
 
            v3_chkpt_close_ctx(ctx);
@@ -792,9 +873,16 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
        default:
            PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
            return -1;
+           
     }
     
     return 0;
+
+ savefailout:
+    PrintError("Failed to save core due to bad context save\n");
+    v3_chkpt_close_ctx(ctx);
+    return -1;
+
 }
 
 
@@ -871,7 +959,7 @@ int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
     }
 
     if ((ret = load_memory(vm, chkpt)) == -1) {
-       PrintError("Unable to save memory\n");
+       PrintError("Unable to load memory\n");
        goto out;
     }
 
index 8feaf5a..0b9829f 100644 (file)
@@ -64,7 +64,6 @@ static int debug_close_chkpt(void * store_data) {
 }
 
 static void * debug_open_ctx(void * store_data, 
-                            void * parent_ctx, 
                             char * name) {
     V3_Print("[%s]\n", name);
     return (void *)1;
@@ -109,7 +108,6 @@ register_chkpt_store(debug_store);
 
 
 
-
 #ifdef V3_CONFIG_KEYED_STREAMS
 #include <interfaces/vmm_keyed_stream.h>
 
@@ -135,7 +133,6 @@ static int keyed_stream_close_chkpt(void * store_data) {
 }
 
 static void * keyed_stream_open_ctx(void * store_data, 
-                                   void * parent_ctx, 
                                    char * name) {
     v3_keyed_stream_t stream = store_data;
 
@@ -152,20 +149,20 @@ static int keyed_stream_close_ctx(void * store_data, void * ctx) {
 
 static int keyed_stream_save(void * store_data, void * ctx, 
                                  char * tag, uint64_t len, void * buf) {
-    if (v3_keyed_stream_write_key(store_data, ctx, buf, len) != len) { 
-       return -1;
-    } else {
-       return 0;
-    }
+  if (v3_keyed_stream_write_key(store_data, ctx, tag, strlen(tag), buf, len) != len) { 
+    return -1;
+  } else {
+    return 0;
+  }
 }
 
 static int keyed_stream_load(void * store_data, void * ctx, 
                                  char * tag, uint64_t len, void * buf) {
-    if (v3_keyed_stream_read_key(store_data, ctx, buf, len) != len) { 
-       return -1;
-    } else {
-       return 0;
-    }
+  if (v3_keyed_stream_read_key(store_data, ctx, tag, strlen(tag), buf, len) != len) { 
+    return -1;
+  } else {
+    return 0;
+  }
 }
 
 
@@ -215,7 +212,6 @@ static int dir_close_chkpt(void * store_data) {
 }
 
 static void * dir_open_ctx(void * store_data, 
-                          void * parent_ctx, 
                           char * name) {
 
     char * url = store_data;