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.


VGA bug fix
[palacios.git] / nautilus / palacios-nautilus-mm.c
1 #include "palacios-nautilus-mm.h"
2 #include "palacios-nautilus-mm-test.h"
3
4 /*
5
6   Page-granularity memory management
7
8   This impedence-matches between Nautilus's singular allocator (malloc/free)
9   and page-level memory allocation needed in Palacios.   It does so via 
10   a last-fit-optimized bitmap allocator that operates over a large pool 
11   allocated from Nautilus at startup.
12
13   Note that this allocation currently ignores NUMA and other constraints
14   as well as general filter expressions.   
15
16 */
17
18 static uint64_t get_order(uint64_t n)
19 {
20     uint64_t top_bit_pos;
21
22     top_bit_pos = 63 - __builtin_clz(n);
23
24     return top_bit_pos + !!(n & ~(1<<top_bit_pos));
25
26 }
27
28 struct mempool {
29     u8 * bitmap;
30     u64 num_pages;
31     u64 num_free_pages;
32     u64 pool_start;
33     u64 base_addr;
34     u64 alloc_base_addr;
35 };
36
37 static struct mempool pool;
38
39
40 static inline int get_page_bit(int index) {
41     int major = index / 8;
42     int minor = index % 8;
43     return pool.bitmap[major] & (0x1 << minor);
44 }
45
46 static inline void clear_page_bit(int index) {
47     int major = index / 8;
48     int minor = index % 8;
49     pool.bitmap[major] &= ~(0x1 << minor);
50     ++pool.num_free_pages;
51 }
52
53 static inline void set_page_bit(int index) {
54     int major = index / 8;
55     int minor = index % 8;
56     pool.bitmap[major] |= (0x1 << minor);
57     --pool.num_free_pages;
58 }
59
60
61
62 int init_palacios_nautilus_mm(uint64_t memsize) {
63
64     INFO("Palacios MM: init\n");
65     INFO("Palacios MM: Nautilus page size is %d\n", PAGE_SIZE);
66     unsigned num_nk_pages = memsize / PAGE_SIZE;
67     unsigned num_palacios_pages = memsize / PALACIOS_PAGE_SIZE;
68
69     INFO("Palacios MM: Initializing with %u 4K pages (%u pages on Nautilus)\n", num_palacios_pages, num_nk_pages);
70
71     unsigned bitmap_size = (num_palacios_pages / 8) + ((num_palacios_pages % 8) > 0);
72     pool.bitmap = palacios_alloc(bitmap_size);
73
74     if (!pool.bitmap) { 
75         ERROR("Palacios MM: Failed to allocate bitmap\n");
76         return -1;
77     }
78     // note that this may not be aligned
79     pool.alloc_base_addr = (u64) palacios_alloc(PAGE_SIZE * num_nk_pages);
80     
81     if (!pool.alloc_base_addr) { 
82         ERROR("Palacios MM: FAILED TO ALLOCATE MEMORY\n");
83         return -1;
84     } else {
85         INFO("Palacios MM: success, alloc_base_addr=%p\n",pool.alloc_base_addr);
86     }
87     
88     // Align our memory to a page boundary
89     pool.base_addr = (u64) (((uint64_t)pool.alloc_base_addr & (~0xfffULL)) + PALACIOS_PAGE_SIZE);
90     
91     INFO("Palacios MM: success, cleaned up base_addr=%p\n",pool.base_addr);
92
93     // We have one fewer pages than requested due to the need to align
94     // the result of the malloc
95     pool.num_pages = num_palacios_pages - 1 ;
96     pool.num_free_pages = num_palacios_pages - 1;
97     pool.pool_start = 0;
98
99     // do unit test if desired
100     //test_palacios_mm(num_palacios_pages);
101
102     return 0;
103
104 }
105
106
107 int deinit_palacios_nautilus_mm(void) {
108     // free pages from nk
109     free((void*)pool.alloc_base_addr); pool.alloc_base_addr = 0;
110     free((void*)pool.bitmap); pool.bitmap = 0;
111     
112     return 0;
113 }
114
115 static uintptr_t alloc_contig_pgs(u64 num_pages, u32 alignment) 
116 {
117     
118     int step = 1;
119     int i = 0;
120     int j = 0;
121     
122     if (num_pages > pool.num_free_pages) {
123         ERROR("ERROR(PALACIOS MM) : NOT ENOUGH MEMORY\n");
124         return 0;
125     }
126
127     //INFO("Allocating %llu pages (align=%lu)\n", num_pages, (unsigned long)alignment);
128
129     if (!pool.bitmap || !pool.base_addr) {
130         ERROR("ERROR: Attempting to allocate from uninitialized memory pool \n");
131         return 0;
132     }
133
134     if (alignment > 0) {
135         if (alignment != 4096) { 
136             ERROR("ERROR: cannot handle alignment that is not 4KB\n");
137             return 0;
138         }
139         step = alignment / 4096;
140     }
141
142     // scan pages from last search forward
143     for (i = pool.pool_start; i < (pool.num_pages - num_pages + 1) ; ) {
144
145         for (j = i; j < (i+num_pages); j++) {
146             if (get_page_bit(j)) {
147                 break;
148             }
149          }
150          
151         if (j==(i+num_pages)) {
152             for (j = i; j<(i+num_pages); j++) {
153                 set_page_bit(j);
154             }
155             
156             pool.pool_start = j % pool.num_pages;
157             
158             return  (void*) (pool.base_addr + (i * 4096));
159             
160         }  else {
161             i = j+1;
162         }
163     }
164     
165
166     // scan from front if we didn't find it
167     for (i = 0;  i < (pool.num_pages - num_pages + 1) ; ) {
168
169         for (j = i; j < (i+num_pages); j++) {
170             if (get_page_bit(j)) {
171                 break;
172             }
173          }
174          
175         if (j==(i+num_pages)) {
176             for (j = i; j<(i+num_pages); j++) {
177                 set_page_bit(j);
178             }
179             
180             pool.pool_start = j % pool.num_pages;
181             
182             return (void*)( pool.base_addr + (i * 4096));
183             
184         }  else {
185             i = j+1;
186         }
187     }
188
189
190     ERROR("Palacios MM: ERROR! Cannot allocate memory...\n");
191     ERROR("Palacios MM: Pool has %d pages, trying to allocate %d pages\n", pool.num_pages, num_pages);
192
193     return 0;
194 }
195
196 uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id, int (*filter_func)(void *paddr, void *filter_state), void *filter_state)
197 {
198     uintptr_t addr = 0;
199     addr = alloc_contig_pgs(num_pages, alignment);
200     return addr;
201 }
202
203
204 void free_palacios_pgs(uintptr_t pg_addr, u64 num_pages)
205 {
206     int pg_idx = ((u64)pg_addr - pool.base_addr) / PALACIOS_PAGE_SIZE;
207     int i = 0;
208     for (i = pg_idx; i < pg_idx+num_pages; i++) {
209         clear_page_bit(i);
210     }
211 }
212
213
214 void free_palacios_pg(uintptr_t pg_addr)
215 {
216     free_palacios_pgs(pg_addr, 1);
217 }