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.


Merge branch 'devel' of newskysaw.cs.northwestern.edu:/home/palacios/palacios into...
[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 (block_size_bytes % mem_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
102         bitmap_entries = scandir(SYS_PATH, &namelist, dir_filter, dir_cmp);
103
104         size = bitmap_entries / 8;
105         if (bitmap_entries % 8) size++;
106
107         bitmap = malloc(size);
108         memset(bitmap, 0, size);
109
110         for (i = 0; i < bitmap_entries; i++) {
111             struct dirent * tmp_dir = namelist[i];
112             int major = i / 8;
113             int minor = i % 8;
114             int block_fd = 0;       
115             char status_str[BUF_SIZE];
116             char fname[BUF_SIZE];
117
118             memset(status_str, 0, BUF_SIZE);
119             memset(fname, 0, BUF_SIZE);
120
121             snprintf(fname, BUF_SIZE, "%s%s/removable", SYS_PATH, tmp_dir->d_name);
122
123             printf("Checking %s...", fname);
124
125             block_fd = open(fname, O_RDONLY);
126             
127             if (block_fd == -1) {
128                 printf("Hotpluggable memory not supported...\n");
129                 return -1;
130             }
131
132             if (read(block_fd, status_str, BUF_SIZE) <= 0) {
133                 perror("Could not read block status");
134                 return -1;
135             }
136
137             close(block_fd);
138             
139             if (atoi(status_str) == 1) {
140                 printf("Removable\n");
141                 bitmap[major] |= (0x1 << minor);
142             } else {
143                 printf("Not removable\n");
144             }
145         }
146
147     }
148     
149     while (!mem_ready) {
150
151
152         /* Scan bitmap for enough consecutive space */
153         {
154             // num_blocks: The number of blocks we need to find
155             // bitmap: bitmap of blocks (1 == allocatable)
156             // bitmap_entries: number of blocks in the system/number of bits in bitmap
157             // reg_start: The block index where our allocation will start
158             
159             int i = 0;
160             int run_len = 0;
161             
162             for (i = 0; i < bitmap_entries; i++) {
163                 int i_major = i / 8;
164                 int i_minor = i % 8;
165                 
166                 
167                 if (!(bitmap[i_major] & (0x1 << i_minor))) {
168                     reg_start = i + 1; // skip the region start to next entry
169                     run_len = 0;
170                     continue;
171                 }
172                 
173                 run_len++;
174
175                 if (run_len >= num_blocks) {
176                     break;
177                 }
178             }
179
180         
181             if (run_len < num_blocks) {
182                 fprintf(stderr, "Could not find enough consecutive memory blocks... (found %d)\n", run_len);
183                 return -1;
184             }
185         }
186     
187
188         /* Offline memory blocks starting at reg_start */
189         {
190             int i = 0;
191
192             for (i = 0; i < num_blocks; i++) {  
193                 FILE * block_file = NULL;
194                 char fname[256];
195
196                 memset(fname, 0, 256);
197
198                 snprintf(fname, 256, "%smemory%d/state", SYS_PATH, i + reg_start);
199             
200                 block_file = fopen(fname, "r+");
201
202                 if (block_file == NULL) {
203                     perror("Could not open block file");
204                     return -1;
205                 }
206
207
208                 printf("Offlining block %d (%s)\n", i + reg_start, fname);
209                 fprintf(block_file, "offline\n");
210
211                 fclose(block_file);
212             }
213         }
214
215
216         /*  We asked to offline set of blocks, but Linux could have lied. 
217          *  To be safe, check whether blocks were offlined and start again if not 
218          */
219
220         {
221             int i = 0;
222
223             mem_ready = 1; // Hopefully we are ok...
224
225
226             for (i = 0; i < num_blocks; i++) {
227                 int block_fd = NULL;
228                 char fname[BUF_SIZE];
229                 char status_buf[BUF_SIZE];
230
231
232                 memset(fname, 0, BUF_SIZE);
233                 memset(status_buf, 0, BUF_SIZE);
234
235                 snprintf(fname, BUF_SIZE, "%smemory%d/state", SYS_PATH, i + reg_start);
236
237         
238                 block_fd = open(fname, O_RDONLY);
239                 
240                 if (block_fd == -1) {
241                     perror("Could not open block file");
242                     return -1;
243                 }
244                     
245                 if (read(block_fd, status_buf, BUF_SIZE) <= 0) {
246                     perror("Could not read block status");
247                     return -1;
248                 }
249
250                 printf("Checking offlined block %d (%s)...", i + reg_start, fname);
251
252                 int ret = strncmp(status_buf, "offline", strlen("offline"));
253
254                 if (ret != 0) {
255                     int j = 0;
256                     int major = (i + reg_start) / 8;
257                     int minor = (i + reg_start) % 8;
258
259                     bitmap[major] &= ~(0x1 << minor); // mark the block as not removable in bitmap
260
261                     mem_ready = 0; // Keep searching
262
263                     printf("ERROR (%d)\n", ret);
264
265                     for (j = 0; j < i; j++) {
266                         FILE * block_file = NULL;
267                         char fname[256];
268                         
269                         memset(fname, 0, 256);
270                         
271                         snprintf(fname, 256, "%smemory%d/state", SYS_PATH, j + reg_start);
272                         
273                         block_file = fopen(fname, "r+");
274                         
275                         if (block_file == NULL) {
276                             perror("Could not open block file");
277                             return -1;
278                         }
279
280                         fprintf(block_file, "online\n");
281                         
282                         fclose(block_file);
283                     }
284                        
285
286                     break;
287                 } 
288                 
289                 printf("OK\n");
290                 
291             }
292             
293             
294         }
295     }
296
297     free(bitmap);
298
299     /* Memory is offlined. Calculate size and phys start addr to send to Palacios */
300
301     {
302         int v3_fd = 0;
303         struct v3_mem_region mem;
304         unsigned long long num_bytes = num_blocks * block_size_bytes;
305         unsigned long long base_addr = reg_start * block_size_bytes;
306
307         printf("Giving Palacios %dMB of memory at (%p) \n", 
308                num_bytes / (1024 * 1024), base_addr);
309
310         mem.base_addr = base_addr;
311         mem.num_pages = num_bytes / 4096;
312
313         v3_fd = open(v3_dev, O_RDONLY);
314
315         if (v3_fd == -1) {
316             printf("Error opening V3Vee control device\n");
317             return -1;
318         }
319
320         ioctl(v3_fd, V3_ADD_MEMORY, &mem); 
321
322         /* Close the file descriptor.  */ 
323         close(v3_fd);   
324     }
325
326     return 0; 
327