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.


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