sfc: Don't use enums as a bitmask.
[zen-stable.git] / arch / x86 / mm / srat_64.c
blob8e9d3394f6d452d97703f2e639e2d0b8f409d473
1 /*
2 * ACPI 3.0 based NUMA setup
3 * Copyright 2004 Andi Kleen, SuSE Labs.
5 * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs.
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.
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/memblock.h>
20 #include <linux/mm.h>
21 #include <asm/proto.h>
22 #include <asm/numa.h>
23 #include <asm/e820.h>
24 #include <asm/apic.h>
25 #include <asm/uv/uv.h>
27 int acpi_numa __initdata;
29 static struct bootnode nodes_add[MAX_NUMNODES];
31 static __init int setup_node(int pxm)
33 return acpi_map_pxm_to_node(pxm);
36 static __init void bad_srat(void)
38 printk(KERN_ERR "SRAT: SRAT not used.\n");
39 acpi_numa = -1;
40 memset(nodes_add, 0, sizeof(nodes_add));
43 static __init inline int srat_disabled(void)
45 return acpi_numa < 0;
48 /* Callback for SLIT parsing */
49 void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
51 int i, j;
53 for (i = 0; i < slit->locality_count; i++)
54 for (j = 0; j < slit->locality_count; j++)
55 numa_set_distance(pxm_to_node(i), pxm_to_node(j),
56 slit->entry[slit->locality_count * i + j]);
59 /* Callback for Proximity Domain -> x2APIC mapping */
60 void __init
61 acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
63 int pxm, node;
64 int apic_id;
66 if (srat_disabled())
67 return;
68 if (pa->header.length < sizeof(struct acpi_srat_x2apic_cpu_affinity)) {
69 bad_srat();
70 return;
72 if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0)
73 return;
74 pxm = pa->proximity_domain;
75 node = setup_node(pxm);
76 if (node < 0) {
77 printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
78 bad_srat();
79 return;
82 apic_id = pa->apic_id;
83 if (apic_id >= MAX_LOCAL_APIC) {
84 printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u skipped apicid that is too big\n", pxm, apic_id, node);
85 return;
87 set_apicid_to_node(apic_id, node);
88 node_set(node, numa_nodes_parsed);
89 acpi_numa = 1;
90 printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u\n",
91 pxm, apic_id, node);
94 /* Callback for Proximity Domain -> LAPIC mapping */
95 void __init
96 acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
98 int pxm, node;
99 int apic_id;
101 if (srat_disabled())
102 return;
103 if (pa->header.length != sizeof(struct acpi_srat_cpu_affinity)) {
104 bad_srat();
105 return;
107 if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0)
108 return;
109 pxm = pa->proximity_domain_lo;
110 node = setup_node(pxm);
111 if (node < 0) {
112 printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
113 bad_srat();
114 return;
117 if (get_uv_system_type() >= UV_X2APIC)
118 apic_id = (pa->apic_id << 8) | pa->local_sapic_eid;
119 else
120 apic_id = pa->apic_id;
122 if (apic_id >= MAX_LOCAL_APIC) {
123 printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u skipped apicid that is too big\n", pxm, apic_id, node);
124 return;
127 set_apicid_to_node(apic_id, node);
128 node_set(node, numa_nodes_parsed);
129 acpi_numa = 1;
130 printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u\n",
131 pxm, apic_id, node);
134 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
135 static inline int save_add_info(void) {return 1;}
136 #else
137 static inline int save_add_info(void) {return 0;}
138 #endif
140 * Update nodes_add[]
141 * This code supports one contiguous hot add area per node
143 static void __init
144 update_nodes_add(int node, unsigned long start, unsigned long end)
146 unsigned long s_pfn = start >> PAGE_SHIFT;
147 unsigned long e_pfn = end >> PAGE_SHIFT;
148 int changed = 0;
149 struct bootnode *nd = &nodes_add[node];
151 /* I had some trouble with strange memory hotadd regions breaking
152 the boot. Be very strict here and reject anything unexpected.
153 If you want working memory hotadd write correct SRATs.
155 The node size check is a basic sanity check to guard against
156 mistakes */
157 if ((signed long)(end - start) < NODE_MIN_SIZE) {
158 printk(KERN_ERR "SRAT: Hotplug area too small\n");
159 return;
162 /* This check might be a bit too strict, but I'm keeping it for now. */
163 if (absent_pages_in_range(s_pfn, e_pfn) != e_pfn - s_pfn) {
164 printk(KERN_ERR
165 "SRAT: Hotplug area %lu -> %lu has existing memory\n",
166 s_pfn, e_pfn);
167 return;
170 /* Looks good */
172 if (nd->start == nd->end) {
173 nd->start = start;
174 nd->end = end;
175 changed = 1;
176 } else {
177 if (nd->start == end) {
178 nd->start = start;
179 changed = 1;
181 if (nd->end == start) {
182 nd->end = end;
183 changed = 1;
185 if (!changed)
186 printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n");
189 if (changed) {
190 node_set(node, numa_nodes_parsed);
191 printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n",
192 nd->start, nd->end);
196 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
197 void __init
198 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
200 unsigned long start, end;
201 int node, pxm;
203 if (srat_disabled())
204 return;
205 if (ma->header.length != sizeof(struct acpi_srat_mem_affinity)) {
206 bad_srat();
207 return;
209 if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
210 return;
212 if ((ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && !save_add_info())
213 return;
214 start = ma->base_address;
215 end = start + ma->length;
216 pxm = ma->proximity_domain;
217 node = setup_node(pxm);
218 if (node < 0) {
219 printk(KERN_ERR "SRAT: Too many proximity domains.\n");
220 bad_srat();
221 return;
224 if (numa_add_memblk(node, start, end) < 0) {
225 bad_srat();
226 return;
229 printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
230 start, end);
232 if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
233 update_nodes_add(node, start, end);
236 void __init acpi_numa_arch_fixup(void) {}
238 int __init x86_acpi_numa_init(void)
240 int ret;
242 ret = acpi_numa_init();
243 if (ret < 0)
244 return ret;
245 return srat_disabled() ? -EINVAL : 0;
248 #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || defined(CONFIG_ACPI_HOTPLUG_MEMORY)
249 int memory_add_physaddr_to_nid(u64 start)
251 int i, ret = 0;
253 for_each_node(i)
254 if (nodes_add[i].start <= start && nodes_add[i].end > start)
255 ret = i;
257 return ret;
259 EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
260 #endif