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_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 #include <alloca.h> 
17
18 #include "v3_ctrl.h"
19
20
21 #define SYS_PATH "/sys/devices/system/memory/"
22
23 #define BUF_SIZE 128
24
25 int verbose=0;
26
27 char offname[256];
28 FILE *off;
29
30 int num_offline;
31 unsigned long long *start_offline;
32 unsigned long long *len_offline;
33
34 unsigned long long kernel_max_order;
35 unsigned long long kernel_max_page_alloc_bytes;
36 unsigned long long kernel_num_nodes;
37 unsigned long long kernel_num_cpus;
38 unsigned long long palacios_compiled_mem_block_size;
39 unsigned long long palacios_runtime_mem_block_size;
40
41
42 #define VPRINTF(...) do { if (verbose) { printf(__VA_ARGS__); } } while (0)
43 #define EPRINTF(...) do { fprintf(stderr,__VA_ARGS__); } while (0)
44
45
46 static int read_offlined();
47 static int write_offlined();
48 static int find_offlined(unsigned long long base_addr);
49 static int clear_offlined();
50
51
52 static int offline_memory(unsigned long long mem_size_bytes,
53                           unsigned long long mem_min_start,
54                           int limit32, 
55                           int node,
56                           unsigned long long *num_bytes, 
57                           unsigned long long *base_addr);
58
59 static int online_memory(unsigned long long num_bytes, 
60                          unsigned long long base_addr);
61
62
63 static int get_kernel_setup();
64
65
66
67 int main(int argc, char * argv[]) {
68     unsigned long long mem_size_bytes = 0;
69     unsigned long long mem_min_start = 0;
70     int v3_fd = -1;
71     int request = 0;
72     int limit32 = 0;
73     int help=0;
74     int alloffline=0;
75     enum {NONE, ADD, REMOVE} op;
76     int node = -1;
77     int c;
78     unsigned long long num_bytes, base_addr;
79     struct v3_mem_region mem;
80
81     while ((c=getopt(argc,argv,"hvarklm:n:"))!=-1) {
82         switch (c) {
83             case 'h':
84                 help=1;
85                 break;
86             case 'v':
87                 verbose=1;
88                 break;
89             case 'a':
90                 op=ADD;
91                 break;
92             case 'r':
93                 op=REMOVE;
94                 break;
95             case 'k':
96                 request=1;
97                 break;
98             case 'l':
99                 limit32=1;
100                 break;
101             case 'm':
102                 mem_min_start = atoll(optarg) * (1024*1024);
103                 break;
104             case 'n':
105                 node = atoi(optarg);
106                 break;
107             case '?':
108                 if (optopt=='n') { 
109                     EPRINTF("-n requires the numa node...\n");
110             return -1;
111                 } else if (optopt=='m') { 
112                     EPRINTF("-m requires the minimum starting address (in MB)...\n");
113             return -1;
114                 } else {
115                     EPRINTF("Unknown option %c\n",optopt);
116             return -1;
117                 }
118                 break;
119             default:
120                 EPRINTF("Unknown option %c\n",optopt);
121                 break;
122         }
123     }
124
125
126     if (op==NONE || optind==argc || help) {
127         EPRINTF("usage: v3_mem [-h] [-v] [ [-k] [-l] [-n k] [-m n] -a <memory size (MB)>] | [-r <hexaddr> | offline]\n\n"
128                "Palacios Memory Management\n\nMemory Addition\n"
129                " -a <mem>      Allocate memory for use by Palacios (MB).\n\n"
130                " With    -k    this requests in-kernel allocation\n"
131                " Without -k    this attempts to offline memory via hot remove\n\n"
132                " With    -l    the request or offlining is limited to first 4 GB\n"
133                " Without -l    the request or offlining has no limits\n\n"
134                " With    -m n  the search for offlineable memory starts at n MB\n"
135                " Without -m n  the search for offlineable memory starts at 0 MB\n\n"
136                " With    -n i  the request is for numa node i\n"
137                " Without -n i  the request can be satified on any numa node\n\n"
138                "Memory Removal\n"
139                " -r <hexaddr>  Free Palacios memory containing hexaddr, online it if needed\n"
140                " -r offline    Free all offline Palacios memory and online it\n\n"
141                "Shared Options\n"
142                " -v            Verbose\n"
143                " -h            Help\n"
144                );
145         
146         return -1;
147     }
148
149
150     if (get_kernel_setup()) { 
151         EPRINTF("Cannot read kernel setup\n");
152         return -1;
153     }
154
155     if (op==ADD) {
156         mem_size_bytes = atoll(argv[optind]) * (1024 * 1024);
157
158         if (mem_size_bytes > palacios_runtime_mem_block_size) { 
159             EPRINTF("Trying to add a larger single chunk of memory than Palacios can manage\n"
160                    "Your request:                        %llu bytes\n"
161                    "Palacios run-time memory block size: %llu bytes\n",
162                    mem_size_bytes, palacios_runtime_mem_block_size);
163             return -1;
164         }
165
166         if (mem_size_bytes < palacios_runtime_mem_block_size) { 
167             EPRINTF("Trying to add a smaller single chunk of memory than Palacios can manage\n"
168                    "Your request:                        %llu bytes\n"
169                    "Palacios run-time memory block size: %llu bytes\n",
170                    mem_size_bytes, palacios_runtime_mem_block_size);
171             return -1;
172         }
173         
174         if (request && mem_size_bytes > kernel_max_page_alloc_bytes) { 
175             EPRINTF("Trying to request a larger single chunk of memory than the kernel can allocate\n"
176                    "Your request:                        %llu bytes\n"
177                    "Kernel largest page allocation:      %llu bytes\n"
178                    "Kernel MAX_ORDER:                    %llu\n",
179                    mem_size_bytes, kernel_max_page_alloc_bytes, kernel_max_order);
180             return -1;
181         }
182
183         if (node>=0 && node>=kernel_num_nodes) { 
184             EPRINTF("Trying to request or allocate memory for a nonexistent node\n"
185                    "Your request:                        node %d\n"
186                    "Kernel number of nodes:              %llu\n",
187                    node, kernel_num_nodes);
188         }
189             
190
191     } else if (op==REMOVE) { 
192         if (!strcasecmp(argv[optind],"offline")) {
193             alloffline=1;
194         } else {
195             base_addr=strtoll(argv[optind],NULL,16);
196         }
197     }
198     
199     if (!getenv("PALACIOS_DIR")) { 
200         EPRINTF("Please set the PALACIOS_DIR variable\n");
201         return -1;
202     }
203
204     strcpy(offname,getenv("PALACIOS_DIR"));
205     strcat(offname,"/.v3offlinedmem");
206
207     if (!(off=fopen(offname,"a+"))) { 
208         EPRINTF("Cannot open or create offline memory file %s",offname);
209         return -1;
210     }
211
212     // removing all offlined memory we added is a special case
213     if (op==REMOVE && alloffline) {
214         int i;
215         int rc=0;
216
217         // we just need to reinvoke ourselves
218         read_offlined();
219         for (i=0;i<num_offline;i++) {
220             char cmd[256];
221             sprintf(cmd,"v3_mem -r %llx", start_offline[i]);
222             rc|=system(cmd);
223         }
224         clear_offlined();
225         return rc;
226     }
227
228         
229     v3_fd = open(v3_dev, O_RDONLY);
230     
231     if (v3_fd == -1) {
232         EPRINTF("Error opening V3Vee control device\n");
233         fclose(off);
234         return -1;
235     }
236
237
238     if (op==ADD) { 
239                    
240         if (!request) { 
241             VPRINTF("Trying to offline memory (size=%llu, min_start=%llu, limit32=%d)\n",mem_size_bytes,mem_min_start,limit32);
242             if (offline_memory(mem_size_bytes,mem_min_start,limit32,node,&num_bytes, &base_addr)) { 
243                 EPRINTF("Could not offline memory\n");
244                 fclose(off);
245                 close(v3_fd);
246                 return -1;
247             }
248             
249             fprintf(off,"%llx\t%llx\n",base_addr, num_bytes);
250             
251             printf("Memory of size %llu at 0x%llx has been offlined\n",num_bytes,base_addr);
252
253             mem.type=PREALLOCATED;
254             mem.node=node;
255             mem.base_addr=base_addr;
256             mem.num_pages=num_bytes/4096;
257
258             
259         } else {
260             VPRINTF("Generating memory allocation request (size=%llu, limit32=%d)\n", mem_size_bytes, limit32);
261             mem.type = limit32 ? REQUESTED32 : REQUESTED;
262             mem.node = node;
263             mem.base_addr = 0;
264             mem.num_pages = mem_size_bytes / 4096;
265         }
266         
267         VPRINTF("Allocation request is: type=%d, node=%d, base_addr=0x%llx, num_pages=%llu\n",
268                mem.type, mem.node, mem.base_addr, mem.num_pages);
269         
270         if (ioctl(v3_fd, V3_ADD_MEMORY, &mem)<0) { 
271             EPRINTF("Request rejected by Palacios\n");
272             printf("Allocation of memory by Palacios has failed.  Check dmesg output for more information.\n");
273             close(v3_fd);
274             fclose(off);
275             return -1;
276         } else {
277             VPRINTF("Request accepted by Palacios\n");
278             printf("%llu bytes of memory has been allocated by Palacios\n",mem.num_pages*4096);
279             close(v3_fd);       
280             fclose(off);
281             return 0;
282         }
283         
284     } else if (op==REMOVE) { 
285         int entry;
286
287         read_offlined();
288
289         entry=find_offlined(base_addr);
290         
291         if (entry<0) { 
292             // no need to offline
293             mem.type=REQUESTED;
294         } else {
295             mem.type=PREALLOCATED;
296         }
297         
298         mem.base_addr=base_addr;
299
300         // now remove it from palacios
301         VPRINTF("Deallocation request is: type=%d, base_addr=0x%llx\n",
302                mem.type, mem.base_addr);
303         
304         if (ioctl(v3_fd, V3_REMOVE_MEMORY, &mem)<0) { 
305             EPRINTF("Request rejected by Palacios\n");
306             close(v3_fd);
307             fclose(off);
308             return -1;
309         } 
310
311         VPRINTF("Request accepted by Palacios\n");
312
313         printf("Memory at 0x%llx has been deallocated by Palacios\n", mem.base_addr);
314
315         if (entry>=0) { 
316             VPRINTF("Onlining the memory to make it available to the kernel\n");
317             online_memory(start_offline[entry],len_offline[entry]);
318         
319             len_offline[entry] = 0;
320
321             write_offlined();
322
323             printf("Memory at 0x%llx has been onlined\n",mem.base_addr);
324             
325         } else {
326             VPRINTF("Memory was deallocated in the kernel\n");
327             printf("Memory at 0x%llx has been onlined\n",mem.base_addr);
328         }
329
330         clear_offlined();
331         close(v3_fd);
332         fclose(off);
333
334         return 0;
335     }
336
337
338
339
340 static int dir_filter(const struct dirent * dir) {
341     if (strncmp("memory", dir->d_name, 6) == 0) {
342         return 1;
343     }
344
345     return 0;
346 }
347
348
349 static int dir_cmp(const struct dirent **dir1, const struct dirent ** dir2) {
350     int num1 = atoi((*dir1)->d_name + 6);
351     int num2 = atoi((*dir2)->d_name + 6);
352     
353     return num1 - num2;
354 }
355
356
357
358 #define UNWIND(first,last)                                      \
359 do {                                                            \
360     int i;                                                      \
361     for (i = first; i <= last; i++) {                           \
362         FILE *f;                                                \
363         char name[256];                                         \
364         snprintf(name,256,"%smemory%d/state",SYS_PATH,i);       \
365         f=fopen(name,"r+");                                     \
366         if (!f) {                                               \
367             perror("Cannot open state file\n");                 \
368             return -1;                                          \
369         }                                                       \
370         VPRINTF("Re-onlining block %d (%s)\n",i,name);          \
371         fprintf(f,"online\n");                                  \
372         fclose(f);                                              \
373     }                                                           \
374 } while (0)
375
376
377 static int offline_memory(unsigned long long mem_size_bytes,
378                           unsigned long long mem_min_start,
379                           int limit32, 
380                           int node,
381                           unsigned long long *num_bytes, 
382                           unsigned long long *base_addr)
383 {
384
385     unsigned int block_size_bytes = 0;
386     int bitmap_entries = 0;
387     unsigned char * bitmap = NULL;
388     int num_blocks = 0;    
389     int reg_start = 0;
390     int mem_ready = 0;
391     
392     
393
394     VPRINTF("Trying to find %dMB (%d bytes) of memory above %llu with limit32=%d\n", mem_size_bytes/(1024*1024), mem_size_bytes, mem_min_start, limit32);
395         
396     /* Figure out the block size */
397     {
398         int tmp_fd = 0;
399         char tmp_buf[BUF_SIZE];
400         
401         tmp_fd = open(SYS_PATH "block_size_bytes", O_RDONLY);
402         
403         if (tmp_fd == -1) {
404             perror("Could not open block size file: " SYS_PATH "block_size_bytes");
405             return -1;
406         }
407     
408         if (read(tmp_fd, tmp_buf, BUF_SIZE) <= 0) {
409             perror("Could not read block size file: " SYS_PATH "block_size_bytes");
410             return -1;
411         }
412         
413         close(tmp_fd);
414         
415         block_size_bytes = strtoll(tmp_buf, NULL, 16);
416         
417         VPRINTF("Memory block size is %dMB (%d bytes)\n", block_size_bytes / (1024 * 1024), block_size_bytes);
418         
419     }
420     
421     
422     num_blocks =  mem_size_bytes / block_size_bytes;
423     if (mem_size_bytes % block_size_bytes) num_blocks++;
424     
425     mem_min_start = block_size_bytes * 
426         ((mem_min_start / block_size_bytes) + (!!(mem_min_start % block_size_bytes)));
427     
428     VPRINTF("Looking for %d blocks of memory starting at %p (block %llu) with limit32=%d for node %d\n", num_blocks, (void*)mem_min_start, mem_min_start/block_size_bytes,limit32,node);
429         
430     
431     // We now need to find <num_blocks> consecutive offlinable memory blocks
432     
433     /* Scan the memory directories */
434     {
435         struct dirent ** namelist = NULL;
436         int size = 0;
437         int i = 0;
438         int j = 0;
439         int last_block = 0;
440         int first_block = mem_min_start/block_size_bytes;
441         int limit_block = 0xffffffff / block_size_bytes; // for 32 bit limiting
442         
443         last_block = scandir(SYS_PATH, &namelist, dir_filter, dir_cmp);
444         bitmap_entries = atoi(namelist[last_block - 1]->d_name + 6) + 1;
445             
446         size = bitmap_entries / 8;
447         if (bitmap_entries % 8) size++;
448             
449         bitmap = alloca(size);
450
451         if (!bitmap) {
452             VPRINTF("ERROR: could not allocate space for bitmap\n");
453             return -1;
454         }
455         
456         memset(bitmap, 0, size);
457         
458         for (i = 0 ; j < bitmap_entries - 1; i++) {
459             struct dirent * tmp_dir = namelist[i];
460             int block_fd = 0;       
461             char status_str[BUF_SIZE];
462             char fname[BUF_SIZE];
463             char nname[BUF_SIZE];
464             struct stat s;
465                 
466             memset(status_str, 0, BUF_SIZE);
467
468             memset(fname, 0, BUF_SIZE);
469             snprintf(fname, BUF_SIZE, "%s%s/removable", SYS_PATH, tmp_dir->d_name);
470
471             memset(nname, 0, BUF_SIZE);
472             snprintf(nname, BUF_SIZE, "%s%s/node%d", SYS_PATH, tmp_dir->d_name,node);
473                 
474             j = atoi(tmp_dir->d_name + 6);
475             int major = j / 8;
476             int minor = j % 8;
477                 
478                 
479             if (i<first_block) { 
480                 VPRINTF("Skipping %s due to minimum start constraint\n",fname);
481                 continue;
482             } 
483
484             if (limit32 && i>limit_block) { 
485                 VPRINTF("Skipping %s due to 32 bit constraint\n",fname);
486                 continue;
487             } 
488                 
489             // The prospective block must be (a) removable, and (b) currently online
490             // and for the needed node
491                 
492             VPRINTF("Checking %s...", fname);
493                 
494             if (node>=0) { 
495                 if (stat(nname,&s)) { 
496                     VPRINTF("Skipping %s due to it being in the wrong node\n", fname);
497                     continue;
498                 }
499             }
500
501
502             block_fd = open(fname, O_RDONLY);
503                 
504             if (block_fd == -1) {
505                 EPRINTF("Hotpluggable memory not supported or could not determine if block is removable...\n");
506                 return -1;
507             }
508                 
509             if (read(block_fd, status_str, BUF_SIZE) <= 0) {
510                 perror("Could not read block removability information\n");
511                 return -1;
512             }
513             
514             status_str[BUF_SIZE-1]=0;
515                 
516             close(block_fd);
517                 
518             if (atoi(status_str) == 1) {
519                 VPRINTF("Removable ");
520             } else {
521                 VPRINTF("Not removable\n");
522                 continue;
523             }
524             
525             snprintf(fname, BUF_SIZE, "%s%s/state", SYS_PATH, tmp_dir->d_name);
526             
527             block_fd = open(fname, O_RDONLY);
528             
529             if (block_fd<0) { 
530                 perror("Could not open block state\n");
531                 return -1;
532             }
533
534             if (read(block_fd, status_str, BUF_SIZE) <=0) { 
535                 perror("Could not read block state information\n");
536                 return -1;
537             }
538
539             status_str[BUF_SIZE-1]=0;
540
541             close(block_fd);
542
543             if (!strncasecmp(status_str,"offline",7)) {
544                 VPRINTF("and Already Offline (unusable)\n");
545             } else if (!strncasecmp(status_str,"online",6)) { 
546                 VPRINTF("and Online (usable)\n");
547                 bitmap[major] |= (0x1 << minor);
548             } else {
549                 VPRINTF("and in Unknown State '%s' (unusable)\n",status_str);
550             }
551             
552         }
553         
554     }
555     
556     while (!mem_ready) {
557
558         /* Scan bitmap for enough consecutive space */
559         {
560             // num_blocks: The number of blocks we need to find
561             // bitmap: bitmap of blocks (1 == allocatable)
562             // bitmap_entries: number of blocks in the system/number of bits in bitmap
563             // reg_start: The block index where our allocation will start
564                 
565             int i = 0;
566             int run_len = 0;
567             
568             for (i = 0; i < bitmap_entries; i++) {
569                 int i_major = i / 8;
570                 int i_minor = i % 8;
571                 
572                 if (!(bitmap[i_major] & (0x1 << i_minor))) {
573                     reg_start = i + 1; // skip the region start to next entry
574                     run_len = 0;
575                     continue;
576                 }
577                 
578                 run_len++;
579                     
580                 if (run_len >= num_blocks) {
581                     break;
582                 }
583             }
584             
585             
586             if (run_len < num_blocks) {
587                 EPRINTF("Could not find enough consecutive memory blocks... (found %d)\n", run_len);
588                 // no offlining yet, so no need to unwind here
589                 return -1;
590             }
591         }
592         
593         
594         /* Offline memory blocks starting at reg_start */
595         {
596             int i = 0;
597             
598             for (i = 0; i < num_blocks; i++) {  
599                 FILE * block_file = NULL;
600                 char fname[256];
601                 
602                 memset(fname, 0, 256);
603                 
604                 snprintf(fname, 256, "%smemory%d/state", SYS_PATH, i + reg_start);
605                 
606                 block_file = fopen(fname, "r+");
607                 
608                 if (block_file == NULL) {
609                     perror("Could not open block file");
610                     UNWIND(reg_start, i+reg_start-1);
611                     return -1;
612                 }
613                 
614                     
615                 VPRINTF("Offlining block %d (%s)\n", i + reg_start, fname);
616                 fprintf(block_file, "offline\n");
617                 
618                 fclose(block_file);
619                 
620             }
621         }
622         
623         
624         /*  We asked to offline set of blocks, but Linux could have lied. 
625          *  To be safe, check whether blocks were offlined and start again if not 
626          */
627         
628         {
629             int i = 0;
630             
631             mem_ready = 1; // Hopefully we are ok...
632             
633             
634             for (i = 0; i < num_blocks; i++) {
635                 int block_fd = 0;
636                 char fname[BUF_SIZE];
637                 char status_buf[BUF_SIZE];
638                 
639                 
640                 memset(fname, 0, BUF_SIZE);
641                 memset(status_buf, 0, BUF_SIZE);
642                 
643                 snprintf(fname, BUF_SIZE, "%smemory%d/state", SYS_PATH, i + reg_start);
644                 
645                 
646                 block_fd = open(fname, O_RDONLY);
647                 
648                 if (block_fd == -1) {
649                     perror("Could not open block state file");
650                     return -1;
651                 }
652                 
653                 if (read(block_fd, status_buf, BUF_SIZE) <= 0) {
654                     perror("Could not read block state");
655                     return -1;
656                 }
657
658                 status_buf[BUF_SIZE-1]=0;
659                 
660                 VPRINTF("Checking offlined block %d (%s)...", i + reg_start, fname);
661                 
662                 int ret = strncmp(status_buf, "offline", strlen("offline"));
663                 
664                 if (ret != 0) {  // uh oh
665                     int j = 0;
666                     int major = (i + reg_start) / 8;
667                     int minor = (i + reg_start) % 8;
668             char * pos;
669
670                     bitmap[major] &= ~(0x1 << minor); // mark the block as not removable in bitmap
671                     
672                     mem_ready = 0; // Keep searching
673                     
674             // remove trailing newline
675             if ((pos=strchr(status_buf, '\n')) != NULL) {
676                 *pos = '\0';
677             }
678
679                     EPRINTF("ERROR - block status is '%s'\n", status_buf);
680
681                     // Unwind space
682                     UNWIND(reg_start,reg_start+num_blocks-1);
683                     
684                     break;
685                 } 
686             }
687             
688             VPRINTF("Offlined Memory OK\n");
689                 
690         }
691     }
692     
693     /* Memory is offlined. Calculate size and phys start addr to send to Palacios */
694     *num_bytes = (unsigned long long)(num_blocks) * (unsigned long long)(block_size_bytes);
695     *base_addr = (unsigned long long)(reg_start) * (unsigned long long)(block_size_bytes);
696     
697     return 0;
698 }
699
700
701 static int online_memory(unsigned long long base_addr,
702                          unsigned long long num_bytes)
703 {
704     
705     unsigned int block_size_bytes = 0;
706     int bitmap_entries = 0;
707     unsigned char * bitmap = NULL;
708     int num_blocks = 0;    
709     int reg_start = 0;
710     int mem_ready = 0;
711     
712     
713
714     VPRINTF("Trying to online memory from %llu to %llu\n",base_addr,base_addr+num_bytes-1);
715         
716     /* Figure out the block size */
717     {
718         int tmp_fd = 0;
719         char tmp_buf[BUF_SIZE];
720         
721         tmp_fd = open(SYS_PATH "block_size_bytes", O_RDONLY);
722         
723         if (tmp_fd == -1) {
724             perror("Could not open block size file: " SYS_PATH "block_size_bytes");
725             return -1;
726         }
727     
728         if (read(tmp_fd, tmp_buf, BUF_SIZE) <= 0) {
729             perror("Could not read block size file: " SYS_PATH "block_size_bytes");
730             return -1;
731         }
732         
733         close(tmp_fd);
734         
735         block_size_bytes = strtoll(tmp_buf, NULL, 16);
736         
737         VPRINTF("Memory block size is %dMB (%d bytes)\n", block_size_bytes / (1024 * 1024), block_size_bytes);
738         
739     }
740     
741     num_blocks =  num_bytes / block_size_bytes;
742     if (num_bytes % block_size_bytes) num_blocks++;
743
744     reg_start = base_addr / block_size_bytes;
745
746     VPRINTF("That is %lu blocks of size %llu starting at block %d\n", num_blocks, block_size_bytes, reg_start);
747    
748     
749         
750     /* Online memory blocks starting at reg_start */
751     {
752         int i = 0;
753             
754         for (i = 0; i < num_blocks; i++) {      
755             FILE * block_file = NULL;
756             char fname[256];
757                 
758             memset(fname, 0, 256);
759             
760             snprintf(fname, 256, "%smemory%d/state", SYS_PATH, i + reg_start);
761             
762             block_file = fopen(fname, "r+");
763             
764             if (block_file == NULL) {
765                 perror("Could not open block file");
766                 return -1;
767             }
768                 
769             
770             VPRINTF("Onlining block %d (%s)\n", i + reg_start, fname);
771             fprintf(block_file, "online\n");
772             
773             fclose(block_file);
774             
775         }
776     }
777     
778     return 0;
779     
780 }
781
782
783
784 static int read_offlined()
785 {
786     rewind(off);
787     unsigned long long base, len;
788     int i;
789     
790     num_offline=0;
791     while (fscanf(off,"%llx\t%llx\n",&base,&len)==2) { num_offline++; }
792
793
794     start_offline=(unsigned long long *)calloc(num_offline, sizeof(unsigned long long));
795     len_offline=(unsigned long long *)calloc(num_offline, sizeof(unsigned long long));
796
797     if (!start_offline || !len_offline) { 
798         EPRINTF("Cannot allocate space to load offline map\n");
799         return -1;
800     }
801
802     rewind(off);
803     for (i=0;i<num_offline;i++) { 
804         fscanf(off,"%llx\t%llx",&(start_offline[i]),&(len_offline[i]));
805     }
806     // we are now back to the end, and can keep appending
807     return 0;
808 }
809
810
811 static int write_offlined()
812 {
813     int i;
814
815     fclose(off);
816     if (!(off=fopen(offname,"w+"))) {  // truncate
817         EPRINTF("Cannot open %s for writing!\n",offname);
818         return -1;
819     }
820
821     for (i=0;i<num_offline;i++) { 
822         if (len_offline[i]) { 
823             fprintf(off,"%llx\t%llx\n",start_offline[i],len_offline[i]);
824         }
825     }
826     // we are now back to the end, and can keep appending
827     return 0;
828 }
829
830
831 static int clear_offlined()
832 {
833     free(start_offline);
834     free(len_offline);
835     return 0;
836 }
837
838 static int find_offlined(unsigned long long base_addr)
839 {
840     int i;
841
842     for (i=0;i<num_offline;i++) { 
843         if (base_addr>=start_offline[i] &&
844             base_addr<(start_offline[i]+len_offline[i])) { 
845             return i;
846         }
847     }
848
849     return -1;
850
851 }
852
853
854
855 static int get_kernel_setup()
856 {
857     FILE *f;
858     
859     f = fopen("/proc/v3vee/v3-info", "r");
860     
861     if (!f) { 
862         EPRINTF("Cannot open /proc/v3vee/v3-info\n");
863         return -1;
864     }
865
866     if (fscanf(f,"kernel MAX_ORDER:\t%llu\n",&kernel_max_order)!=1) { 
867         EPRINTF("Cannot read kernel MAX_ORDER\n");
868         return -1;
869     }
870
871     kernel_max_page_alloc_bytes =  4096ULL * (0x1ULL << kernel_max_order);
872
873     if (fscanf(f,"number of nodes:\t%llu\n",&kernel_num_nodes)!=1) { 
874         EPRINTF("Cannot read kernel number of numa nodes\n");
875         return -1;
876     }
877
878     if (fscanf(f,"number of cpus:\t%llu\n",&kernel_num_cpus)!=1) { 
879         EPRINTF("Cannot read kernel number of cpus\n");
880         return -1;
881     }
882
883     if (fscanf(f,"palacios compiled mem_block_size:\t%llu\n",&palacios_compiled_mem_block_size)!=1) { 
884         EPRINTF("Cannot read palacios compiled mem_block_size\n");
885         return -1;
886     }
887
888     if (fscanf(f,"palacios run-time mem_block_size:\t%llu\n",&palacios_runtime_mem_block_size)!=1) { 
889         EPRINTF("Cannot read palacios run-time mem_block_size\n");
890         return -1;
891     }
892
893     return 0;
894 }
895
896