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.


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