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.


Optional starting address for v3_mem
[palacios.git] / linux_usr / v3_mem.c
1 /* 
2  * V3 Control utility
3  * (c) Jack lange, 2010
4  */
5
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <fcntl.h> 
10 #include <sys/ioctl.h> 
11 #include <sys/stat.h> 
12 #include <sys/types.h> 
13 #include <unistd.h> 
14 #include <string.h>
15 #include <dirent.h> 
16
17 #include "v3_ctrl.h"
18
19 #define SYS_PATH "/sys/devices/system/memory/"
20
21 #define BUF_SIZE 128
22
23 int dir_filter(const struct dirent * dir) {
24     if (strncmp("memory", dir->d_name, 6) == 0) {
25         return 1;
26     }
27
28     return 0;
29 }
30
31
32
33 int dir_cmp(const struct dirent **dir1, const struct dirent ** dir2) {
34     int num1 = atoi((*dir1)->d_name + 6);
35     int num2 = atoi((*dir2)->d_name + 6);
36
37     return num1 - num2;
38 }
39
40
41
42 int main(int argc, char * argv[]) {
43     unsigned long long mem_size_bytes = 0;
44     unsigned long long mem_min_start = 0;
45     unsigned int block_size_bytes = 0;
46     int bitmap_entries = 0;
47     unsigned char * bitmap = NULL;
48     int num_blocks = 0;    
49     int reg_start = 0;
50     int mem_ready = 0;
51
52     if (argc != 2 && argc != 3) {
53         printf("usage: v3_mem <memory size (MB)> [min_start (MB)]\n\n"
54                "Offline memory for use in Palacios.\n"
55                "min_start is the minimum allowable starting address.\n"
56                "this is zero by default\n\n");  
57         return -1;
58     }
59
60
61     mem_size_bytes = atoll(argv[1]) * (1024 * 1024);
62
63     if (argc==3) { 
64         mem_min_start = atoll(argv[1]) * (1024 * 1024);
65     }
66
67     printf("Trying to find %dMB (%d bytes) of memory above %llu\n", atoll(argv[1]), mem_size_bytes, mem_min_start);
68
69     /* Figure out the block size */
70     {
71         int tmp_fd = 0;
72         char tmp_buf[BUF_SIZE];
73
74         tmp_fd = open(SYS_PATH "block_size_bytes", O_RDONLY);
75
76         if (tmp_fd == -1) {
77             perror("Could not open block size file: " SYS_PATH "block_size_bytes");
78             return -1;
79         }
80         
81         if (read(tmp_fd, tmp_buf, BUF_SIZE) <= 0) {
82             perror("Could not read block size file: " SYS_PATH "block_size_bytes");
83             return -1;
84         }
85         
86         close(tmp_fd);
87
88         block_size_bytes = strtoll(tmp_buf, NULL, 16);
89
90         printf("Memory block size is %dMB (%d bytes)\n", block_size_bytes / (1024 * 1024), block_size_bytes);
91              
92     }
93     
94
95     num_blocks =  mem_size_bytes / block_size_bytes;
96     if (mem_size_bytes % block_size_bytes) num_blocks++;
97
98     mem_min_start = block_size_bytes * 
99       ((mem_min_start / block_size_bytes) + (!!(mem_min_start % block_size_bytes)));
100          
101     printf("Looking for %d blocks of memory starting at %p (block %llu)\n", num_blocks, (void*)mem_min_start, mem_min_start/block_size_bytes);
102
103
104     // We now need to find <num_blocks> consecutive offlinable memory blocks
105
106     /* Scan the memory directories */
107     {
108         struct dirent ** namelist = NULL;
109         int size = 0;
110         int i = 0;
111         int j = 0;
112         int last_block = 0;
113         int first_block = mem_min_start/block_size_bytes;
114
115         last_block = scandir(SYS_PATH, &namelist, dir_filter, dir_cmp);
116         bitmap_entries = atoi(namelist[last_block - 1]->d_name + 6) + 1;
117
118         size = bitmap_entries / 8;
119         if (bitmap_entries % 8) size++;
120
121         bitmap = malloc(size);
122     if (!bitmap) {
123             printf("ERROR: could not allocate space for bitmap\n");
124             return -1;
125     }
126
127         memset(bitmap, 0, size);
128
129         for (i = 0 ; j < bitmap_entries - 1; i++) {
130             struct dirent * tmp_dir = namelist[i];
131             int block_fd = 0;       
132             char status_str[BUF_SIZE];
133             char fname[BUF_SIZE];
134
135             memset(status_str, 0, BUF_SIZE);
136             memset(fname, 0, BUF_SIZE);
137
138             snprintf(fname, BUF_SIZE, "%s%s/removable", SYS_PATH, tmp_dir->d_name);
139
140             j = atoi(tmp_dir->d_name + 6);
141             int major = j / 8;
142             int minor = j % 8;
143
144
145             if (i<first_block) { 
146               printf("Skipping %s due to minimum start constraint\n",fname);
147               continue;
148             }
149
150             printf("Checking %s...", fname);
151
152             block_fd = open(fname, O_RDONLY);
153             
154             if (block_fd == -1) {
155                 printf("Hotpluggable memory not supported...\n");
156                 return -1;
157             }
158
159             if (read(block_fd, status_str, BUF_SIZE) <= 0) {
160                 perror("Could not read block status");
161                 return -1;
162             }
163
164             close(block_fd);
165             
166             if (atoi(status_str) == 1) {
167                 printf("Removable\n");
168                 bitmap[major] |= (0x1 << minor);
169             } else {
170                 printf("Not removable\n");
171             }
172         }
173
174     }
175     
176     while (!mem_ready) {
177
178
179         /* Scan bitmap for enough consecutive space */
180         {
181             // num_blocks: The number of blocks we need to find
182             // bitmap: bitmap of blocks (1 == allocatable)
183             // bitmap_entries: number of blocks in the system/number of bits in bitmap
184             // reg_start: The block index where our allocation will start
185             
186             int i = 0;
187             int run_len = 0;
188             
189             for (i = 0; i < bitmap_entries; i++) {
190                 int i_major = i / 8;
191                 int i_minor = i % 8;
192             
193                 if (!(bitmap[i_major] & (0x1 << i_minor))) {
194                     reg_start = i + 1; // skip the region start to next entry
195                     run_len = 0;
196                     continue;
197                 }
198             
199                 run_len++;
200
201                 if (run_len >= num_blocks) {
202                     break;
203                 }
204             }
205
206             
207             if (run_len < num_blocks) {
208                 fprintf(stderr, "Could not find enough consecutive memory blocks... (found %d)\n", run_len);
209                 return -1;
210             }
211         }
212     
213
214         /* Offline memory blocks starting at reg_start */
215         {
216             int i = 0;
217
218             for (i = 0; i < num_blocks; i++) {  
219                 FILE * block_file = NULL;
220                 char fname[256];
221
222                 memset(fname, 0, 256);
223
224                 snprintf(fname, 256, "%smemory%d/state", SYS_PATH, i + reg_start);
225                 
226                 block_file = fopen(fname, "r+");
227
228                 if (block_file == NULL) {
229                     perror("Could not open block file");
230                     return -1;
231                 }
232
233
234                 printf("Offlining block %d (%s)\n", i + reg_start, fname);
235                 fprintf(block_file, "offline\n");
236
237                 fclose(block_file);
238             }
239         }
240
241
242         /*  We asked to offline set of blocks, but Linux could have lied. 
243          *  To be safe, check whether blocks were offlined and start again if not 
244          */
245
246         {
247             int i = 0;
248
249             mem_ready = 1; // Hopefully we are ok...
250
251
252             for (i = 0; i < num_blocks; i++) {
253                 int block_fd = 0;
254                 char fname[BUF_SIZE];
255                 char status_buf[BUF_SIZE];
256
257
258                 memset(fname, 0, BUF_SIZE);
259                 memset(status_buf, 0, BUF_SIZE);
260
261                 snprintf(fname, BUF_SIZE, "%smemory%d/state", SYS_PATH, i + reg_start);
262
263                 
264                 block_fd = open(fname, O_RDONLY);
265                 
266                 if (block_fd == -1) {
267                     perror("Could not open block file");
268                     return -1;
269                 }
270                 
271                 if (read(block_fd, status_buf, BUF_SIZE) <= 0) {
272                     perror("Could not read block status");
273                     return -1;
274                 }
275
276                 printf("Checking offlined block %d (%s)...", i + reg_start, fname);
277
278                 int ret = strncmp(status_buf, "offline", strlen("offline"));
279
280                 if (ret != 0) {
281                     int j = 0;
282                     int major = (i + reg_start) / 8;
283                     int minor = (i + reg_start) % 8;
284
285                     bitmap[major] &= ~(0x1 << minor); // mark the block as not removable in bitmap
286
287                     mem_ready = 0; // Keep searching
288
289                     printf("ERROR (%d)\n", ret);
290
291                     for (j = 0; j < i; j++) {
292                         FILE * block_file = NULL;
293                         char fname[256];
294                         
295                         memset(fname, 0, 256);
296                         
297                         snprintf(fname, 256, "%smemory%d/state", SYS_PATH, j + reg_start);
298                         
299                         block_file = fopen(fname, "r+");
300                         
301                         if (block_file == NULL) {
302                             perror("Could not open block file");
303                             return -1;
304                         }
305
306                         fprintf(block_file, "online\n");
307                         
308                         fclose(block_file);
309                     }
310
311                     break;
312                 } 
313                 
314                 printf("OK\n");
315                 
316             }
317             
318             
319         }
320     }
321
322     free(bitmap);
323
324     /* Memory is offlined. Calculate size and phys start addr to send to Palacios */
325
326     {
327         int v3_fd = 0;
328         struct v3_mem_region mem;
329         unsigned long long num_bytes = (unsigned long long)(num_blocks) * (unsigned long long)(block_size_bytes);
330         unsigned long long base_addr = (unsigned long long)(reg_start) * (unsigned long long)(block_size_bytes);
331
332         printf("Giving Palacios %lluMB of memory at (%p) \n", 
333                num_bytes / (1024 * 1024), base_addr);
334
335         mem.base_addr = base_addr;
336         mem.num_pages = num_bytes / 4096;
337
338         v3_fd = open(v3_dev, O_RDONLY);
339
340         if (v3_fd == -1) {
341             printf("Error opening V3Vee control device\n");
342             return -1;
343         }
344
345         ioctl(v3_fd, V3_ADD_MEMORY, &mem); 
346
347         /* Close the file descriptor.  */ 
348         close(v3_fd);   
349     }
350
351     return 0; 
352