From: Peter Dinda Date: Fri, 27 Jun 2014 00:55:36 +0000 (-0500) Subject: Linux user-space tools for memory tracking functionality X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=2dd1cacbcfe8c0c9acc1d04098e0e2e65a505202 Linux user-space tools for memory tracking functionality --- diff --git a/linux_usr/Makefile b/linux_usr/Makefile index 51fcc74..f1aaaca 100644 --- a/linux_usr/Makefile +++ b/linux_usr/Makefile @@ -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 $@ # diff --git a/linux_usr/v3_guest_mem.c b/linux_usr/v3_guest_mem.c index ed1cd44..f1fe9de 100644 --- a/linux_usr/v3_guest_mem.c +++ b/linux_usr/v3_guest_mem.c @@ -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;inum_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;icore[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; +} + + + diff --git a/linux_usr/v3_guest_mem.h b/linux_usr/v3_guest_mem.h index 508f351..cacddd1 100644 --- a/linux_usr/v3_guest_mem.h +++ b/linux_usr/v3_guest_mem.h @@ -4,6 +4,13 @@ #include #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 index 0000000..7a257dd --- /dev/null +++ b/linux_usr/v3_guest_mem_track.c @@ -0,0 +1,235 @@ +#include +#include + +#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;inum_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;jcore[i].num_pages;j++) { + count+=GET_BIT(s->core[i].access_bitmap,j); + } + fprintf(fd," %llu pages touched) : ", count); + for (j=0;jcore[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;inum_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; +} + diff --git a/palacios/src/palacios/vmm_checkpoint.c b/palacios/src/palacios/vmm_checkpoint.c index 6bb8a79..8156cdf 100644 --- a/palacios/src/palacios/vmm_checkpoint.c +++ b/palacios/src/palacios/vmm_checkpoint.c @@ -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;inum_cores;i++) { //v3_invalidate_nested_addr_range(&(vm->cores[i]),0,vm->mem_size-1);