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.


User space library and example tool for accessing guest physical memory from host...
Peter Dinda [Wed, 13 Mar 2013 15:51:29 +0000 (10:51 -0500)]
linux_usr/Makefile
linux_usr/v3_guest_mem.c [new file with mode: 0644]
linux_usr/v3_guest_mem.h [new file with mode: 0644]
linux_usr/v3_guest_mem_example.c [new file with mode: 0644]

index e314209..609a4a4 100644 (file)
@@ -39,7 +39,8 @@ BASE_EXECS =  v3_mem \
 EXAMPLE_EXECS = v3_user_host_dev_example \
                v3_os_debug \
                v3_user_keyed_stream_example \
-               v3_user_keyed_stream_file 
+               v3_user_keyed_stream_file \
+               v3_guest_mem_example
 
 #
 # Currently experimental things
@@ -63,7 +64,7 @@ COPIED_EXECS = v3_x0vncserver v3_x0gui
 #
 # Libraries that we need to build
 #
-LIBS = libv3_user_host_dev.a libv3_user_keyed_stream.a libv3_ctrl.a
+LIBS = libv3_user_host_dev.a libv3_user_keyed_stream.a libv3_ctrl.a libv3_guest_mem.a
 
 BUILD_EXECS = $(BASE_EXECS) $(EXAMPLE_EXECS) $(EXPERIMENTAL_EXECS) 
 BUILD_LIBS = $(LIBS)
@@ -149,6 +150,17 @@ v3_user_keyed_stream_file : v3_user_keyed_stream_file.c libv3_user_keyed_stream.
        $(CC) $(CFLAGS) $< -I../linux_module -L. -lv3_user_keyed_stream -o $@
 
 
+# guest memory access by mmap and example
+#
+libv3_guest_mem.a : v3_guest_mem.c v3_guest_mem.h v3_ctrl.h
+       $(CC) $(CFLAGS) -c v3_guest_mem.c 
+       $(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
+       $(CC) $(CFLAGS) $< -L. -lv3_guest_mem -o $@
+
+
 
 #
 # VNC support is compiled separately
diff --git a/linux_usr/v3_guest_mem.c b/linux_usr/v3_guest_mem.c
new file mode 100644 (file)
index 0000000..24877eb
--- /dev/null
@@ -0,0 +1,124 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "v3_guest_mem.h"
+
+
+#define GUEST_FILE "/proc/v3vee/v3-guests"
+//#define GUEST_FILE "/441/pdinda/test.proc"
+#define MAXLINE 65536
+
+struct v3_guest_mem_map * v3_guest_mem_get_map(char *vmdev)
+{
+  FILE *f;
+  char buf[MAXLINE];
+  char name[MAXLINE];
+  char dev[MAXLINE];
+  char state[MAXLINE];
+  uint64_t start, end;
+  
+
+  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);
+      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;
+      fclose(f);
+      return m;
+    }
+  }
+  
+  fprintf(stderr,"%s not found\n",vmdev);
+  fclose(f);
+  return 0;
+
+}
+
+int v3_map_guest_mem(struct v3_guest_mem_map *map)
+{
+  uint64_t i;
+  
+  if (map->fd) {
+    fprintf(stderr, "Memory appears to already be mapped\n");
+    return -1;
+  }
+
+  map->fd = open("/dev/mem", O_RDWR | O_SYNC);
+
+  if (map->fd<0) { 
+    fprintf(stderr, "Cannot open /dev/mem - are you root?\n");
+    map->fd=0;
+    return -1;
+  }
+
+  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));
+    map->block[i].uva = mmap(NULL, 
+                            map->block[i].numpages*4096,
+                            PROT_READ | PROT_WRITE, 
+                            MAP_SHARED, 
+                            map->fd, 
+                            (off_t) (map->block[i].hpa));
+
+    if (map->block[i].uva == MAP_FAILED) { 
+      fprintf(stderr, "Failed to map block %llu\n",i);
+      map->block[i].uva=0;
+      v3_unmap_guest_mem(map);
+      return -1;
+    }
+  }
+   
+  return 0;
+    
+}
+
+int v3_unmap_guest_mem(struct v3_guest_mem_map *map)
+{
+  uint64_t i;
+
+  for (i=0; i<map->numblocks; i++) { 
+    if (map->block[i].uva) { 
+      munmap(map->block[i].uva, map->block[i].numpages*4096);
+      map->block[i].uva=0;
+    }
+  }
+  if (map->fd) { 
+    close(map->fd);
+    map->fd=0;
+  }
+  return 0;
+}
diff --git a/linux_usr/v3_guest_mem.h b/linux_usr/v3_guest_mem.h
new file mode 100644 (file)
index 0000000..907502c
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _V3_GUEST_MEM_
+#define _V3_GUEST_MEM_
+
+#include <stdint.h>
+#include "v3_ctrl.h"
+
+struct v3_guest_mem_block {
+  void     *gpa;      // guest physical address is
+  void     *hpa;      // mapped to this host physical address
+  void     *uva;      // which is mapped here in this process
+  uint64_t numpages;  // this many 4K pages
+};
+
+// Whole memory map of guest's physical memory
+// that is backed by host physical memory (ie, everything we 
+// can read or write from the host user space)
+struct v3_guest_mem_map {
+  int      fd;              // used by mmap
+  uint64_t numblocks;
+  struct v3_guest_mem_block block[0];
+};
+
+// This function gets the basic memory map, but does not map it
+struct v3_guest_mem_map * v3_guest_mem_get_map(char *vmdev);
+// This function mmaps it into the guest address space
+// and fills out the "myaddr" fields
+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);
+
+
+#endif
+
diff --git a/linux_usr/v3_guest_mem_example.c b/linux_usr/v3_guest_mem_example.c
new file mode 100644 (file)
index 0000000..4dd6235
--- /dev/null
@@ -0,0 +1,96 @@
+#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;
+  }
+}
+