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.


Updated userspace guest memory access tools for regions, plus added new fast function...
Peter Dinda [Wed, 21 Aug 2013 20:17:23 +0000 (15:17 -0500)]
copies, hashes, and applies

linux_usr/Makefile
linux_usr/v3_guest_mem.c
linux_usr/v3_guest_mem.h
linux_usr/v3_guest_mem_access.c [new file with mode: 0644]
linux_usr/v3_guest_mem_example.c [deleted file]

index 2d60e5a..0cf09ce 100644 (file)
@@ -30,7 +30,8 @@ BASE_EXECS =  v3_mem \
                v3_debug \
                v3_send \
                v3_receive \
-               v3_pci
+               v3_pci \
+               v3_guest_mem_access
 
 
 #
@@ -40,7 +41,6 @@ EXAMPLE_EXECS = v3_user_host_dev_example \
                v3_os_debug \
                v3_user_keyed_stream_example \
                v3_user_keyed_stream_file \
-               v3_guest_mem_example
 
 #
 # Currently experimental things
@@ -170,7 +170,7 @@ libv3_guest_mem.a : v3_guest_mem.c v3_guest_mem.h v3_ctrl.h
        $(AR) ruv libv3_guest_mem.a v3_guest_mem.o
        rm -f v3_guest_mem.o
 
-v3_guest_mem_example : v3_guest_mem_example.c libv3_guest_mem.a
+v3_guest_mem_access : v3_guest_mem_access.c libv3_guest_mem.a
        $(CC) $(CFLAGS) $< -L. -lv3_guest_mem -o $@
 
 
index d23acc1..ed1cd44 100644 (file)
@@ -7,66 +7,88 @@
 #include "v3_guest_mem.h"
 
 
-#warning FIX THE PARSER TO CONFORM TO NEW /proc/v3 VM output format
 
-
-#define GUEST_FILE "/proc/v3vee/v3-guests"
-//#define GUEST_FILE "/441/pdinda/test.proc"
+#define GUEST_FILE "/proc/v3vee/v3-guests-details"
+//#define GUEST_FILE "/v-test/numa/palacios-devel/test.proc"
 #define MAXLINE 65536
 
 struct v3_guest_mem_map * v3_guest_mem_get_map(char *vmdev)
 {
   FILE *f;
+  int rc;
+  int i;
   char buf[MAXLINE];
-  char name[MAXLINE];
   char dev[MAXLINE];
-  char state[MAXLINE];
-  uint64_t start, end;
+  uint64_t start, end, num;
+  uint64_t guest_cur;
+  uint64_t num_regions;
   
 
   if (!(f=fopen(GUEST_FILE,"r"))) { 
-    fprintf(stderr,"Cannot open %s - is Palacios active?\n",GUEST_FILE);
-    return 0;
-  }
-  
-  // This is using the current "single memory region" model
-  // and will change when /proc convention changes to conform to
-  // multiple region model
-  while (fgets(buf,MAXLINE,f)) {
-    if (sscanf(buf,
-              "%s %s %s [0x%llx-0x%llx]",
-              name,
-              dev,
-              state,
-              &start,
-              &end)!=5) { 
-      fprintf(stderr, "Cannot parse following line\n%s\n",buf);
-      fclose(f);
+      fprintf(stderr,"Cannot open %s - is Palacios active?\n",GUEST_FILE);
       return 0;
-    }
-    if (!strcmp(dev,vmdev)) { 
-      struct v3_guest_mem_map *m = 
-       (struct v3_guest_mem_map *) malloc(sizeof(struct v3_guest_mem_map)+1*sizeof(struct v3_guest_mem_block));
-      if (!m) { 
-       fprintf(stderr, "Cannot allocate space\n");
-       fclose(f);
-       return 0;
-      }
+  }
 
-      memset(m,0,sizeof(struct v3_guest_mem_map)+1*sizeof(struct v3_guest_mem_block));
-      
-      m->numblocks=1;
-      m->block[0].gpa=0;
-      m->block[0].hpa=(void*)start;
-      m->block[0].numpages = (end-start+1) / 4096;
+  while (1) {
+      if (!fgets(buf,MAXLINE,f)) {
+         fprintf(stderr,"Could not find info for %s\n",vmdev);
+         return 0;
+      }
+      if (sscanf(buf,"Device: %s",dev)==1) { 
+         if (!strcmp(dev,vmdev)) {
+             // found our VM
+             break;
+         } 
+      }
+  }
+       
+  // Now we need the number of regions
+  while (1) {
+      if (!fgets(buf,MAXLINE,f)) {
+         fprintf(stderr,"Could not find number of regions for %s\n",vmdev);
+         return 0;
+      }
+      if (sscanf(buf,"Regions: %llu",&num_regions)==1) {
+         break;
+      }
+  }
+  struct v3_guest_mem_map *m = 
+      (struct v3_guest_mem_map *) malloc(sizeof(struct v3_guest_mem_map)+num_regions*sizeof(struct v3_guest_mem_block));
+  if (!m) { 
+      fprintf(stderr, "Cannot allocate space\n");
       fclose(f);
-      return m;
-    }
+      return 0;
   }
   
-  fprintf(stderr,"%s not found\n",vmdev);
+  memset(m,0,sizeof(struct v3_guest_mem_map)+num_regions*sizeof(struct v3_guest_mem_block));
+
+  m->numblocks=num_regions;
+
+  // Now collect the region info
+  guest_cur=0;
+  while (i<num_regions) { 
+      if (!fgets(buf,MAXLINE,f)) {
+         fprintf(stderr,"Did not find all regions...\n");
+         free(m);
+         return 0;
+      }
+      if (sscanf(buf," region %d has HPAs %llx-%llx",&num,&start,&end)==3) { 
+         m->block[i].gpa = (void*)guest_cur;
+         m->block[i].hpa = (void*)start;
+         m->block[i].numpages = (end-start) / 4096 + !!((end-start) % 4096);
+         if ((end-start)%4096) { 
+             fprintf(stderr,"Odd, region %d is a non-integral number of pages");
+         }
+         guest_cur+=end-start;
+         m->block[i].cumgpa=(void*)(guest_cur-1);
+         i++;
+      }
+  }
+
   fclose(f);
-  return 0;
+
+  return m;
 
 }
 
