]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/x86/mm/srat_64.c
x86, ACPI: add support for x2apic ACPI extensions
[linux-2.6-omap-h63xx.git] / arch / x86 / mm / srat_64.c
1 /*
2  * ACPI 3.0 based NUMA setup
3  * Copyright 2004 Andi Kleen, SuSE Labs.
4  *
5  * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs.
6  *
7  * Called from acpi_numa_init while reading the SRAT and SLIT tables.
8  * Assumes all memory regions belonging to a single proximity domain
9  * are in one chunk. Holes between them will be included in the node.
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/acpi.h>
14 #include <linux/mmzone.h>
15 #include <linux/bitmap.h>
16 #include <linux/module.h>
17 #include <linux/topology.h>
18 #include <linux/bootmem.h>
19 #include <linux/mm.h>
20 #include <asm/proto.h>
21 #include <asm/numa.h>
22 #include <asm/e820.h>
23 #include <asm/genapic.h>
24
25 int acpi_numa __initdata;
26
27 static struct acpi_table_slit *acpi_slit;
28
29 static nodemask_t nodes_parsed __initdata;
30 static struct bootnode nodes[MAX_NUMNODES] __initdata;
31 static struct bootnode nodes_add[MAX_NUMNODES];
32 static int found_add_area __initdata;
33 int hotadd_percent __initdata = 0;
34
35 static int num_node_memblks __initdata;
36 static struct bootnode node_memblk_range[NR_NODE_MEMBLKS] __initdata;
37 static int memblk_nodeid[NR_NODE_MEMBLKS] __initdata;
38
39 /* Too small nodes confuse the VM badly. Usually they result
40    from BIOS bugs. */
41 #define NODE_MIN_SIZE (4*1024*1024)
42
43 static __init int setup_node(int pxm)
44 {
45         return acpi_map_pxm_to_node(pxm);
46 }
47
48 static __init int conflicting_memblks(unsigned long start, unsigned long end)
49 {
50         int i;
51         for (i = 0; i < num_node_memblks; i++) {
52                 struct bootnode *nd = &node_memblk_range[i];
53                 if (nd->start == nd->end)
54                         continue;
55                 if (nd->end > start && nd->start < end)
56                         return memblk_nodeid[i];
57                 if (nd->end == end && nd->start == start)
58                         return memblk_nodeid[i];
59         }
60         return -1;
61 }
62
63 static __init void cutoff_node(int i, unsigned long start, unsigned long end)
64 {
65         struct bootnode *nd = &nodes[i];
66
67         if (found_add_area)
68                 return;
69
70         if (nd->start < start) {
71                 nd->start = start;
72                 if (nd->end < nd->start)
73                         nd->start = nd->end;
74         }
75         if (nd->end > end) {
76                 nd->end = end;
77                 if (nd->start > nd->end)
78                         nd->start = nd->end;
79         }
80 }
81
82 static __init void bad_srat(void)
83 {
84         int i;
85         printk(KERN_ERR "SRAT: SRAT not used.\n");
86         acpi_numa = -1;
87         found_add_area = 0;
88         for (i = 0; i < MAX_LOCAL_APIC; i++)
89                 apicid_to_node[i] = NUMA_NO_NODE;
90         for (i = 0; i < MAX_NUMNODES; i++)
91                 nodes_add[i].start = nodes[i].end = 0;
92         remove_all_active_ranges();
93 }
94
95 static __init inline int srat_disabled(void)
96 {
97         return numa_off || acpi_numa < 0;
98 }
99
100 /* Callback for SLIT parsing */
101 void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
102 {
103         unsigned length;
104         unsigned long phys;
105
106         length = slit->header.length;
107         phys = find_e820_area(0, max_pfn_mapped<<PAGE_SHIFT, length,
108                  PAGE_SIZE);
109
110         if (phys == -1L)
111                 panic(" Can not save slit!\n");
112
113         acpi_slit = __va(phys);
114         memcpy(acpi_slit, slit, length);
115         reserve_early(phys, phys + length, "ACPI SLIT");
116 }
117
118 /* Callback for Proximity Domain -> x2APIC mapping */
119 void __init
120 acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
121 {
122         int pxm, node;
123         int apic_id;
124
125         if (srat_disabled())
126                 return;
127         if (pa->header.length < sizeof(struct acpi_srat_x2apic_cpu_affinity)) {
128                 bad_srat();
129                 return;
130         }
131         if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0)
132                 return;
133         pxm = pa->proximity_domain;
134         node = setup_node(pxm);
135         if (node < 0) {
136                 printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
137                 bad_srat();
138                 return;
139         }
140
141         apic_id = pa->apic_id;
142         apicid_to_node[apic_id] = node;
143         acpi_numa = 1;
144         printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
145                pxm, apic_id, node);
146 }
147
148 /* Callback for Proximity Domain -> LAPIC mapping */
149 void __init
150 acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
151 {
152         int pxm, node;
153         int apic_id;
154
155         if (srat_disabled())
156                 return;
157         if (pa->header.length != sizeof(struct acpi_srat_cpu_affinity)) {
158                 bad_srat();
159                 return;
160         }
161         if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0)
162                 return;
163         pxm = pa->proximity_domain_lo;
164         node = setup_node(pxm);
165         if (node < 0) {
166                 printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
167                 bad_srat();
168                 return;
169         }
170
171         if (get_uv_system_type() >= UV_X2APIC)
172                 apic_id = (pa->apic_id << 8) | pa->local_sapic_eid;
173         else
174                 apic_id = pa->apic_id;
175         apicid_to_node[apic_id] = node;
176         acpi_numa = 1;
177         printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
178                pxm, apic_id, node);
179 }
180
181 static int update_end_of_memory(unsigned long end) {return -1;}
182 static int hotadd_enough_memory(struct bootnode *nd) {return 1;}
183 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
184 static inline int save_add_info(void) {return 1;}
185 #else
186 static inline int save_add_info(void) {return 0;}
187 #endif
188 /*
189  * Update nodes_add and decide if to include add are in the zone.
190  * Both SPARSE and RESERVE need nodes_add information.
191  * This code supports one contiguous hot add area per node.
192  */
193 static int __init
194 reserve_hotadd(int node, unsigned long start, unsigned long end)
195 {
196         unsigned long s_pfn = start >> PAGE_SHIFT;
197         unsigned long e_pfn = end >> PAGE_SHIFT;
198         int ret = 0, changed = 0;
199         struct bootnode *nd = &nodes_add[node];
200
201         /* I had some trouble with strange memory hotadd regions breaking
202            the boot. Be very strict here and reject anything unexpected.
203            If you want working memory hotadd write correct SRATs.
204
205            The node size check is a basic sanity check to guard against
206            mistakes */
207         if ((signed long)(end - start) < NODE_MIN_SIZE) {
208                 printk(KERN_ERR "SRAT: Hotplug area too small\n");
209                 return -1;
210         }
211
212         /* This check might be a bit too strict, but I'm keeping it for now. */
213         if (absent_pages_in_range(s_pfn, e_pfn) != e_pfn - s_pfn) {
214                 printk(KERN_ERR
215                         "SRAT: Hotplug area %lu -> %lu has existing memory\n",
216                         s_pfn, e_pfn);
217                 return -1;
218         }
219
220         if (!hotadd_enough_memory(&nodes_add[node]))  {
221                 printk(KERN_ERR "SRAT: Hotplug area too large\n");
222                 return -1;
223         }
224
225         /* Looks good */
226
227         if (nd->start == nd->end) {
228                 nd->start = start;
229                 nd->end = end;
230                 changed = 1;
231         } else {
232                 if (nd->start == end) {
233                         nd->start = start;
234                         changed = 1;
235                 }
236                 if (nd->end == start) {
237                         nd->end = end;
238                         changed = 1;
239                 }
240                 if (!changed)
241                         printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n");
242         }
243
244         ret = update_end_of_memory(nd->end);
245
246         if (changed)
247                 printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n", nd->start, nd->end);
248         return ret;
249 }
250
251 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
252 void __init
253 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
254 {
255         struct bootnode *nd, oldnode;
256         unsigned long start, end;
257         int node, pxm;
258         int i;
259
260         if (srat_disabled())
261                 return;
262         if (ma->header.length != sizeof(struct acpi_srat_mem_affinity)) {
263                 bad_srat();
264                 return;
265         }
266         if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
267                 return;
268
269         if ((ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && !save_add_info())
270                 return;
271         start = ma->base_address;
272         end = start + ma->length;
273         pxm = ma->proximity_domain;
274         node = setup_node(pxm);
275         if (node < 0) {
276                 printk(KERN_ERR "SRAT: Too many proximity domains.\n");
277                 bad_srat();
278                 return;
279         }
280         i = conflicting_memblks(start, end);
281         if (i == node) {
282                 printk(KERN_WARNING
283                 "SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n",
284                         pxm, start, end, nodes[i].start, nodes[i].end);
285         } else if (i >= 0) {
286                 printk(KERN_ERR
287                        "SRAT: PXM %d (%lx-%lx) overlaps with PXM %d (%Lx-%Lx)\n",
288                        pxm, start, end, node_to_pxm(i),
289                         nodes[i].start, nodes[i].end);
290                 bad_srat();
291                 return;
292         }
293         nd = &nodes[node];
294         oldnode = *nd;
295         if (!node_test_and_set(node, nodes_parsed)) {
296                 nd->start = start;
297                 nd->end = end;
298         } else {
299                 if (start < nd->start)
300                         nd->start = start;
301                 if (nd->end < end)
302                         nd->end = end;
303         }
304
305         printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
306                start, end);
307         e820_register_active_regions(node, start >> PAGE_SHIFT,
308                                      end >> PAGE_SHIFT);
309         push_node_boundaries(node, nd->start >> PAGE_SHIFT,
310                                                 nd->end >> PAGE_SHIFT);
311
312         if ((ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) &&
313             (reserve_hotadd(node, start, end) < 0)) {
314                 /* Ignore hotadd region. Undo damage */
315                 printk(KERN_NOTICE "SRAT: Hotplug region ignored\n");
316                 *nd = oldnode;
317                 if ((nd->start | nd->end) == 0)
318                         node_clear(node, nodes_parsed);
319         }
320
321         node_memblk_range[num_node_memblks].start = start;
322         node_memblk_range[num_node_memblks].end = end;
323         memblk_nodeid[num_node_memblks] = node;
324         num_node_memblks++;
325 }
326
327 /* Sanity check to catch more bad SRATs (they are amazingly common).
328    Make sure the PXMs cover all memory. */
329 static int __init nodes_cover_memory(const struct bootnode *nodes)
330 {
331         int i;
332         unsigned long pxmram, e820ram;
333
334         pxmram = 0;
335         for_each_node_mask(i, nodes_parsed) {
336                 unsigned long s = nodes[i].start >> PAGE_SHIFT;
337                 unsigned long e = nodes[i].end >> PAGE_SHIFT;
338                 pxmram += e - s;
339                 pxmram -= absent_pages_in_range(s, e);
340                 if ((long)pxmram < 0)
341                         pxmram = 0;
342         }
343
344         e820ram = max_pfn - absent_pages_in_range(0, max_pfn);
345         /* We seem to lose 3 pages somewhere. Allow a bit of slack. */
346         if ((long)(e820ram - pxmram) >= 1*1024*1024) {
347                 printk(KERN_ERR
348         "SRAT: PXMs only cover %luMB of your %luMB e820 RAM. Not used.\n",
349                         (pxmram << PAGE_SHIFT) >> 20,
350                         (e820ram << PAGE_SHIFT) >> 20);
351                 return 0;
352         }
353         return 1;
354 }
355
356 static void __init unparse_node(int node)
357 {
358         int i;
359         node_clear(node, nodes_parsed);
360         for (i = 0; i < MAX_LOCAL_APIC; i++) {
361                 if (apicid_to_node[i] == node)
362                         apicid_to_node[i] = NUMA_NO_NODE;
363         }
364 }
365
366 void __init acpi_numa_arch_fixup(void) {}
367
368 /* Use the information discovered above to actually set up the nodes. */
369 int __init acpi_scan_nodes(unsigned long start, unsigned long end)
370 {
371         int i;
372
373         if (acpi_numa <= 0)
374                 return -1;
375
376         /* First clean up the node list */
377         for (i = 0; i < MAX_NUMNODES; i++) {
378                 cutoff_node(i, start, end);
379                 /*
380                  * don't confuse VM with a node that doesn't have the
381                  * minimum memory.
382                  */
383                 if (nodes[i].end &&
384                         (nodes[i].end - nodes[i].start) < NODE_MIN_SIZE) {
385                         unparse_node(i);
386                         node_set_offline(i);
387                 }
388         }
389
390         if (!nodes_cover_memory(nodes)) {
391                 bad_srat();
392                 return -1;
393         }
394
395         memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks,
396                                            memblk_nodeid);
397         if (memnode_shift < 0) {
398                 printk(KERN_ERR
399                      "SRAT: No NUMA node hash function found. Contact maintainer\n");
400                 bad_srat();
401                 return -1;
402         }
403
404         node_possible_map = nodes_parsed;
405
406         /* Finally register nodes */
407         for_each_node_mask(i, node_possible_map)
408                 setup_node_bootmem(i, nodes[i].start, nodes[i].end);
409         /* Try again in case setup_node_bootmem missed one due
410            to missing bootmem */
411         for_each_node_mask(i, node_possible_map)
412                 if (!node_online(i))
413                         setup_node_bootmem(i, nodes[i].start, nodes[i].end);
414
415         for (i = 0; i < nr_cpu_ids; i++) {
416                 int node = early_cpu_to_node(i);
417
418                 if (node == NUMA_NO_NODE)
419                         continue;
420                 if (!node_isset(node, node_possible_map))
421                         numa_clear_node(i);
422         }
423         numa_init_array();
424         return 0;
425 }
426
427 #ifdef CONFIG_NUMA_EMU
428 static int fake_node_to_pxm_map[MAX_NUMNODES] __initdata = {
429         [0 ... MAX_NUMNODES-1] = PXM_INVAL
430 };
431 static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = {
432         [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
433 };
434 static int __init find_node_by_addr(unsigned long addr)
435 {
436         int ret = NUMA_NO_NODE;
437         int i;
438
439         for_each_node_mask(i, nodes_parsed) {
440                 /*
441                  * Find the real node that this emulated node appears on.  For
442                  * the sake of simplicity, we only use a real node's starting
443                  * address to determine which emulated node it appears on.
444                  */
445                 if (addr >= nodes[i].start && addr < nodes[i].end) {
446                         ret = i;
447                         break;
448                 }
449         }
450         return ret;
451 }
452
453 /*
454  * In NUMA emulation, we need to setup proximity domain (_PXM) to node ID
455  * mappings that respect the real ACPI topology but reflect our emulated
456  * environment.  For each emulated node, we find which real node it appears on
457  * and create PXM to NID mappings for those fake nodes which mirror that
458  * locality.  SLIT will now represent the correct distances between emulated
459  * nodes as a result of the real topology.
460  */
461 void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes)
462 {
463         int i, j;
464
465         printk(KERN_INFO "Faking PXM affinity for fake nodes on real "
466                          "topology.\n");
467         for (i = 0; i < num_nodes; i++) {
468                 int nid, pxm;
469
470                 nid = find_node_by_addr(fake_nodes[i].start);
471                 if (nid == NUMA_NO_NODE)
472                         continue;
473                 pxm = node_to_pxm(nid);
474                 if (pxm == PXM_INVAL)
475                         continue;
476                 fake_node_to_pxm_map[i] = pxm;
477                 /*
478                  * For each apicid_to_node mapping that exists for this real
479                  * node, it must now point to the fake node ID.
480                  */
481                 for (j = 0; j < MAX_LOCAL_APIC; j++)
482                         if (apicid_to_node[j] == nid)
483                                 fake_apicid_to_node[j] = i;
484         }
485         for (i = 0; i < num_nodes; i++)
486                 __acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i);
487         memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node));
488
489         nodes_clear(nodes_parsed);
490         for (i = 0; i < num_nodes; i++)
491                 if (fake_nodes[i].start != fake_nodes[i].end)
492                         node_set(i, nodes_parsed);
493         WARN_ON(!nodes_cover_memory(fake_nodes));
494 }
495
496 static int null_slit_node_compare(int a, int b)
497 {
498         return node_to_pxm(a) == node_to_pxm(b);
499 }
500 #else
501 static int null_slit_node_compare(int a, int b)
502 {
503         return a == b;
504 }
505 #endif /* CONFIG_NUMA_EMU */
506
507 void __init srat_reserve_add_area(int nodeid)
508 {
509         if (found_add_area && nodes_add[nodeid].end) {
510                 u64 total_mb;
511
512                 printk(KERN_INFO "SRAT: Reserving hot-add memory space "
513                                 "for node %d at %Lx-%Lx\n",
514                         nodeid, nodes_add[nodeid].start, nodes_add[nodeid].end);
515                 total_mb = (nodes_add[nodeid].end - nodes_add[nodeid].start)
516                                         >> PAGE_SHIFT;
517                 total_mb *= sizeof(struct page);
518                 total_mb >>= 20;
519                 printk(KERN_INFO "SRAT: This will cost you %Lu MB of "
520                                 "pre-allocated memory.\n", (unsigned long long)total_mb);
521                 reserve_bootmem_node(NODE_DATA(nodeid), nodes_add[nodeid].start,
522                                nodes_add[nodeid].end - nodes_add[nodeid].start,
523                                BOOTMEM_DEFAULT);
524         }
525 }
526
527 int __node_distance(int a, int b)
528 {
529         int index;
530
531         if (!acpi_slit)
532                 return null_slit_node_compare(a, b) ? LOCAL_DISTANCE :
533                                                       REMOTE_DISTANCE;
534         index = acpi_slit->locality_count * node_to_pxm(a);
535         return acpi_slit->entry[index + node_to_pxm(b)];
536 }
537
538 EXPORT_SYMBOL(__node_distance);
539
540 #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || defined(CONFIG_ACPI_HOTPLUG_MEMORY)
541 int memory_add_physaddr_to_nid(u64 start)
542 {
543         int i, ret = 0;
544
545         for_each_node(i)
546                 if (nodes_add[i].start <= start && nodes_add[i].end > start)
547                         ret = i;
548
549         return ret;
550 }
551 EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
552 #endif