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.


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