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.


fa398e959b35f9cfc89b24bfcba29f5b201447fc
[palacios.git] / linux_usr / v3_guest_mem.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <fcntl.h>
5 #include <sys/mman.h>
6
7 #include "v3_guest_mem.h"
8
9
10
11 #define GUEST_FILE "/proc/v3vee/v3-guests-details"
12 //#define GUEST_FILE "/v-test/numa/palacios-devel/test.proc"
13 #define MAXLINE 65536
14
15 struct v3_guest_mem_map * v3_guest_mem_get_map(char *vmdev)
16 {
17   FILE *f;
18   int rc;
19   int i;
20   char buf[MAXLINE];
21   char dev[MAXLINE];
22   uint64_t start, end, num;
23   uint64_t guest_cur;
24   uint64_t num_regions;
25   uint64_t num_regions_shown;
26   
27
28   if (!(f=fopen(GUEST_FILE,"r"))) { 
29       fprintf(stderr,"Cannot open %s - is Palacios active?\n",GUEST_FILE);
30       return 0;
31   }
32
33   while (1) {
34       if (!fgets(buf,MAXLINE,f)) {
35           fprintf(stderr,"Could not find info for %s\n",vmdev);
36           return 0;
37       }
38       if (sscanf(buf,"Device: %s",dev)==1) { 
39           if (!strcmp(dev,vmdev)) {
40               // found our VM
41               break;
42           } 
43       }
44   }
45         
46   // Now we need the number of regions
47   while (1) {
48       if (!fgets(buf,MAXLINE,f)) {
49           fprintf(stderr,"Could not find number of regions for %s\n",vmdev);
50           return 0;
51       }
52       if (sscanf(buf,"Regions: %llu (%llu shown)",&num_regions,&num_regions_shown)==2) {
53           break;
54       }
55   }
56
57   if (num_regions != num_regions_shown) { 
58       fprintf(stderr,"Cannot see all regions for %s\n",vmdev);
59       return 0;
60   }
61  
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));
64   if (!m) { 
65       fprintf(stderr, "Cannot allocate space\n");
66       fclose(f);
67       return 0;
68   }
69   
70   memset(m,0,sizeof(struct v3_guest_mem_map)+num_regions*sizeof(struct v3_guest_mem_block));
71
72   m->numblocks=num_regions;
73
74   // Now collect the region info
75   guest_cur=0;
76   i=0;
77   while (i<num_regions) { 
78       if (!fgets(buf,MAXLINE,f)) {
79           fprintf(stderr,"Did not find all regions...\n");
80           free(m);
81           return 0;
82       }
83       if (sscanf(buf," region %d has HPAs %llx-%llx",&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);
89           }
90           guest_cur+=end-start;
91           m->block[i].cumgpa=(void*)(guest_cur-1);
92           i++;
93       }
94   }
95
96   fclose(f);
97
98   return m;
99
100 }
101
102 int v3_map_guest_mem(struct v3_guest_mem_map *map)
103 {
104   uint64_t i;
105   
106   if (map->fd) {
107     fprintf(stderr, "Memory appears to already be mapped\n");
108     return -1;
109   }
110
111   map->fd = open("/dev/mem", O_RDWR | O_SYNC);
112
113   if (map->fd<0) { 
114     fprintf(stderr, "Cannot open /dev/mem - are you root?\n");
115     map->fd=0;
116     return -1;
117   }
118
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, 
125                              MAP_SHARED, 
126                              map->fd, 
127                              (off_t) (map->block[i].hpa));
128
129     if (map->block[i].uva == MAP_FAILED) { 
130       fprintf(stderr, "Failed to map block %llu\n",i);
131       map->block[i].uva=0;
132       v3_unmap_guest_mem(map);
133       return -1;
134     }
135   }
136    
137   return 0;
138     
139 }
140
141 int v3_unmap_guest_mem(struct v3_guest_mem_map *map)
142 {
143   uint64_t i;
144
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);
148       map->block[i].uva=0;
149     }
150   }
151   if (map->fd) { 
152     close(map->fd);
153     map->fd=0;
154   }
155   return 0;
156 }
157
158
159 void *v3_gpa_start(struct v3_guest_mem_map *map)
160 {
161     return 0; // all guests start at zero for now
162 }
163
164 void *v3_gpa_end(struct v3_guest_mem_map *map)
165 {
166     struct v3_guest_mem_block *l = &(map->block[map->numblocks-1]); 
167
168     // currently, the regions are consecutive, so we just need the last block
169     return l->gpa+l->numpages*4096-1; 
170 }
171
172
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)
175 {
176     void *cur_gpa;
177     void *cur_uva;
178     uint64_t left_bytes;
179     uint64_t block_bytes;
180     
181     if (!(map->fd)) {
182         return -1;
183     }
184     
185     if (gpa < v3_gpa_start(map) || gpa+num_bytes-1 > v3_gpa_end(map)) { 
186         return -1;
187     }
188
189     cur_gpa = gpa;
190     left_bytes = num_bytes;
191
192     while (left_bytes) { 
193         cur_uva = v3_gpa_to_uva(map, cur_gpa, &block_bytes);
194         if (!cur_uva) { 
195             return -1;
196         }
197         if (block_bytes>left_bytes) { 
198             block_bytes = left_bytes;
199         }
200         func(cur_uva,block_bytes,priv);
201         left_bytes-=block_bytes;
202         cur_gpa+=block_bytes;
203     }
204     
205     return 0;
206 }
207
208
209
210 static void copy_out(void *uva, uint64_t num_bytes, void *curoff)
211 {
212     memcpy(*((void**)(curoff)), uva, num_bytes);
213     *(void**)curoff += num_bytes;
214 }
215
216 static void copy_in(void *uva, uint64_t num_bytes, void *curoff)
217 {
218     memcpy(uva, *((void**)(curoff)), num_bytes);
219     *(void**)curoff += num_bytes;
220 }
221
222 static void do_hash(void *uva, uint64_t num_bytes, void *priv)
223 {
224     uint64_t i;
225     uint64_t *curhash = (uint64_t *)priv;
226
227     for (i=0;i<num_bytes;i++) { 
228         *curhash += ((uint8_t*)uva)[i];
229     }
230 }
231
232 int v3_guest_mem_read(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, char *data)
233 {
234     void *cpy_ptr=data;
235
236     return v3_guest_mem_apply(copy_out,map,gpa,num_bytes,&cpy_ptr);
237 }
238
239 int v3_guest_mem_write(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, char *data)
240 {
241     void *cpy_ptr=data;
242
243     return v3_guest_mem_apply(copy_in,map,gpa,num_bytes,&cpy_ptr);
244 }
245
246 int v3_guest_mem_hash(struct v3_guest_mem_map *map, void *gpa, uint64_t num_bytes, uint64_t *hash)
247 {
248     *hash = 0;
249
250     return v3_guest_mem_apply(do_hash,map,gpa,num_bytes,hash);
251 }
252
253
254
255 int v3_guest_mem_track_start(char *vmdev, 
256                              v3_mem_track_access_t access, 
257                              v3_mem_track_reset_t reset, 
258                              uint64_t period)
259 {
260     struct v3_mem_track_cmd cmd;
261
262     cmd.request=V3_MEM_TRACK_START;
263     cmd.config.access_type=access;
264     cmd.config.reset_type=reset;
265     cmd.config.period=period;
266
267     return v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_CMD,&cmd);
268
269 }
270
271 int v3_guest_mem_track_stop(char *vmdev)
272 {
273     struct v3_mem_track_cmd cmd;
274
275     cmd.request=V3_MEM_TRACK_STOP;
276
277     return v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_CMD,&cmd);
278
279 }
280
281
282 #define CEIL_DIV(x,y) (((x)/(y)) + !!((x)%(y)))
283
284 static uint8_t *alloc_bitmap(uint64_t num_pages) 
285 {
286     uint8_t *b;
287     
288     if (!(b =  malloc(CEIL_DIV(num_pages,8)))) {
289         return NULL;
290     }
291     
292     memset(b,0,CEIL_DIV(num_pages,8));
293     
294     return b;
295 }
296
297
298 static void free_bitmap(uint8_t *b)
299 {
300     if (b) { 
301         free(b);
302     }
303
304 }
305
306
307 void v3_guest_mem_track_free_snapshot(v3_mem_track_snapshot *s)
308 {
309     int i;
310
311     if (s) {
312         for (i=0;i<s->num_cores;i++) {
313             free_bitmap(s->core[i].access_bitmap);
314         }
315         free(s);
316     }
317 }
318
319
320 static v3_mem_track_snapshot *alloc_snapshot(uint64_t num_cores, uint64_t num_pages) 
321 {
322     int i;
323     v3_mem_track_snapshot *s;
324
325     s = malloc(sizeof(v3_mem_track_snapshot) + sizeof(struct v3_core_mem_track) * num_cores);
326     
327     if (!s) { 
328         return NULL;
329     }
330
331     memset(s,0,sizeof(v3_mem_track_snapshot) + sizeof(struct v3_core_mem_track) * num_cores);
332     
333     s->num_cores=num_cores;
334
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);
338             return NULL;
339         }
340         s->core[i].num_pages=num_pages;
341     }
342
343     return s;
344 }
345
346
347 v3_mem_track_snapshot *v3_guest_mem_track_snapshot(char *vmdev)
348 {
349     struct v3_mem_track_sizes size;
350     v3_mem_track_snapshot *s;
351     int rc;
352
353     rc = v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_SIZE,&size);
354
355     if (rc) { 
356         return 0;
357     }
358
359     //printf("returned size num_cores=%u, num_pages=%llu",size.num_cores,size.num_pages);
360
361     // allocate a snapshot;
362     if (!(s=alloc_snapshot(size.num_cores,size.num_pages))) { 
363         return 0;
364     }
365
366     
367
368     if (v3_vm_ioctl(vmdev,V3_VM_MEM_TRACK_SNAP,s)) { 
369         v3_guest_mem_track_free_snapshot(s);
370         return 0;
371     }
372
373     return s;
374 }
375     
376
377