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.


Linux user-space tools for memory tracking functionality
Peter Dinda [Fri, 27 Jun 2014 00:55:36 +0000 (19:55 -0500)]
linux_usr/Makefile
linux_usr/v3_guest_mem.c
linux_usr/v3_guest_mem.h
linux_usr/v3_guest_mem_track.c [new file with mode: 0644]
palacios/src/palacios/vmm_checkpoint.c

index 51fcc74..f1aaaca 100644 (file)
@@ -32,7 +32,8 @@ BASE_EXECS =  v3_mem \
                v3_send \
                v3_receive \
                v3_pci \
-               v3_guest_mem_access
+               v3_guest_mem_access \
+               v3_guest_mem_track
 
 
 #
@@ -78,7 +79,7 @@ ifeq ($(STATIC),1)
   CFLAGS += -static 
 endif
 
-CFLAGS += -I../linux_module
+CFLAGS += -I../linux_module -I../palacios/include/
 
 CC = gcc -g
 AR = ar
@@ -164,15 +165,20 @@ 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
+# guest memory access by mmap 
+# guest memory reference tracking via mem_track interface
+# examples
 #
 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_access : v3_guest_mem_access.c libv3_guest_mem.a
-       $(CC) $(CFLAGS) $< -L. -lv3_guest_mem -o $@
+v3_guest_mem_access : v3_guest_mem_access.c libv3_guest_mem.a libv3_ctrl.a
+       $(CC) $(CFLAGS) $< -L. -lv3_guest_mem -lv3_ctrl -o $@
+
+v3_guest_mem_track : v3_guest_mem_track.c libv3_guest_mem.a libv3_ctrl.a
+       $(CC) $(CFLAGS) $< -L. -lv3_guest_mem -lv3_ctrl -o $@
 
 
 #
index ed1cd44..f1fe9de 100644 (file)
@@ -243,3 +243,128 @@ int v3_guest_mem_hash(struct v3_guest_mem_map *map, void *gpa, uint64_t num_byte
     return v3_guest_mem_apply(do_hash,map,gpa,num_bytes,hash);
 }
 
+
+
+int v3_guest_mem_track_start(char *vmdev, 
+                            v3_mem_track_access_t access, 
+                            v3_mem_track_reset_t reset, 
+                            uint64_t period)
+{
+    struct v3_mem_track_cmd cmd;
+
+    cmd.request=V3_MEM_TRACK_START;
+    cmd.config.access_type=access;
+    cmd.config.reset_type=reset;
+    cmd.config.period=period;
+
+    return v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_CMD,&cmd);
+
+}
+
+int v3_guest_mem_track_stop(char *vmdev)
+{
+    struct v3_mem_track_cmd cmd;
+
+    cmd.request=V3_MEM_TRACK_STOP;
+
+    return v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_CMD,&cmd);
+
+}
+
+
+#define CEIL_DIV(x,y) (((x)/(y)) + !!((x)%(y)))
+
+static uint8_t *alloc_bitmap(uint64_t num_pages) 
+{
+    uint8_t *b;
+    
+    if (!(b =  malloc(CEIL_DIV(num_pages,8)))) {
+       return NULL;
+    }
+    
+    memset(b,0,CEIL_DIV(num_pages,8));
+    
+    return b;
+}
+
+
+static void free_bitmap(uint8_t *b)
+{
+    if (b) { 
+       free(b);
+    }
+
+}
+
+
+void v3_guest_mem_track_free_snapshot(v3_mem_track_snapshot *s)
+{
+    int i;
+
+    if (s) {
+       for (i=0;i<s->num_cores;i++) {
+           free_bitmap(s->core[i].access_bitmap);
+       }
+       free(s);
+    }
+}
+
+
+static v3_mem_track_snapshot *alloc_snapshot(uint64_t num_cores, uint64_t num_pages) 
+{
+    int i;
+    v3_mem_track_snapshot *s;
+
+    s = malloc(sizeof(v3_mem_track_snapshot) + sizeof(struct v3_core_mem_track) * num_cores);
+    
+    if (!s) { 
+       return NULL;
+    }
+
+    memset(s,0,sizeof(v3_mem_track_snapshot) + sizeof(struct v3_core_mem_track) * num_cores);
+    
+    s->num_cores=num_cores;
+
+    for (i=0;i<num_cores;i++) {
+       if (!(s->core[i].access_bitmap = alloc_bitmap(num_pages))) { 
+           v3_guest_mem_track_free_snapshot(s);
+           return NULL;
+       }
+       s->core[i].num_pages=num_pages;
+    }
+
+    return s;
+}
+
+
+v3_mem_track_snapshot *v3_guest_mem_track_snapshot(char *vmdev)
+{
+    struct v3_mem_track_sizes size;
+    v3_mem_track_snapshot *s;
+    int rc;
+
+    rc = v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_SIZE,&size);
+
+    if (rc) { 
+       return 0;
+    }
+
+    //printf("returned size num_cores=%u, num_pages=%llu",size.num_cores,size.num_pages);
+
+    // allocate a snapshot;
+    if (!(s=alloc_snapshot(size.num_cores,size.num_pages))) { 
+       return 0;
+    }
+
+    
+
+    if (v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_SNAP,s)) { 
+       v3_guest_mem_track_free_snapshot(s);
+       return 0;
+    }
+
+    return s;
+}
+    
+
+
index 508f351..cacddd1 100644 (file)
@@ -4,6 +4,13 @@
 #include <stdint.h>
 #include "v3_ctrl.h"
 
