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.


/proc info showing vm device and vm name mapping, and memory use
[palacios.git] / linux_module / mm.c
1 /* Palacios memory manager 
2  * (c) Jack Lange, 2010
3  */
4
5 #include <asm/page_64_types.h>
6 #include <linux/kernel.h>
7 #include <linux/list.h>
8 #include <linux/slab.h>
9 #include <linux/mm.h>
10 //static struct list_head pools;
11
12 #include "palacios.h"
13
14 struct mempool {
15     uintptr_t base_addr;
16     u64 num_pages;
17
18     u8 * bitmap;
19 };
20
21
22 static struct mempool pool;
23
24 static inline int get_page_bit(int index) {
25     int major = index / 8;
26     int minor = index % 8;
27
28     return (pool.bitmap[major] & (0x1 << minor));
29 }
30
31 static inline void set_page_bit(int index) {
32     int major = index / 8;
33     int minor = index % 8;
34
35     pool.bitmap[major] |= (0x1 << minor);
36 }
37
38 static inline void clear_page_bit(int index) {
39     int major = index / 8;
40     int minor = index % 8;
41
42     pool.bitmap[major] &= ~(0x1 << minor);
43 }
44
45
46 uintptr_t get_palacios_base_addr(void) {
47     return pool.base_addr;
48 }
49
50 u64 get_palacios_num_pages(void) {
51     return pool.num_pages;
52 }
53
54
55 static uintptr_t alloc_contig_pgs(u64 num_pages, u32 alignment) {
56     int step = 1;
57     int i = 0;
58     int start = 0;
59
60     DEBUG("Allocating %llu pages (align=%lu)\n", 
61            num_pages, (unsigned long)alignment);
62
63     if (pool.bitmap == NULL) {
64         ERROR("ERROR: Attempting to allocate from non initialized memory\n");
65         return 0;
66     }
67
68     if (alignment > 0) {
69         step = alignment / 4096;
70     }
71
72     // Start the search at the correct alignment 
73     if (pool.base_addr % alignment) {
74         start = ((alignment - (pool.base_addr % alignment)) >> 12);
75     }
76
77     ERROR("\t Start idx %d (base_addr=%p)\n", start, (void *)(u64)pool.base_addr);
78
79     for (i = start; i < (pool.num_pages - num_pages); i += step) {
80         if (get_page_bit(i) == 0) {
81             int j = 0;
82             int collision = 0;
83
84             for (j = i; (j - i) < num_pages; j++) {
85                 if (get_page_bit(j) == 1) {
86                     collision = 1;
87                     break;
88                 }
89             }
90
91             if (collision == 1) {
92                 break;
93             }
94
95             for (j = i; (j - i) < num_pages; j++) {
96                 set_page_bit(j);
97             }
98
99             return pool.base_addr + (i * 4096);
100         }
101     }
102
103     /* ERROR("PALACIOS BAD: LARGE PAGE ALLOCATION FAILED\n"); */
104
105     return 0;
106 }
107
108
109 // alignment is in bytes
110 uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment) {
111     uintptr_t addr = 0; 
112
113     if ((num_pages < 12)) {
114         struct page * pgs = NULL;
115         int order = get_order(num_pages * PAGE_SIZE);
116          
117         pgs = alloc_pages(GFP_DMA32, order);
118     
119         WARN(!pgs, "Could not allocate pages\n");
120  
121         /* if (!pgs) { ERROR("PALACIOS BAD: SMALL PAGE ALLOCATION FAILED\n");  } */
122        
123         /* DEBUG("%llu pages (order=%d) aquired from alloc_pages\n", 
124                num_pages, order); */
125
126         addr = page_to_pfn(pgs) << PAGE_SHIFT; 
127     } else {
128         //DEBUG("Allocating %llu pages from bitmap allocator\n", num_pages);
129         //addr = pool.base_addr;
130         addr = alloc_contig_pgs(num_pages, alignment);
131     }
132
133
134     //DEBUG("Returning from alloc addr=%p, vaddr=%p\n", (void *)addr, __va(addr));
135     return addr;
136 }
137
138
139
140 void free_palacios_pgs(uintptr_t pg_addr, int num_pages) {
141     //DEBUG("Freeing Memory page %p\n", (void *)pg_addr);
142
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;
146         int i = 0;
147
148         if ((pg_idx + num_pages) > pool.num_pages) {
149             ERROR("Freeing memory bounds exceeded\n");
150             return;
151         }
152
153         for (i = 0; i < num_pages; i++) {
154             WARN(get_page_bit(pg_idx + i) == 0, "Trying to free unallocated page\n");
155
156             clear_page_bit(pg_idx + i);
157         }
158     } else {
159         __free_pages(pfn_to_page(pg_addr >> PAGE_SHIFT), get_order(num_pages * PAGE_SIZE));
160     }
161 }
162
163
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
168      */
169
170     int bitmap_size = (num_pages / 8) + ((num_pages % 8) > 0); 
171
172     if (pool.num_pages != 0) {
173         ERROR("ERROR: Memory has already been added\n");
174         return -1;
175     }
176
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)));
181
182
183     pool.bitmap = kmalloc(bitmap_size, GFP_KERNEL);
184     
185     if (IS_ERR(pool.bitmap)) {
186         WARNING("Error allocating Palacios MM bitmap\n");
187         return -1;
188     }
189     
190     memset(pool.bitmap, 0, bitmap_size);
191
192     pool.base_addr = base_addr;
193     pool.num_pages = num_pages;
194
195     return 0;
196 }
197
198
199
200 int palacios_init_mm( void ) {
201     //    INIT_LIST_HEAD(&(pools));
202     pool.base_addr = 0;
203     pool.num_pages = 0;
204     pool.bitmap = NULL;
205
206     return 0;
207 }
208
209 int palacios_deinit_mm( void ) {
210     kfree(pool.bitmap);
211     
212     return 0;
213 }