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.


ed1cd443d157890112f77515d952ef66f7e83c94
[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