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.


Modified v3_mem to automatically scan for contiguous memory blocks.
[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
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
150     /* Scan bitmap for enough consecutive space */
151     {
152         // num_blocks: The number of blocks we need to find
153         // bitmap: bitmap of blocks (1 == allocatable)
154         // bitmap_entries: number of blocks in the system/number of bits in bitmap
155         // reg_start: The block index where our allocation will start
156
157         int i = 0;
158         int run_len = 0;
159
160         for (i = 0; i < bitmap_entries; i++) {
161             int i_major = i / 8;
162             int i_minor = i % 8;
163
164
165             if (!(bitmap[i_major] & (0x1 << i_minor))) {
166                 reg_start = i + 1; // skip the region start to next entry
167                 run_len = 0;
168                 continue;
169             }
170
171             run_len++;
172
173             if (run_len >= num_blocks) {
174                 break;
175             }
176         }
177
178         free(bitmap);
179         
180         if (run_len < num_blocks) {
181             fprintf(stderr, "Could not find enough consecutive memory blocks... (found %d)\n", run_len);
182             return -1;
183         }
184     }
185     
186
187     /* Offline memory blocks starting at reg_start */
188     {
189         int i = 0;
190
191         for (i = 0; i < num_blocks; i++) {      
192             FILE * block_file = NULL;
193             char fname[256];
194
195             memset(fname, 0, 256);
196
197             snprintf(fname, 256, "%smemory%d/state", SYS_PATH, i + reg_start);
198             
199             block_file = fopen(fname, "r+");
200
201             if (block_file == NULL) {
202                 perror("Could not open block file");
203                 return -1;
204             }
205
206
207             printf("Offlining block %d (%s)\n", i + reg_start, fname);
208             fprintf(block_file, "offline\n");
209
210             fclose(block_file);
211         }
212     }
213
214
215     /* Memory is offlined. Calculate size and phys start addr to send to Palacios */
216
217     {
218         int v3_fd = 0;
219         struct v3_mem_region mem;
220         unsigned long long num_bytes = num_blocks * block_size_bytes;
221         unsigned long long base_addr = reg_start * block_size_bytes;
222
223         printf("Giving Palacios %dMB of memory at (%p) \n", 
224                num_bytes / (1024 * 1024), base_addr);
225
226         mem.base_addr = base_addr;
227         mem.num_pages = num_bytes / 4096;
228
229         v3_fd = open(v3_dev, O_RDONLY);
230
231         if (v3_fd == -1) {
232             printf("Error opening V3Vee control device\n");
233             return -1;
234         }
235
236         ioctl(v3_fd, V3_ADD_MEMORY, &mem); 
237
238         /* Close the file descriptor.  */ 
239         close(v3_fd);   
240     }
241
242     return 0; 
243