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.


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