@@ -88,8 +110,8 @@ int v3_map_guest_mem(struct v3_guest_mem_map *map)
   }
 
   for (i=0; i<map->numblocks; i++) { 
-    fprintf(stderr,"Mapping %llu bytes of /dev/mem offset 0x%llx\n",
-           map->block[i].numpages*4096, (off_t)(map->block[i].hpa));
+      //fprintf(stderr,"Mapping %llu bytes of /dev/mem offset 0x%llx\n",
+      //    map->block[i].numpages*4096, (off_t)(map->block[i].hpa));
     map->block[i].uva = mmap(NULL, 
                             map->block[i].numpages*4096,
                             PROT_READ | PROT_WRITE, 
@@ -125,3 +147,99 @@ int v3_unmap_guest_mem(struct v3_guest_mem_map *map)
   }
   return 0;
 }
+
+
+void *v3_gpa_start(struct v3_guest_mem_map *map)
+{
+    return 0; // all guests start at zero for now
+}
+
+void *v3_gpa_end(struct v3_guest_mem_map *map)
+{
+    struct v3_guest_mem_block *l = &(map->block[map->numblocks-1]); 
+
+    // currently, the regions are consecutive, so we just need the last block
+    return l->gpa+l->numpages*4096-1; 
+}
+
+
+int v3_guest_mem_apply(void (*func)(void *data, uint64_t num_bytes, void *priv),
+                      struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, void *priv)
+{
+    void *cur_gpa;
+    void *cur_uva;
+    uint64_t left_bytes;
+    uint64_t block_bytes;
+    
+    if (!(map->fd)) {
+       return -1;
+    }
+    
+    if (gpa < v3_gpa_start(map) || gpa+num_bytes-1 > v3_gpa_end(map)) { 
+       return -1;
+    }
+
+    cur_gpa = gpa;
+    left_bytes = num_bytes;
+
+    while (left_bytes) { 
+       cur_uva = v3_gpa_to_uva(map, cur_gpa, &block_bytes);
+       if (!cur_uva) { 
+           return -1;
+       }
+       if (block_bytes>left_bytes) { 
+           block_bytes = left_bytes;
+       }
+       func(cur_uva,block_bytes,priv);
+       left_bytes-=block_bytes;
+       cur_gpa+=block_bytes;
+    }
+    
+    return 0;
+}
+
+
+
+static void copy_out(void *uva, uint64_t num_bytes, void *curoff)
+{
+    memcpy(*((void**)(curoff)), uva, num_bytes);
+    *(void**)curoff += num_bytes;
+}
+
+static void copy_in(void *uva, uint64_t num_bytes, void *curoff)
+{
+    memcpy(uva, *((void**)(curoff)), num_bytes);
+    *(void**)curoff += num_bytes;
+}
+
+static void do_hash(void *uva, uint64_t num_bytes, void *priv)
+{
+    uint64_t i;
+    uint64_t *curhash = (uint64_t *)priv;
+
+    for (i=0;i<num_bytes;i++) { 
+       *curhash += ((uint8_t*)uva)[i];
+    }
+}
+
+int v3_guest_mem_read(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, char *data)
+{
+    void *cpy_ptr=data;
+
+    return v3_guest_mem_apply(copy_out,map,gpa,num_bytes,&cpy_ptr);
+}
+
+int v3_guest_mem_write(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, char *data)
+{
+    void *cpy_ptr=data;
+
+    return v3_guest_mem_apply(copy_in,map,gpa,num_bytes,&cpy_ptr);
+}
+
+int v3_guest_mem_hash(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, uint64_t *hash)
+{
+    *hash = 0;
+
+    return v3_guest_mem_apply(do_hash,map,gpa,num_bytes,hash);
+}
+
index 907502c..508f351 100644 (file)
@@ -5,7 +5,8 @@
 #include "v3_ctrl.h"
 
 struct v3_guest_mem_block {
-  void     *gpa;      // guest physical address is
+  void     *gpa;      // guest physical address this region starts at
+  void     *cumgpa;   // cumulative GPA in the VM including this block
   void     *hpa;      // mapped to this host physical address
   void     *uva;      // which is mapped here in this process
   uint64_t numpages;  // this many 4K pages
@@ -27,7 +28,60 @@ struct v3_guest_mem_map * v3_guest_mem_get_map(char *vmdev);
 int v3_map_guest_mem(struct v3_guest_mem_map *map);
 // This function unmaps it - it assumes myaddrs are valid
 int v3_unmap_guest_mem(struct v3_guest_mem_map *map);
+// What is the first GPA of this guest that contains memory ?
+void *v3_gpa_start(struct v3_guest_mem_map *map);
+// What is the last GPA of this guest that contains memory ?
+void *v3_gpa_end(struct v3_guest_mem_map *map);
+// map from a gpa to a uva, optionally giving the number of 
+// subsequent bytes for which the mapping is continguous
+static inline void *v3_gpa_to_uva(struct v3_guest_mem_map *map, void *gpa, uint64_t *num_bytes)
+{
+    uint64_t left, right, middle;
 
+    if (!map->fd) { 
+       // not mapped
+       if (num_bytes) { *num_bytes=0;}
+       return 0;
+    }
+    
+    left = 0; right=map->numblocks-1;
+    
+    while (right>=left) { 
+       middle = (right+left)/2;
+       if (gpa > map->block[middle].cumgpa) { 
+           left=middle+1;
+       } else if (gpa < map->block[middle].gpa) { 
+           right=middle-1;
+       } else {
+           break;
+       }
+    }
+
+    if (right>=left) { 
+       if (num_bytes) { 
+           *num_bytes = map->block[middle].cumgpa - gpa + 1;
+       }
+       return map->block[middle].uva + (gpa - map->block[middle].gpa);
+    } else {
+       if (num_bytes) { 
+           *num_bytes=0;
+       } 
+       return 0;
+    }
+}
+
+// efficiently map function over the specified guest memory
+int v3_guest_mem_apply(void (*func)(void *data, uint64_t num_bytes, void *priv),
+                      struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, void *priv);
+
+// read data out of guest
+int v3_guest_mem_read(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, char *data);
+
+// write data into  guest
+int v3_guest_mem_write(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, char *data);
+
+// hash the guest's data
+int v3_guest_mem_hash(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, uint64_t *hash);
 
 #endif
 
diff --git a/linux_usr/v3_guest_mem_access.c b/linux_usr/v3_guest_mem_access.c
new file mode 100644 (file)
index 0000000..2162ea8
--- /dev/null
@@ -0,0 +1,146 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#include "v3_guest_mem.h"
+
+void usage() 
+{
+  fprintf(stderr,"usage: v3_guest_mem_access /dev/v3-vmN read|write|hash gpa_hex numbytes [<data]\n");
+}
+
+int main(int argc, char *argv[])
+{
+  char *vmdev;
+  enum {READ, WRITE, HASH} mode;
+  uint64_t gpa;
+  uint64_t numbytes;
+  struct v3_guest_mem_map *map;
+  uint64_t i;
+  int rc;
+  uint64_t hash;
+  uint8_t *data=0;
+    
+  if (argc!=5) { 
+    usage();
+    return -1;
+  }
+
+  vmdev=argv[1];
+  
+  if (toupper(argv[2][0])=='R') { 
+      mode=READ;
+  } else if (toupper(argv[2][0])=='W') {
+      mode=WRITE;
+  } else if (toupper(argv[2][0])=='H') {
+      mode=HASH;
+  } else {
+      fprintf(stderr,"Unknown mode %s\n", argv[2]);
+      return -1;
+  }
+  
+  if (sscanf(argv[3],"%llx",&gpa)!=1) { 
+    fprintf(stderr,"Don't understand address %s\n",argv[3]);
+    return -1;
+  }
+
+  numbytes=atol(argv[4]);
+
+  if (!(map=v3_guest_mem_get_map(vmdev))) { 
+    fprintf(stderr,"Cannot get guest memory map for %s\n",vmdev);
+    return -1;
+  }
+  
+  //for (i=0; i< map->numblocks; i++) { 
+  //  fprintf(stderr,"Region %llu: gpa=%p, hpa=%p, numpages=%llu\n", 
+  //    i, map->block[i].gpa, map->block[i].hpa, map->block[i].numpages);
+  //}  
+
+  if (v3_map_guest_mem(map)) { 
+    fprintf(stderr, "Cannot map guest memory\n");
+    free(map);
+    return -1;
+  }
+
+  if (mode==READ || mode==WRITE) { 
+      data = malloc(numbytes);
+      if (!data) { 
+         fprintf(stderr, "Cannot allocate memory\n");
+         v3_unmap_guest_mem(map);
+         return -1;
+      }
+  }
+
+  switch (mode) { 
+      case WRITE:
+         for (i=0;i<numbytes;) {
+             rc = read(0,data+i,(numbytes-i));
+             if (rc<=0) {
+                 fprintf(stderr, "Cannot read from stdin\n");
+                 free(data);
+                 v3_unmap_guest_mem(map);
+                 return -1;
+             } else {
+                 i+=rc;
+             }
+         }
+         if (v3_guest_mem_write(map,(void*)gpa,numbytes,data)) { 
+             fprintf(stderr, "Failed to write all of guest memory\n");
+             free(data);
+             v3_unmap_guest_mem(map);
+             return -1;
+         }
+
+         fprintf(stderr, "Write complete (%llu bytes)\n", numbytes);
+
+         free(data);
+
+         break;
+         
+      case READ:
+         if (v3_guest_mem_read(map,(void*)gpa,numbytes,data)) { 
+             fprintf(stderr, "Failed to read all of guest memory\n");
+             free(data);
+             v3_unmap_guest_mem(map);
+             return -1;
+         }
+         for (i=0;i<numbytes;) {
+             rc = write(1,data+i,(numbytes-i));
+             if (rc<=0) {
+                 fprintf(stderr, "Cannot write to stdout\n");
+                 free(data);
+                 v3_unmap_guest_mem(map);
+                 return -1;
+             } else {
+                 i+=rc;
+             }
+         }
+         
+         fprintf(stderr, "Read complete (%llu bytes)\n", numbytes);
+         
+         free(data);
+
+         break;
+         
+      case HASH:
+         if (v3_guest_mem_hash(map,(void*)gpa,numbytes,&hash)) { 
+             fprintf(stderr, "Failed to hash all of guest memory\n");
+             v3_unmap_guest_mem(map);
+             return -1;
+         }
+         
+         fprintf(stderr, "Hash complete (%llu bytes), result is 0x%llx\n", numbytes, hash);
+         
+         break;
+         
+  }
+  
+  
+  if (v3_unmap_guest_mem(map)) { 
+      fprintf(stderr, "Cannot unmap guest memory\n");
+      free(map);
+      return -1;
+  }
+  
+  return 0;
+}
+  
diff --git a/linux_usr/v3_guest_mem_example.c b/linux_usr/v3_guest_mem_example.c
deleted file mode 100644 (file)
index 4dd6235..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#include <stdint.h>
-#include <stdio.h>
-
-#include "v3_guest_mem.h"
-
-void usage() 
-{
-  fprintf(stderr,"usage: v3_guest_mem_example /dev/v3-vmN read|write gpa_hex numbytes [<data]\n");
-}
-
-int main(int argc, char *argv[])
-{
-  char *vmdev;
-  enum {READ, WRITE} mode;
-  uint64_t gpa;
-  uint64_t numbytes;
-  struct v3_guest_mem_map *map;
-  uint64_t i;
-    
-  if (argc!=5) { 
-    usage();
-    return -1;
-  }
-
-  vmdev=argv[1];
-  
-  if (toupper(argv[2][0])=='R') { 
-    mode=READ;
-  } else if (toupper(argv[2][0]=='W')) {
-    mode=WRITE;
-  } else {
-    fprintf(stderr,"Unknown mode %s\n", argv[2]);
-    return -1;
-  }
-  
-  if (sscanf(argv[3],"%llx",&gpa)!=1) { 
-    fprintf(stderr,"Don't understand address %s\n",argv[3]);
-    return -1;
-  }
-
-  numbytes=atol(argv[4]);
-
-  if (!(map=v3_guest_mem_get_map(vmdev))) { 
-    fprintf(stderr,"Cannot get guest memory map for %s\n",vmdev);
-    return -1;
-  }
-  
-  for (i=0; i< map->numblocks; i++) { 
-    fprintf(stderr,"Region %llu: gpa=%p, hpa=%p, numpages=%llu\n", 
-           i, map->block[i].gpa, map->block[i].hpa, map->block[i].numpages);
-  }  
-
-  if (map->numblocks!=1) { 
-    fprintf(stderr,"Don't handle multiregion map yet\n");
-    return -1;
-  }
-  
-  if (!( ((void*)(gpa) >= map->block[0].gpa) &&
-        (numbytes <= map->block[0].numpages*4096))) { 
-    fprintf(stderr,"request (%p to %p) is out of range\n",
-           gpa, gpa+numbytes-1);
-    return -1;
-  }
-
-  if (v3_map_guest_mem(map)) { 
-    fprintf(stderr, "Cannot map guest memory\n");
-    free(map);
-    return -1;
-  }
-
-  for (i=0; i<numbytes; i++) {
-    uint8_t cur;
-    if (mode==WRITE) {
-      if (read(0,&cur,1)!=1) { 
-       fprintf(stderr,"can't get data from stdin for byte %llu\n", i);
-       break;
-      }
-      *((uint8_t*)(map->block[0].uva+gpa+i))=cur;
-    } else {
-      cur = *((uint8_t *)(map->block[0].uva+gpa+i));
-      //      fprintf(stderr, "read %llu from uva=%p, ptr=%p\n",i,map->block[0].uva, map->block[0].uva+gpa+i);
-      if (write(1,&cur,1)!=1) { 
-       fprintf(stderr,"can't write data to stdout for byte %llu\n", i);
-       break;
-      }
-    }
-  }
-      
-
-  if (v3_unmap_guest_mem(map)) { 
-    fprintf(stderr, "Cannot unmap guest memory\n");
-    free(map);
-    return -1;
-  }
-}
-