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.


Correct memory addition calculations
[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 #include "mm.h"
14 #include "buddy.h"
15 #include "numa.h"
16
17
18 static struct buddy_memzone ** memzones = NULL;
19 static uintptr_t * seed_addrs = NULL;
20
21
22 // alignment is in bytes
23 uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id) {
24     uintptr_t addr = 0; 
25
26     if (node_id == -1) {
27         int cpu_id = get_cpu();
28         put_cpu();
29         
30         node_id = numa_cpu_to_node(cpu_id);
31     } else if (numa_num_nodes() == 1) {
32         node_id = 0;
33     } else if (node_id >= numa_num_nodes()) {
34         ERROR("Requesting memory from an invalid NUMA node. (Node: %d) (%d nodes on system)\n", 
35               node_id, numa_num_nodes());
36         return 0;
37     }
38
39     addr = buddy_alloc(memzones[node_id], get_order(num_pages * PAGE_SIZE) + PAGE_SHIFT);
40
41     //DEBUG("Returning from alloc addr=%p, vaddr=%p\n", (void *)addr, __va(addr));
42     return addr;
43 }
44
45
46
47 void free_palacios_pgs(uintptr_t pg_addr, u64 num_pages) {
48     int node_id = numa_addr_to_node(pg_addr);
49
50     //DEBUG("Freeing Memory page %p\n", (void *)pg_addr);
51     buddy_free(memzones[node_id], pg_addr, get_order(num_pages * PAGE_SIZE) + PAGE_SHIFT);
52     
53     return;
54 }
55
56
57 unsigned long long pow2(int i)
58 {
59     unsigned long long x=1;
60     for (;i!=0;i--) { x*=2; } 
61     return x;
62 }
63
64 int add_palacios_memory(struct v3_mem_region *r) {
65     int pool_order = 0;
66     int node_id = 0;
67
68     struct v3_mem_region *keep;
69
70     // fixup request regardless of its type
71     if (r->num_pages*4096 < V3_CONFIG_MEM_BLOCK_SIZE) { 
72         WARNING("Allocating a memory pool smaller than the Palacios block size - may not be useful\n");
73     }
74
75     if (pow2(get_order(r->num_pages*PAGE_SIZE)) != r->num_pages*PAGE_SIZE) { 
76         WARNING("Allocating a memory pool that is not a power of two (is %llu) - it will be rounded down!\n", r->num_pages*PAGE_SIZE);
77         r->num_pages=pow2(get_order(r->num_pages*PAGE_SIZE));
78         WARNING("Rounded power Allocating a memory pool that is not a power of two (rounded to %llu)\n", r->num_pages*PAGE_SIZE);
79     }
80
81
82     if (!(keep=palacios_alloc(sizeof(struct v3_mem_region)))) { 
83         ERROR("Error allocating space for tracking region\n");
84         return -1;
85     }
86
87
88     if (r->type==REQUESTED || r->type==REQUESTED32) { 
89         struct page * pgs = alloc_pages_node(r->node, 
90                                              r->type==REQUESTED ? GFP_KERNEL :
91                                              r->type==REQUESTED32 ? GFP_DMA32 : GFP_KERNEL, 
92                                              get_order(r->num_pages));
93         if (!pgs) { 
94             ERROR("Unable to satisfy allocation request\n");
95             palacios_free(keep);
96             return -1;
97         }
98         r->base_addr = page_to_pfn(pgs) << PAGE_SHIFT;
99     }
100         
101
102     *keep = *r;
103
104     node_id = numa_addr_to_node(r->base_addr);
105
106     if (node_id == -1) {
107         ERROR("Error locating node for addr %p\n", (void *)(r->base_addr));
108         return -1;
109     }
110
111     pool_order = get_order(r->num_pages * PAGE_SIZE) + PAGE_SHIFT;
112
113     if (buddy_add_pool(memzones[node_id], r->base_addr, pool_order, keep)) {
114         ERROR("ALERT ALERT ALERT Unable to add pool to buddy allocator...\n");
115         if (r->type==REQUESTED || r->type==REQUESTED32) { 
116             free_pages((uintptr_t)__va(r->base_addr), get_order(r->num_pages));
117         }
118         palacios_free(keep);
119         return -1;
120     }
121
122     return 0;
123 }
124
125
126
127 int palacios_remove_memory(uintptr_t base_addr) {
128     int node_id = numa_addr_to_node(base_addr);
129     struct v3_mem_region *r;
130
131     if (buddy_remove_pool(memzones[node_id], base_addr, 0, (void**)(&r))) { //unforced remove
132         ERROR("Cannot remove memory at base address 0x%p because it is in use\n", (void*)base_addr);
133         return -1;
134     }
135
136     if (r->type==REQUESTED || r->type==REQUESTED32) { 
137         free_pages((uintptr_t)__va(r->base_addr), get_order(r->num_pages));
138     } else {
139         // user space resposible for onlining
140     }
141     
142     palacios_free(r);
143
144     return 0;
145 }
146
147
148
149 int palacios_deinit_mm( void ) {
150
151     int i = 0;
152
153     if (memzones) {
154         for (i = 0; i < numa_num_nodes(); i++) {
155             
156             if (memzones[i]) {
157                 buddy_deinit(memzones[i]);
158             }
159             
160             // note that the memory is not onlined here - offlining and onlining
161             // is the resposibility of the caller
162             
163             if (seed_addrs[i]) {
164                 // free the seed regions
165                 free_pages((uintptr_t)__va(seed_addrs[i]), MAX_ORDER - 1);
166             }
167         }
168         
169         palacios_free(memzones);
170         palacios_free(seed_addrs);
171     }
172
173     return 0;
174 }
175
176 int palacios_init_mm( void ) {
177     int num_nodes = numa_num_nodes();
178     int node_id = 0;
179
180     memzones = palacios_alloc_extended(sizeof(struct buddy_memzone *) * num_nodes, GFP_KERNEL);
181
182     if (!memzones) { 
183         ERROR("Cannot allocate space for memory zones\n");
184         palacios_deinit_mm();
185         return -1;
186     }
187
188     memset(memzones, 0, sizeof(struct buddy_memzone *) * num_nodes);
189
190     seed_addrs = palacios_alloc_extended(sizeof(uintptr_t) * num_nodes, GFP_KERNEL);
191
192     if (!seed_addrs) { 
193         ERROR("Cannot allocate space for seed addrs\n");
194         palacios_deinit_mm();
195         return -1;
196     }
197
198     memset(seed_addrs, 0, sizeof(uintptr_t) * num_nodes);
199
200     for (node_id = 0; node_id < num_nodes; node_id++) {
201         struct buddy_memzone * zone = NULL;
202
203         // Seed the allocator with a small set of pages to allow initialization to complete. 
204         // For now we will just grab some random pages, but in the future we will need to grab NUMA specific regions
205         // See: alloc_pages_node()
206
207         {
208             struct page * pgs = alloc_pages_node(node_id, GFP_KERNEL, MAX_ORDER - 1);
209
210             if (!pgs) {
211                 ERROR("Could not allocate initial memory block for node %d\n", node_id);
212                 BUG_ON(!pgs);
213                 palacios_deinit_mm();
214                 return -1;
215             }
216
217             seed_addrs[node_id] = page_to_pfn(pgs) << PAGE_SHIFT;
218         }
219
220         zone = buddy_init(get_order(V3_CONFIG_MEM_BLOCK_SIZE) + PAGE_SHIFT, PAGE_SHIFT, node_id);
221
222         if (zone == NULL) {
223             ERROR("Could not initialization memory management for node %d\n", node_id);
224             palacios_deinit_mm();
225             return -1;
226         }
227
228         printk("Zone initialized, Adding seed region (order=%d)\n", 
229                (MAX_ORDER - 1) + PAGE_SHIFT);
230
231         if (buddy_add_pool(zone, seed_addrs[node_id], (MAX_ORDER - 1) + PAGE_SHIFT,0)) { 
232             ERROR("Could not add pool to buddy allocator\n");
233             palacios_deinit_mm();
234             return -1;
235         }
236
237         memzones[node_id] = zone;
238     }
239
240     return 0;
241
242 }
243