10 #include <sys/ioctl.h>
12 #include <sys/types.h>
19 #define SYS_PATH "/sys/devices/system/memory/"
23 int dir_filter(const struct dirent * dir) {
24 if (strncmp("memory", dir->d_name, 6) == 0) {
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);
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;
54 printf("Usage: v3_mem <memory size (MB)>\n");
59 mem_size_bytes = atoll(argv[1]) * (1024 * 1024);
61 printf("Trying to find %dMB (%d bytes) of memory\n", atoll(argv[1]), mem_size_bytes);
63 /* Figure out the block size */
66 char tmp_buf[BUF_SIZE];
68 tmp_fd = open(SYS_PATH "block_size_bytes", O_RDONLY);
71 perror("Could not open block size file: " SYS_PATH "block_size_bytes");
75 if (read(tmp_fd, tmp_buf, BUF_SIZE) <= 0) {
76 perror("Could not read block size file: " SYS_PATH "block_size_bytes");
82 block_size_bytes = strtoll(tmp_buf, NULL, 16);
84 printf("Memory block size is %dMB (%d bytes)\n", block_size_bytes / (1024 * 1024), block_size_bytes);
88 num_blocks = mem_size_bytes / block_size_bytes;
89 if (block_size_bytes % mem_size_bytes) num_blocks++;
91 printf("Looking for %d blocks of memory\n", num_blocks);
94 // We now need to find <num_blocks> consecutive offlinable memory blocks
96 /* Scan the memory directories */
98 struct dirent ** namelist = NULL;
102 bitmap_entries = scandir(SYS_PATH, &namelist, dir_filter, dir_cmp);
104 size = bitmap_entries / 8;
105 if (bitmap_entries % 8) size++;
107 bitmap = malloc(size);
108 memset(bitmap, 0, size);
110 for (i = 0; i < bitmap_entries; i++) {
111 struct dirent * tmp_dir = namelist[i];
115 char status_str[BUF_SIZE];
116 char fname[BUF_SIZE];
118 memset(status_str, 0, BUF_SIZE);
119 memset(fname, 0, BUF_SIZE);
121 snprintf(fname, BUF_SIZE, "%s%s/removable", SYS_PATH, tmp_dir->d_name);
123 printf("Checking %s...", fname);
125 block_fd = open(fname, O_RDONLY);
127 if (block_fd == -1) {
128 printf("Hotpluggable memory not supported...\n");
132 if (read(block_fd, status_str, BUF_SIZE) <= 0) {
133 perror("Could not read block status");
139 if (atoi(status_str) == 1) {
140 printf("Removable\n");
141 bitmap[major] |= (0x1 << minor);
143 printf("Not removable\n");
150 /* Scan bitmap for enough consecutive space */
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
160 for (i = 0; i < bitmap_entries; i++) {
165 if (!(bitmap[i_major] & (0x1 << i_minor))) {
166 reg_start = i + 1; // skip the region start to next entry
173 if (run_len >= num_blocks) {
180 if (run_len < num_blocks) {
181 fprintf(stderr, "Could not find enough consecutive memory blocks... (found %d)\n", run_len);
187 /* Offline memory blocks starting at reg_start */
191 for (i = 0; i < num_blocks; i++) {
192 FILE * block_file = NULL;
195 memset(fname, 0, 256);
197 snprintf(fname, 256, "%smemory%d/state", SYS_PATH, i + reg_start);
199 block_file = fopen(fname, "r+");
201 if (block_file == NULL) {
202 perror("Could not open block file");
207 printf("Offlining block %d (%s)\n", i + reg_start, fname);
208 fprintf(block_file, "offline\n");
215 /* Memory is offlined. Calculate size and phys start addr to send to Palacios */
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;
223 printf("Giving Palacios %dMB of memory at (%p) \n",
224 num_bytes / (1024 * 1024), base_addr);
226 mem.base_addr = base_addr;
227 mem.num_pages = num_bytes / 4096;
229 v3_fd = open(v3_dev, O_RDONLY);
232 printf("Error opening V3Vee control device\n");
236 ioctl(v3_fd, V3_ADD_MEMORY, &mem);
238 /* Close the file descriptor. */