7 #include "v3_guest_mem.h"
11 #define GUEST_FILE "/proc/v3vee/v3-guests-details"
12 //#define GUEST_FILE "/v-test/numa/palacios-devel/test.proc"
15 struct v3_guest_mem_map * v3_guest_mem_get_map(char *vmdev)
22 uint64_t start, end, num;
25 uint64_t num_regions_shown;
28 if (!(f=fopen(GUEST_FILE,"r"))) {
29 fprintf(stderr,"Cannot open %s - is Palacios active?\n",GUEST_FILE);
34 if (!fgets(buf,MAXLINE,f)) {
35 fprintf(stderr,"Could not find info for %s\n",vmdev);
38 if (sscanf(buf,"Device: %s",dev)==1) {
39 if (!strcmp(dev,vmdev)) {
46 // Now we need the number of regions
48 if (!fgets(buf,MAXLINE,f)) {
49 fprintf(stderr,"Could not find number of regions for %s\n",vmdev);
52 if (sscanf(buf,"Regions: %lu (%lu shown)",&num_regions,&num_regions_shown)==2) {
57 if (num_regions != num_regions_shown) {
58 fprintf(stderr,"Cannot see all regions for %s\n",vmdev);
62 struct v3_guest_mem_map *m =
63 (struct v3_guest_mem_map *) malloc(sizeof(struct v3_guest_mem_map)+num_regions*sizeof(struct v3_guest_mem_block));
65 fprintf(stderr, "Cannot allocate space\n");
70 memset(m,0,sizeof(struct v3_guest_mem_map)+num_regions*sizeof(struct v3_guest_mem_block));
72 m->numblocks=num_regions;
74 // Now collect the region info
77 while (i<num_regions) {
78 if (!fgets(buf,MAXLINE,f)) {
79 fprintf(stderr,"Did not find all regions...\n");
83 if (sscanf(buf," region %lu has HPAs %lx-%lx",&num,&start,&end)==3) {
84 m->block[i].gpa = (void*)guest_cur;
85 m->block[i].hpa = (void*)start;
86 m->block[i].numpages = (end-start) / 4096 + !!((end-start) % 4096);
87 if ((end-start)%4096) {
88 fprintf(stderr,"Odd, region %d is a non-integral number of pages",i);
91 m->block[i].cumgpa=(void*)(guest_cur-1);
102 int v3_map_guest_mem(struct v3_guest_mem_map *map)
107 fprintf(stderr, "Memory appears to already be mapped\n");
111 map->fd = open("/dev/mem", O_RDWR | O_SYNC);
114 fprintf(stderr, "Cannot open /dev/mem - are you root?\n");
119 for (i=0; i<map->numblocks; i++) {
120 //fprintf(stderr,"Mapping %llu bytes of /dev/mem offset 0x%llx\n",
121 // map->block[i].numpages*4096, (off_t)(map->block[i].hpa));
122 map->block[i].uva = mmap(NULL,
123 map->block[i].numpages*4096,
124 PROT_READ | PROT_WRITE,
127 (off_t) (map->block[i].hpa));
129 if (map->block[i].uva == MAP_FAILED) {
130 fprintf(stderr, "Failed to map block %lu\n",i);
132 v3_unmap_guest_mem(map);
141 int v3_unmap_guest_mem(struct v3_guest_mem_map *map)
145 for (i=0; i<map->numblocks; i++) {
146 if (map->block[i].uva) {
147 munmap(map->block[i].uva, map->block[i].numpages*4096);
159 void *v3_gpa_start(struct v3_guest_mem_map *map)
161 return 0; // all guests start at zero for now
164 void *v3_gpa_end(struct v3_guest_mem_map *map)
166 struct v3_guest_mem_block *l = &(map->block[map->numblocks-1]);
168 // currently, the regions are consecutive, so we just need the last block
169 return l->gpa+l->numpages*4096-1;
173 int v3_guest_mem_apply(void (*func)(void *data, uint64_t num_bytes, void *priv),
174 struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, void *priv)
179 uint64_t block_bytes;
185 if (gpa < v3_gpa_start(map) || gpa+num_bytes-1 > v3_gpa_end(map)) {
190 left_bytes = num_bytes;
193 cur_uva = v3_gpa_to_uva(map, cur_gpa, &block_bytes);
197 if (block_bytes>left_bytes) {
198 block_bytes = left_bytes;
200 func(cur_uva,block_bytes,priv);
201 left_bytes-=block_bytes;
202 cur_gpa+=block_bytes;
210 static void copy_out(void *uva, uint64_t num_bytes, void *curoff)
212 memcpy(*((void**)(curoff)), uva, num_bytes);
213 *(void**)curoff += num_bytes;
216 static void copy_in(void *uva, uint64_t num_bytes, void *curoff)
218 memcpy(uva, *((void**)(curoff)), num_bytes);
219 *(void**)curoff += num_bytes;
222 static void do_hash(void *uva, uint64_t num_bytes, void *priv)
225 uint64_t *curhash = (uint64_t *)priv;
227 for (i=0;i<num_bytes;i++) {
228 *curhash += ((uint8_t*)uva)[i];
232 int v3_guest_mem_read(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, char *data)
236 return v3_guest_mem_apply(copy_out,map,gpa,num_bytes,&cpy_ptr);
239 int v3_guest_mem_write(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, char *data)
243 return v3_guest_mem_apply(copy_in,map,gpa,num_bytes,&cpy_ptr);
246 int v3_guest_mem_hash(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, uint64_t *hash)
250 return v3_guest_mem_apply(do_hash,map,gpa,num_bytes,hash);
255 int v3_guest_mem_track_start(char *vmdev,
256 v3_mem_track_access_t access,
257 v3_mem_track_reset_t reset,
260 struct v3_mem_track_cmd cmd;
262 cmd.request=V3_MEM_TRACK_START;
263 cmd.config.access_type=access;
264 cmd.config.reset_type=reset;
265 cmd.config.period=period;
267 return v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_CMD,&cmd);
271 int v3_guest_mem_track_stop(char *vmdev)
273 struct v3_mem_track_cmd cmd;
275 cmd.request=V3_MEM_TRACK_STOP;
277 return v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_CMD,&cmd);
282 #define CEIL_DIV(x,y) (((x)/(y)) + !!((x)%(y)))
284 static uint8_t *alloc_bitmap(uint64_t num_pages)
288 if (!(b = malloc(CEIL_DIV(num_pages,8)))) {
292 memset(b,0,CEIL_DIV(num_pages,8));
298 static void free_bitmap(uint8_t *b)
307 void v3_guest_mem_track_free_snapshot(v3_mem_track_snapshot *s)
312 for (i=0;i<s->num_cores;i++) {
313 free_bitmap(s->core[i].access_bitmap);
320 static v3_mem_track_snapshot *alloc_snapshot(uint64_t num_cores, uint64_t num_pages)
323 v3_mem_track_snapshot *s;
325 s = malloc(sizeof(v3_mem_track_snapshot) + sizeof(struct v3_core_mem_track) * num_cores);
331 memset(s,0,sizeof(v3_mem_track_snapshot) + sizeof(struct v3_core_mem_track) * num_cores);
333 s->num_cores=num_cores;
335 for (i=0;i<num_cores;i++) {
336 if (!(s->core[i].access_bitmap = alloc_bitmap(num_pages))) {
337 v3_guest_mem_track_free_snapshot(s);
340 s->core[i].num_pages=num_pages;
347 v3_mem_track_snapshot *v3_guest_mem_track_snapshot(char *vmdev)
349 struct v3_mem_track_sizes size;
350 v3_mem_track_snapshot *s;
353 rc = v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_SIZE,&size);
359 //printf("returned size num_cores=%u, num_pages=%llu",size.num_cores,size.num_pages);
361 // allocate a snapshot;
362 if (!(s=alloc_snapshot(size.num_cores,size.num_pages))) {
368 if (v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_SNAP,s)) {
369 v3_guest_mem_track_free_snapshot(s);