1 /* Palacios memory manager
5 #include <asm/page_64_types.h>
6 #include <linux/kernel.h>
7 #include <linux/list.h>
8 #include <linux/slab.h>
10 //static struct list_head pools;
22 static struct mempool pool;
24 static inline int get_page_bit(int index) {
25 int major = index / 8;
26 int minor = index % 8;
28 return (pool.bitmap[major] & (0x1 << minor));
31 static inline void set_page_bit(int index) {
32 int major = index / 8;
33 int minor = index % 8;
35 pool.bitmap[major] |= (0x1 << minor);
38 static inline void clear_page_bit(int index) {
39 int major = index / 8;
40 int minor = index % 8;
42 pool.bitmap[major] &= ~(0x1 << minor);
46 uintptr_t get_palacios_base_addr(void) {
47 return pool.base_addr;
50 u64 get_palacios_num_pages(void) {
51 return pool.num_pages;
55 static uintptr_t alloc_contig_pgs(u64 num_pages, u32 alignment) {
60 DEBUG("Allocating %llu pages (align=%lu)\n",
61 num_pages, (unsigned long)alignment);
63 if (pool.bitmap == NULL) {
64 ERROR("ERROR: Attempting to allocate from non initialized memory\n");
69 step = alignment / 4096;
72 // Start the search at the correct alignment
73 if (pool.base_addr % alignment) {
74 start = ((alignment - (pool.base_addr % alignment)) >> 12);
77 ERROR("\t Start idx %d (base_addr=%p)\n", start, (void *)(u64)pool.base_addr);
79 for (i = start; i < (pool.num_pages - num_pages); i += step) {
80 if (get_page_bit(i) == 0) {
84 for (j = i; (j - i) < num_pages; j++) {
85 if (get_page_bit(j) == 1) {
95 for (j = i; (j - i) < num_pages; j++) {
99 return pool.base_addr + (i * 4096);
103 /* ERROR("PALACIOS BAD: LARGE PAGE ALLOCATION FAILED\n"); */
109 // alignment is in bytes
110 uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment) {
113 if ((num_pages < 12)) {
114 struct page * pgs = NULL;
115 int order = get_order(num_pages * PAGE_SIZE);
117 pgs = alloc_pages(GFP_DMA32, order);
119 WARN(!pgs, "Could not allocate pages\n");
121 /* if (!pgs) { ERROR("PALACIOS BAD: SMALL PAGE ALLOCATION FAILED\n"); } */
123 /* DEBUG("%llu pages (order=%d) aquired from alloc_pages\n",
124 num_pages, order); */
126 addr = page_to_pfn(pgs) << PAGE_SHIFT;
128 //DEBUG("Allocating %llu pages from bitmap allocator\n", num_pages);
129 //addr = pool.base_addr;
130 addr = alloc_contig_pgs(num_pages, alignment);
134 //DEBUG("Returning from alloc addr=%p, vaddr=%p\n", (void *)addr, __va(addr));
140 void free_palacios_pgs(uintptr_t pg_addr, int num_pages) {
141 //DEBUG("Freeing Memory page %p\n", (void *)pg_addr);
143 if ((pg_addr >= pool.base_addr) &&
144 (pg_addr < pool.base_addr + (4096 * pool.num_pages))) {
145 int pg_idx = (pg_addr - pool.base_addr) / 4096;
148 if ((pg_idx + num_pages) > pool.num_pages) {
149 ERROR("Freeing memory bounds exceeded\n");
153 for (i = 0; i < num_pages; i++) {
154 WARN(get_page_bit(pg_idx + i) == 0, "Trying to free unallocated page\n");
156 clear_page_bit(pg_idx + i);
159 __free_pages(pfn_to_page(pg_addr >> PAGE_SHIFT), get_order(num_pages * PAGE_SIZE));
164 int add_palacios_memory(uintptr_t base_addr, u64 num_pages) {
165 /* JRL: OK.... so this is horrible, terrible and if anyone else did it I would yell at them.
166 * But... the fact that you can do this in C is so ridiculous that I can't help myself.
167 * Note that we're repurposing "true" to be 1 here
170 int bitmap_size = (num_pages / 8) + ((num_pages % 8) > 0);
172 if (pool.num_pages != 0) {
173 ERROR("ERROR: Memory has already been added\n");
177 DEBUG("Managing %dMB of memory starting at %llu (%lluMB)\n",
178 (unsigned int)(num_pages * 4096) / (1024 * 1024),
179 (unsigned long long)base_addr,
180 (unsigned long long)(base_addr / (1024 * 1024)));
183 pool.bitmap = kmalloc(bitmap_size, GFP_KERNEL);
185 if (IS_ERR(pool.bitmap)) {
186 WARNING("Error allocating Palacios MM bitmap\n");
190 memset(pool.bitmap, 0, bitmap_size);
192 pool.base_addr = base_addr;
193 pool.num_pages = num_pages;
200 int palacios_init_mm( void ) {
201 // INIT_LIST_HEAD(&(pools));
209 int palacios_deinit_mm( void ) {