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.


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