Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
numa.c
Go to the documentation of this file.
1 /*
2  * acpi_numa.c - ACPI NUMA support
3  *
4  * Copyright (C) 2002 Takayoshi Kochi <[email protected]>
5  *
6  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23  *
24  */
25 #include <linux/module.h>
26 #include <linux/init.h>
27 #include <linux/kernel.h>
28 #include <linux/types.h>
29 #include <linux/errno.h>
30 #include <linux/acpi.h>
31 #include <linux/numa.h>
32 #include <acpi/acpi_bus.h>
33 
34 #define PREFIX "ACPI: "
35 
36 #define ACPI_NUMA 0x80000000
37 #define _COMPONENT ACPI_NUMA
38 ACPI_MODULE_NAME("numa");
39 
40 static nodemask_t nodes_found_map = NODE_MASK_NONE;
41 
42 /* maps to convert between proximity domain and logical node ID */
43 static int pxm_to_node_map[MAX_PXM_DOMAINS]
44  = { [0 ... MAX_PXM_DOMAINS - 1] = NUMA_NO_NODE };
45 static int node_to_pxm_map[MAX_NUMNODES]
46  = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
47 
48 unsigned char acpi_srat_revision __initdata;
49 
50 int pxm_to_node(int pxm)
51 {
52  if (pxm < 0)
53  return NUMA_NO_NODE;
54  return pxm_to_node_map[pxm];
55 }
56 
57 int node_to_pxm(int node)
58 {
59  if (node < 0)
60  return PXM_INVAL;
61  return node_to_pxm_map[node];
62 }
63 
64 void __acpi_map_pxm_to_node(int pxm, int node)
65 {
66  if (pxm_to_node_map[pxm] == NUMA_NO_NODE || node < pxm_to_node_map[pxm])
67  pxm_to_node_map[pxm] = node;
68  if (node_to_pxm_map[node] == PXM_INVAL || pxm < node_to_pxm_map[node])
69  node_to_pxm_map[node] = pxm;
70 }
71 
73 {
74  int node = pxm_to_node_map[pxm];
75 
76  if (node < 0) {
77  if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
78  return NUMA_NO_NODE;
79  node = first_unset_node(nodes_found_map);
80  __acpi_map_pxm_to_node(pxm, node);
81  node_set(node, nodes_found_map);
82  }
83 
84  return node;
85 }
86 
87 static void __init
88 acpi_table_print_srat_entry(struct acpi_subtable_header *header)
89 {
90 
91  ACPI_FUNCTION_NAME("acpi_table_print_srat_entry");
92 
93  if (!header)
94  return;
95 
96  switch (header->type) {
97 
99 #ifdef ACPI_DEBUG_OUTPUT
100  {
101  struct acpi_srat_cpu_affinity *p =
102  (struct acpi_srat_cpu_affinity *)header;
104  "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
105  p->apic_id, p->local_sapic_eid,
108  "enabled" : "disabled"));
109  }
110 #endif /* ACPI_DEBUG_OUTPUT */
111  break;
112 
114 #ifdef ACPI_DEBUG_OUTPUT
115  {
116  struct acpi_srat_mem_affinity *p =
117  (struct acpi_srat_mem_affinity *)header;
119  "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s\n",
120  (unsigned long)p->base_address,
121  (unsigned long)p->length,
122  p->proximity_domain,
124  "enabled" : "disabled",
126  " hot-pluggable" : ""));
127  }
128 #endif /* ACPI_DEBUG_OUTPUT */
129  break;
130 
132 #ifdef ACPI_DEBUG_OUTPUT
133  {
135  (struct acpi_srat_x2apic_cpu_affinity *)header;
137  "SRAT Processor (x2apicid[0x%08x]) in"
138  " proximity domain %d %s\n",
139  p->apic_id,
140  p->proximity_domain,
142  "enabled" : "disabled"));
143  }
144 #endif /* ACPI_DEBUG_OUTPUT */
145  break;
146  default:
148  "Found unsupported SRAT entry (type = 0x%x)\n",
149  header->type);
150  break;
151  }
152 }
153 
154 /*
155  * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
156  * up the NUMA heuristics which wants the local node to have a smaller
157  * distance than the others.
158  * Do some quick checks here and only use the SLIT if it passes.
159  */
160 static __init int slit_valid(struct acpi_table_slit *slit)
161 {
162  int i, j;
163  int d = slit->locality_count;
164  for (i = 0; i < d; i++) {
165  for (j = 0; j < d; j++) {
166  u8 val = slit->entry[d*i + j];
167  if (i == j) {
168  if (val != LOCAL_DISTANCE)
169  return 0;
170  } else if (val <= LOCAL_DISTANCE)
171  return 0;
172  }
173  }
174  return 1;
175 }
176 
177 static int __init acpi_parse_slit(struct acpi_table_header *table)
178 {
179  struct acpi_table_slit *slit;
180 
181  if (!table)
182  return -EINVAL;
183 
184  slit = (struct acpi_table_slit *)table;
185 
186  if (!slit_valid(slit)) {
187  printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
188  return -EINVAL;
189  }
190  acpi_numa_slit_init(slit);
191 
192  return 0;
193 }
194 
195 void __init __attribute__ ((weak))
197 {
199  "Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
200  return;
201 }
202 
203 
204 static int __init
205 acpi_parse_x2apic_affinity(struct acpi_subtable_header *header,
206  const unsigned long end)
207 {
208  struct acpi_srat_x2apic_cpu_affinity *processor_affinity;
209 
210  processor_affinity = (struct acpi_srat_x2apic_cpu_affinity *)header;
211  if (!processor_affinity)
212  return -EINVAL;
213 
214  acpi_table_print_srat_entry(header);
215 
216  /* let architecture-dependent part to do it */
217  acpi_numa_x2apic_affinity_init(processor_affinity);
218 
219  return 0;
220 }
221 
222 static int __init
223 acpi_parse_processor_affinity(struct acpi_subtable_header *header,
224  const unsigned long end)
225 {
226  struct acpi_srat_cpu_affinity *processor_affinity;
227 
228  processor_affinity = (struct acpi_srat_cpu_affinity *)header;
229  if (!processor_affinity)
230  return -EINVAL;
231 
232  acpi_table_print_srat_entry(header);
233 
234  /* let architecture-dependent part to do it */
235  acpi_numa_processor_affinity_init(processor_affinity);
236 
237  return 0;
238 }
239 
240 static int __initdata parsed_numa_memblks;
241 
242 static int __init
243 acpi_parse_memory_affinity(struct acpi_subtable_header * header,
244  const unsigned long end)
245 {
246  struct acpi_srat_mem_affinity *memory_affinity;
247 
248  memory_affinity = (struct acpi_srat_mem_affinity *)header;
249  if (!memory_affinity)
250  return -EINVAL;
251 
252  acpi_table_print_srat_entry(header);
253 
254  /* let architecture-dependent part to do it */
255  if (!acpi_numa_memory_affinity_init(memory_affinity))
256  parsed_numa_memblks++;
257  return 0;
258 }
259 
260 static int __init acpi_parse_srat(struct acpi_table_header *table)
261 {
262  struct acpi_table_srat *srat;
263  if (!table)
264  return -EINVAL;
265 
266  srat = (struct acpi_table_srat *)table;
267  acpi_srat_revision = srat->header.revision;
268 
269  /* Real work done in acpi_table_parse_srat below. */
270 
271  return 0;
272 }
273 
274 static int __init
275 acpi_table_parse_srat(enum acpi_srat_type id,
276  acpi_table_entry_handler handler, unsigned int max_entries)
277 {
279  sizeof(struct acpi_table_srat), id,
280  handler, max_entries);
281 }
282 
284 {
285  int cnt = 0;
286 
287  /*
288  * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
289  * SRAT cpu entries could have different order with that in MADT.
290  * So go over all cpu entries in SRAT to get apicid to node mapping.
291  */
292 
293  /* SRAT: Static Resource Affinity Table */
294  if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
295  acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
296  acpi_parse_x2apic_affinity, 0);
297  acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
298  acpi_parse_processor_affinity, 0);
299  cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
300  acpi_parse_memory_affinity,
302  }
303 
304  /* SLIT: System Locality Information Table */
305  acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
306 
308 
309  if (cnt < 0)
310  return cnt;
311  else if (!parsed_numa_memblks)
312  return -ENOENT;
313  return 0;
314 }
315 
317 {
318  unsigned long long pxm;
322 
323  do {
324  handle = phandle;
325  status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
326  if (ACPI_SUCCESS(status))
327  return pxm;
328  status = acpi_get_parent(handle, &phandle);
329  } while (ACPI_SUCCESS(status));
330  return -1;
331 }
332 
334 {
335  int pxm, node = -1;
336 
337  pxm = acpi_get_pxm(handle);
338  if (pxm >= 0 && pxm < MAX_PXM_DOMAINS)
339  node = acpi_map_pxm_to_node(pxm);
340 
341  return node;
342 }