+
+#include "memtrack.h"
+
+/**************************/
+/* Access to guest memory */
+/**************************/
+
 struct v3_guest_mem_block {
   void     *gpa;      // guest physical address this region starts at
   void     *cumgpa;   // cumulative GPA in the VM including this block
@@ -83,5 +90,25 @@ int v3_guest_mem_write(struct v3_guest_mem_map *map, void *gpa, uint64_t num_byt
 // 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);
 
+
+/********************************/
+/* Guest memory access tracking */
+/********************************/
+
+#include "../linux_module/memtrack.h"
+
+int v3_guest_mem_track_start(char *vmdev, 
+                            v3_mem_track_access_t access, 
+                            v3_mem_track_reset_t reset, 
+                            uint64_t period);
+
+int v3_guest_mem_track_stop(char *vmdev);
+
+v3_mem_track_snapshot *v3_guest_mem_track_snapshot(char *vmdev);
+
+void v3_guest_mem_track_free_snapshot(v3_mem_track_snapshot *snap);
+
+
+
 #endif
 
diff --git a/linux_usr/v3_guest_mem_track.c b/linux_usr/v3_guest_mem_track.c
new file mode 100644 (file)
index 0000000..7a257dd
--- /dev/null
@@ -0,0 +1,235 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#include "v3_guest_mem.h"
+
+void usage() 
+{
+    fprintf(stderr,"usage: v3_guest_mem_track /dev/v3-vmN command\n");
+    fprintf(stderr,"    where command is one of the following\n");
+    fprintf(stderr,"           start oneshot|periodic period access\n");
+    fprintf(stderr,"               access=combination of rwx (only rwx currently)\n");
+    fprintf(stderr,"           stop\n");
+    fprintf(stderr,"           snapshot bin|text file|_\n\n");
+}
+
+int start(char *vm, char *reset_str, char *period_str, char *access_str)
+{
+  v3_mem_track_access_t access;
+  v3_mem_track_reset_t reset;
+  uint64_t period;
+
+  if (!strcasecmp(reset_str,"oneshot")) { 
+    reset=V3_MEM_TRACK_ONESHOT;
+  } else if (!strcasecmp(reset_str,"periodic")) { 
+    reset=V3_MEM_TRACK_PERIODIC;
+  } else {
+    usage();
+    return -1;
+  }
+
+  if (!strcasecmp(access_str,"rwx")) {
+    access=V3_MEM_TRACK_ACCESS;
+  } else {
+    usage();
+    return -1;
+  }
+
+  period=atoll(period_str);
+
+  return v3_guest_mem_track_start(vm,access,reset,period);
+}
+
+
+int stop(char *vm)
+{
+  return v3_guest_mem_track_stop(vm);
+}
+
+int text_out(char *vm, char *target, v3_mem_track_snapshot *s)
+{
+  FILE *fd;
+  int close=0;
+  struct timeval tv;
+  double thetime;
+  uint64_t i,j;
+  uint64_t count;
+
+  gettimeofday(&tv,0);
+  thetime = tv.tv_sec + ((double)tv.tv_usec)/1.0e6;
+
+  if (!strcasecmp(target,"_")) { 
+    fd = stdout;
+  } else {
+    if (!(fd=fopen(target,"w"))) { 
+      fprintf(stderr,"Cannot open %s for write\n",target);
+      return -1;
+    }
+    close=1;
+  }
+
+  fprintf(fd,"Memory Tracking Snapshot\n\n");
+  fprintf(fd,"VM:\t%s\n",vm);
+  fprintf(fd,"Time:\t%lf\n\n",thetime);
+  fprintf(fd,"Reset:\t%s\n", 
+         s->reset_type==V3_MEM_TRACK_ONESHOT ? "oneshot" :
+         s->reset_type==V3_MEM_TRACK_PERIODIC ? "periodic" : "UNKNOWN");
+  fprintf(fd,"Interval:\t%llu cycles\n", s->period);
+  fprintf(fd,"Access:\t%s%s%s\n",
+         s->access_type&V3_MEM_TRACK_READ ? "r" : "",
+         s->access_type&V3_MEM_TRACK_WRITE ? "w" : "",
+         s->access_type&V3_MEM_TRACK_EXEC ? "x" : "");
+         
+  fprintf(fd,"Cores:\t%llu\n",s->num_cores);
+  fprintf(fd,"Pages:\t%llu\n\n",s->core[0].num_pages);
+
+  
+  for (i=0;i<s->num_cores;i++) { 
+    fprintf(fd,"Core %llu (%llu to %llu, ",
+           i, s->core[i].start_time, s->core[i].end_time);
+    count=0;
+    for (j=0;j<s->core[i].num_pages;j++) {
+       count+=GET_BIT(s->core[i].access_bitmap,j);
+    }
+    fprintf(fd," %llu pages touched) : ", count);
+    for (j=0;j<s->core[i].num_pages;j++) {
+      if (GET_BIT(s->core[i].access_bitmap,j)) { 
+       fprintf(fd,"X");
+      } else {
+       fprintf(fd,".");
+      }
+    }
+    fprintf(fd,"\n");
+  }
+
+  fprintf(fd,"\n");
+
+  if (close) { 
+    fclose(fd);
+  }
+  
+  return 0;
+
+}
+  
+int write_all(int fd, void *buf, int n)
+{
+  int rc;
+
+  while (n) { 
+    rc=write(fd,buf,n);
+    if (rc<=0) { 
+      return -1;
+    } 
+    buf+=rc;
+    n-=rc;
+  }
+  return 0;
+}
+
+
+int bin_out(char *vm, char *target, v3_mem_track_snapshot *s)
+{
+  int fd;
+  int doclose=0;
+  struct timeval tv;
+  double thetime;
+  uint64_t i;
+
+  gettimeofday(&tv,0);
+  thetime = tv.tv_sec + ((double)tv.tv_usec)/1.0e6;
+
+  if (!strcasecmp(target,"_")) { 
+    fd = fileno(stdout);
+  } else {
+    if ((fd=open(target,O_WRONLY | O_CREAT, 0600))<0) { 
+      fprintf(stderr,"Cannot open %s for write\n",target);
+      return -1;
+    }
+    doclose=1;
+  }
+
+#define WRITE(x) write_all(fd, &(x), sizeof(x))
+
+  WRITE(thetime);
+  WRITE(s->reset_type);
+  WRITE(s->period);
+  WRITE(s->access_type);
+  WRITE(s->num_cores);
+  WRITE(s->core[0].num_pages);
+  for (i=0;i<s->num_cores;i++) { 
+    WRITE(i);
+    WRITE(s->core[i].start_time);
+    WRITE(s->core[i].end_time);
+    write_all(fd,s->core[i].access_bitmap,s->core[i].num_pages/8 + !!(s->core[i].num_pages%8));
+  }
+
+  if (doclose) { 
+    close(fd);
+  }
+  
+  return 0;
+
+}
+
+int snapshot(char *vm, char *format, char *target)
+{
+  v3_mem_track_snapshot *snap;
+
+  if (!(snap=v3_guest_mem_track_snapshot(vm))) { 
+    return -1;
+  }
+
+  if (!strcasecmp(format,"bin")) { 
+    int rc = bin_out(vm,target, snap);
+    v3_guest_mem_track_free_snapshot(snap);
+    return rc;
+  } else if (!strcasecmp(format,"text")) { 
+    int rc = text_out(vm,target, snap);
+    v3_guest_mem_track_free_snapshot(snap);
+    return rc;
+  } else {
+    return -1;
+  }
+}
+  
+
+int main(int argc, char *argv[])
+{
+  char *vm=argv[1];
+  char *cmd=argv[2];
+
+  if (argc<3) { 
+    usage();
+    return -1;
+  }
+
+  if (!strcasecmp(cmd,"start")) { 
+    if (argc!=6) { 
+      usage();
+      return -1;
+    } else {
+      return start(vm,argv[3],argv[4],argv[5]);
+    }
+  } else if (!strcasecmp(cmd,"stop")) { 
+    if (argc!=3) { 
+      usage();
+      return -1;
+    } else {
+      return stop(vm);
+    } 
+  } else if (!strcasecmp(cmd,"snapshot")) { 
+    if (argc!=5) { 
+      usage();
+      return -1;
+    } else {
+      return snapshot(vm,argv[3],argv[4]);
+    }
+  } else {
+    usage();
+    return -1;
+  }
+
+  return 0;
+}
+  
index 6bb8a79..8156cdf 100644 (file)
@@ -490,7 +490,7 @@ static struct mem_migration_state *start_page_tracking(struct v3_vm_info *vm)
        v3_invalidate_shadow_pts(&(vm->cores[i]));
       }
     } else if (vm->cores[0].shdw_pg_mode==NESTED_PAGING) { 
-      //v3_register_nested_paging_event_callback(vm,nested_paging_callback,m);
+       //v3_register_nested_paging_event_callback(vm,nested_paging_callback,m);
       
       for (i=0;i<vm->num_cores;i++) {
        //v3_invalidate_nested_addr_range(&(vm->cores[i]),0,vm->mem_size-1);