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;
21 static struct mempool pool;
23 static inline int get_page_bit(int index) {
24 int major = index / 8;
25 int minor = index % 8;
27 return (pool.bitmap[major] & (0x1 << minor));
30 static inline void set_page_bit(int index) {
31 int major = index / 8;
32 int minor = index % 8;
34 pool.bitmap[major] |= (0x1 << minor);
37 static inline void clear_page_bit(int index) {
38 int major = index / 8;
39 int minor = index % 8;
41 pool.bitmap[major] &= ~(0x1 << minor);
46 static uintptr_t alloc_contig_pgs(u64 num_pages, u32 alignment) {
51 printk("Allocating %llu pages (align=%lu)\n",
52 num_pages, (unsigned long)alignment);
54 if (pool.bitmap == NULL) {
55 printk("ERROR: Attempting to allocate from non initialized memory\n");
60 step = alignment / 4096;
63 // Start the search at the correct alignment
64 if (pool.base_addr % alignment) {
65 start = ((alignment - (pool.base_addr % alignment)) >> 12);
68 printk("\t Start idx %d (base_addr=%llu)\n", start, (u64)pool.base_addr);
70 for (i = start; i < (pool.num_pages - num_pages); i += step) {
71 if (get_page_bit(i) == 0) {
75 for (j = i; (j - i) < num_pages; j++) {
76 if (get_page_bit(j) == 1) {
86 for (j = i; (j - i) < num_pages; j++) {
90 return pool.base_addr + (i * 4096);
98 // alignment is in bytes
99 uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment) {
102 if ((num_pages < 12)) {
103 struct page * pgs = NULL;
104 int order = get_order(num_pages * PAGE_SIZE);
106 pgs = alloc_pages(GFP_DMA, order);
108 WARN(!pgs, "Could not allocate pages\n");
110 printk("%llu pages (order=%d) aquired from alloc_pages\n",
113 addr = page_to_pfn(pgs) << PAGE_SHIFT;
115 printk("Allocating %llu pages from bitmap allocator\n", num_pages);
116 //addr = pool.base_addr;
117 addr = alloc_contig_pgs(num_pages, alignment);
121 printk("Returning from alloc addr=%p, vaddr=%p\n", (void *)addr, __va(addr));
127 void free_palacios_pgs(uintptr_t pg_addr, int num_pages) {
128 printk("Freeing Memory page %p\n", (void *)pg_addr);
130 if ((pg_addr >= pool.base_addr) &&
131 (pg_addr < pool.base_addr + (4096 * pool.num_pages))) {
132 int pg_idx = (pg_addr - pool.base_addr) / 4096;
135 if ((pg_idx + num_pages) > pool.num_pages) {
136 printk("Freeing memory bounds exceeded\n");
140 for (i = 0; i < num_pages; i++) {
141 WARN(get_page_bit(pg_idx + i) == 0, "Trying to free unallocated page\n");
143 clear_page_bit(pg_idx + i);
146 __free_pages(pfn_to_page(pg_addr >> PAGE_SHIFT), get_order(num_pages * PAGE_SIZE));
151 int add_palacios_memory(uintptr_t base_addr, u64 num_pages) {
152 /* JRL: OK.... so this is horrible, terrible and if anyone else did it I would yell at them.
153 * But... the fact that you can do this in C is so ridiculous that I can't help myself.
154 * Note that we're repurposing "true" to be 1 here
157 int bitmap_size = (num_pages / 8) + ((num_pages % 8) > 0);
159 if (pool.num_pages != 0) {
160 printk("ERROR: Memory has already been added\n");
164 printk("Managing %dMB of memory starting at %llu (%lluMB)\n",
165 (unsigned int)(num_pages * 4096) / (1024 * 1024),
166 (unsigned long long)base_addr,
167 (unsigned long long)(base_addr / (1024 * 1024)));
170 pool.bitmap = kmalloc(bitmap_size, GFP_KERNEL);
172 if (IS_ERR(pool.bitmap)) {
173 printk("Error allocating Palacios MM bitmap\n");
177 memset(pool.bitmap, 0, bitmap_size);
179 pool.base_addr = base_addr;
180 pool.num_pages = num_pages;
187 int palacios_init_mm( void ) {
188 // INIT_LIST_HEAD(&(pools));
196 int palacios_deinit_mm( void ) {