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.


added NUMA query support for Linux to allow Palacios to determine the NUMA layout...
[palacios.git] / linux_module / numa.c
1 /* NUMA topology 
2  * (c) Jack Lange, 2013
3  */
4
5 #include <linux/mm.h>
6
7 #include "palacios.h"
8 #include <interfaces/vmm_numa.h>
9
10
11
12 #if 0
13 struct mem_region {
14     u64 start_addr;
15     u64 end_addr;
16     u32 node_id;
17 };
18
19
20 static struct {
21     unsigned int num_nodes;
22     unsigned int num_cpus;
23     unsigned int num_mem_regions;
24
25     u32 * cpu_to_node_map;
26
27     // For now an array, but we might want to move this to an rbtree
28     struct mem_region * mem_to_node_map;
29     
30     u32 * distance_table;
31 } topology}
32
33
34 int create_numa_topology_from_user(void __user * argp) {
35     struct v3_numa_topo user_topo;
36
37     if (copy_from_user(&user_topo, argp, sizeof(struct v3_numa_topo))) {
38         ERROR("Could not read in NUMA topology from user\n");
39         return -1;
40     }
41         
42     argp += sizeof(struct v3_numa_topo);
43
44     topology.num_nodes = user_topo.num_nodes;
45     topology.num_cpus = user_topo.num_cpus;
46     topology.num_mem_regions = user_topo.num_mem_regions;
47
48
49     /* Read in the CPU to Node mapping */
50     {
51         topology.cpu_to_node_map = kmalloc(GFP_KERNEL, 
52                                            sizeof(u32) * 
53                                            topology.num_cpus);
54         
55         if (IS_ERR(topology.cpu_to_node_map)) {
56             ERROR("Could  not allocate cpu to node map\n");
57             return -1;
58         }
59         
60
61         if (copy_from_user(topology.cpu_to_node_map, argp,
62                            sizeof(u32) * topology.num_cpus)) {
63             ERROR("Could not copy cpu to node map from user space\n");
64             kfree(topology.cpu_to_node_map);
65             return -1;
66         }
67         
68         argp += sizeof(u32) * topology.num_cpus;
69     }
70
71     /* Read in the memory to Node Mapping */
72     {
73         int i = 0;
74
75         topology.mem_to_node_map = kmalloc(GFP_KERNEL, 
76                                            sizeof(struct mem_region) * 
77                                            topology.num_mem_regions);
78
79         if (IS_ERR(topology.mem_to_node_map)) {
80             ERROR("Could not allocate mem to node map\n");
81             kfree(topology.cpu_to_node_map);
82             return -1;
83         }
84
85         if (copy_from_user(topology.mem_to_node_map, argp,
86                            sizeof(struct mem_region) * topology.num_mem_regions)) {
87             ERROR("Coudl not copy mem to node map from user space\n");
88             kfree(topology.cpu_to_node_map);
89             kfree(topology.mem_to_node_map);
90             return -1;
91         }
92
93         /* The memory range comes in as the base_addr and the number of pages
94            We need to fix it up to be the base addr and end addr instead 
95            We just perform the transformation inline
96         */
97         for (i = 0; i < topology.num_mem_regions; i++) {
98             struct mem_region * region = &(topology.mem_to_node_map[i]);
99
100             region->end_addr = region->base_addr + (region->end_addr * 4096);
101         }
102
103     }
104
105     
106     /* Read in the distance table */
107     {
108         topology.distance_table = kmalloc(GFP_KERNEL,
109                                           sizeof(u32) * 
110                                           (topology.num_nodes * topology.num_nodes));
111         
112         if (IS_ERR(topology.distance_table)) {
113             ERROR("Could not allocate distance table\n");
114             kfree(topology.cpu_to_node_map);
115             kfree(topology.mem_to_node_map);
116             return -1;
117         }
118         
119
120         if (copy_from_user(topology.distance_table, argp,
121                            sizeof(u32) * (topology.num_nodes * topology.num_nodes))) {
122             ERROR("Could not copy distance table from user space\n");
123             kfree(topology.cpu_to_node_map);
124             kfree(topology.mem_to_node_map);
125             kfree(topology.distance_table);
126             return -1;
127         }
128
129     }
130     
131     /* Report what we found */
132     {
133         int i = 0;
134         int j = 0;
135
136         printk("Created NUMA topology from user space\n");
137         printk("Number of Nodes: %d, CPUs: %d, MEM regions: %d\n", 
138                topology.num_nodes, topology.num_cpus, topology.num_mem_regions);
139
140         printk("CPU mapping\n");
141         for (i = 0; i < topology.num_cpus; i++) {
142             printk("\tCPU %d -> Node %d\n", i, topology.cpu_to_node_map[i]);
143         }
144
145         printk("Memory mapping\n");
146
147         for (i = 0; i < topology.num_mem_regions; i++) {
148             struct mem_region * region = &(topology.mem_to_node_map[i]);
149             printk("\tMEM %p - %p -> Node %d\n", 
150                    region->start_addr, 
151                    region->end_addr, 
152                    region->node_id);
153         }
154
155
156         printk("Distance Table\n");
157         for (i = 0; i < topology.num_nodes; i++) {
158             printk("\t%d", i);
159         }
160         printk("\n");
161         
162         for (i = 0; i < topology.num_nodes; i++) {
163             printk("%d", i);
164
165             for (j = 0; j < topology.num_nodes; j++) {
166                 printk("\t%d", topology.distance_table[j + (i * topology.num_nodes)]);
167             }
168
169             printk("\n");
170
171         }           
172
173
174     }
175     return 0;
176
177 }
178
179
180 #endif
181
182
183
184 int numa_num_nodes(void) {
185     return num_online_nodes();
186 }
187
188
189
190 int numa_addr_to_node(uintptr_t phys_addr) {
191     return page_to_nid(pfn_to_page(phys_addr >> PAGE_SHIFT));
192 }
193
194 int numa_cpu_to_node(int cpu_id) {
195     return cpu_to_node(cpu_id);
196 }
197
198
199 int numa_get_distance(int node1, int node2) {
200     return node_distance(node1, node2);
201 }
202
203
204 /* Ugly fix for interface type differences... */
205 static int phys_ptr_to_node(void * phys_ptr) {
206     return numa_addr_to_node((uintptr_t)phys_ptr);
207 }
208
209 struct v3_numa_hooks numa_hooks = {
210     .cpu_to_node = numa_cpu_to_node,
211     .phys_addr_to_node = phys_ptr_to_node,
212     .get_distance = numa_get_distance,
213 };
214
215
216 int palacios_init_numa( void ) {
217  
218     V3_Init_NUMA(&numa_hooks);
219   
220     return 0;
221 }