2 * Some of the code in this file has been gleaned from the 64 bit
3 * discontigmem support code base.
5 * Copyright (C) 2002, IBM Corp.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
17 * NON INFRINGEMENT. See the GNU General Public License for more
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * Send feedback to Pat Gaughen <gone@us.ibm.com>
27 #include <linux/bootmem.h>
28 #include <linux/mmzone.h>
29 #include <linux/acpi.h>
30 #include <linux/nodemask.h>
32 #include <asm/topology.h>
37 * proximity macros and definitions
39 #define NODE_ARRAY_INDEX(x) ((x) / 8) /* 8 bits/char */
40 #define NODE_ARRAY_OFFSET(x) ((x) % 8) /* 8 bits/char */
41 #define BMAP_SET(bmap, bit) ((bmap)[NODE_ARRAY_INDEX(bit)] |= 1 << NODE_ARRAY_OFFSET(bit))
42 #define BMAP_TEST(bmap, bit) ((bmap)[NODE_ARRAY_INDEX(bit)] & (1 << NODE_ARRAY_OFFSET(bit)))
43 /* bitmap length; _PXM is at most 255 */
44 #define PXM_BITMAP_LEN (MAX_PXM_DOMAINS / 8)
45 static u8 __initdata pxm_bitmap
[PXM_BITMAP_LEN
]; /* bitmap of proximity domains */
47 #define MAX_CHUNKS_PER_NODE 3
48 #define MAXCHUNKS (MAX_CHUNKS_PER_NODE * MAX_NUMNODES)
49 struct node_memory_chunk_s
{
50 unsigned long start_pfn
;
51 unsigned long end_pfn
;
52 u8 pxm
; // proximity domain of node
53 u8 nid
; // which cnode contains this chunk?
54 u8 bank
; // which mem bank on this node
56 static struct node_memory_chunk_s __initdata node_memory_chunk
[MAXCHUNKS
];
58 static int __initdata num_memory_chunks
; /* total number of memory chunks */
59 static u8 __initdata apicid_to_pxm
[MAX_APICID
];
61 int numa_off __initdata
;
62 int acpi_numa __initdata
;
64 static __init
void bad_srat(void)
66 printk(KERN_ERR
"SRAT: SRAT not used.\n");
68 num_memory_chunks
= 0;
71 static __init
inline int srat_disabled(void)
73 return numa_off
|| acpi_numa
< 0;
76 /* Identify CPU proximity domains */
78 acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity
*cpu_affinity
)
82 if (cpu_affinity
->header
.length
!=
83 sizeof(struct acpi_srat_cpu_affinity
)) {
88 if ((cpu_affinity
->flags
& ACPI_SRAT_CPU_ENABLED
) == 0)
89 return; /* empty entry */
91 /* mark this node as "seen" in node bitmap */
92 BMAP_SET(pxm_bitmap
, cpu_affinity
->proximity_domain_lo
);
94 apicid_to_pxm
[cpu_affinity
->apic_id
] = cpu_affinity
->proximity_domain_lo
;
96 printk("CPU 0x%02X in proximity domain 0x%02X\n",
97 cpu_affinity
->apic_id
, cpu_affinity
->proximity_domain_lo
);
101 * Identify memory proximity domains and hot-remove capabilities.
102 * Fill node memory chunk list structure.
105 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity
*memory_affinity
)
107 unsigned long long paddr
, size
;
108 unsigned long start_pfn
, end_pfn
;
110 struct node_memory_chunk_s
*p
, *q
, *pend
;
114 if (memory_affinity
->header
.length
!=
115 sizeof(struct acpi_srat_mem_affinity
)) {
120 if ((memory_affinity
->flags
& ACPI_SRAT_MEM_ENABLED
) == 0)
121 return; /* empty entry */
123 pxm
= memory_affinity
->proximity_domain
& 0xff;
125 /* mark this node as "seen" in node bitmap */
126 BMAP_SET(pxm_bitmap
, pxm
);
128 /* calculate info for memory chunk structure */
129 paddr
= memory_affinity
->base_address
;
130 size
= memory_affinity
->length
;
132 start_pfn
= paddr
>> PAGE_SHIFT
;
133 end_pfn
= (paddr
+ size
) >> PAGE_SHIFT
;
136 if (num_memory_chunks
>= MAXCHUNKS
) {
137 printk("Too many mem chunks in SRAT. Ignoring %lld MBytes at %llx\n",
138 size
/(1024*1024), paddr
);
142 /* Insertion sort based on base address */
143 pend
= &node_memory_chunk
[num_memory_chunks
];
144 for (p
= &node_memory_chunk
[0]; p
< pend
; p
++) {
145 if (start_pfn
< p
->start_pfn
)
149 for (q
= pend
; q
>= p
; q
--)
152 p
->start_pfn
= start_pfn
;
153 p
->end_pfn
= end_pfn
;
158 printk("Memory range 0x%lX to 0x%lX (type 0x%X) in proximity domain 0x%02X %s\n",
160 memory_affinity
->memory_type
,
162 ((memory_affinity
->flags
& ACPI_SRAT_MEM_HOT_PLUGGABLE
) ?
163 "enabled and removable" : "enabled" ) );
166 /* Callback for SLIT parsing */
167 void __init
acpi_numa_slit_init(struct acpi_table_slit
*slit
)
171 void acpi_numa_arch_fixup(void)
175 * The SRAT table always lists ascending addresses, so can always
176 * assume that the first "start" address that you see is the real
177 * start of the node, and that the current "end" address is after
180 static __init
void node_read_chunk(int nid
, struct node_memory_chunk_s
*memory_chunk
)
183 * Only add present memory as told by the e820.
184 * There is no guarantee from the SRAT that the memory it
185 * enumerates is present at boot time because it represents
186 * *possible* memory hotplug areas the same as normal RAM.
188 if (memory_chunk
->start_pfn
>= max_pfn
) {
189 printk (KERN_INFO
"Ignoring SRAT pfns: 0x%08lx -> %08lx\n",
190 memory_chunk
->start_pfn
, memory_chunk
->end_pfn
);
193 if (memory_chunk
->nid
!= nid
)
196 if (!node_has_online_mem(nid
))
197 node_start_pfn
[nid
] = memory_chunk
->start_pfn
;
199 if (node_start_pfn
[nid
] > memory_chunk
->start_pfn
)
200 node_start_pfn
[nid
] = memory_chunk
->start_pfn
;
202 if (node_end_pfn
[nid
] < memory_chunk
->end_pfn
)
203 node_end_pfn
[nid
] = memory_chunk
->end_pfn
;
206 int __init
get_memcfg_from_srat(void)
214 if (num_memory_chunks
== 0) {
215 printk("could not finy any ACPI SRAT memory areas.\n");
219 /* Calculate total number of nodes in system from PXM bitmap and create
220 * a set of sequential node IDs starting at zero. (ACPI doesn't seem
221 * to specify the range of _PXM values.)
224 * MCD - we no longer HAVE to number nodes sequentially. PXM domain
225 * numbers could go as high as 256, and MAX_NUMNODES for i386 is typically
226 * 32, so we will continue numbering them in this manner until MAX_NUMNODES
227 * approaches MAX_PXM_DOMAINS for i386.
229 nodes_clear(node_online_map
);
230 for (i
= 0; i
< MAX_PXM_DOMAINS
; i
++) {
231 if (BMAP_TEST(pxm_bitmap
, i
)) {
232 int nid
= acpi_map_pxm_to_node(i
);
233 node_set_online(nid
);
236 BUG_ON(num_online_nodes() == 0);
238 /* set cnode id in memory chunk structure */
239 for (i
= 0; i
< num_memory_chunks
; i
++)
240 node_memory_chunk
[i
].nid
= pxm_to_node(node_memory_chunk
[i
].pxm
);
242 printk("pxm bitmap: ");
243 for (i
= 0; i
< sizeof(pxm_bitmap
); i
++) {
244 printk("%02X ", pxm_bitmap
[i
]);
247 printk("Number of logical nodes in system = %d\n", num_online_nodes());
248 printk("Number of memory chunks in system = %d\n", num_memory_chunks
);
250 for (i
= 0; i
< MAX_APICID
; i
++)
251 apicid_2_node
[i
] = pxm_to_node(apicid_to_pxm
[i
]);
253 for (j
= 0; j
< num_memory_chunks
; j
++){
254 struct node_memory_chunk_s
* chunk
= &node_memory_chunk
[j
];
255 printk("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
256 j
, chunk
->nid
, chunk
->start_pfn
, chunk
->end_pfn
);
257 node_read_chunk(chunk
->nid
, chunk
);
258 e820_register_active_regions(chunk
->nid
, chunk
->start_pfn
,
259 min(chunk
->end_pfn
, max_pfn
));
262 for_each_online_node(nid
) {
263 unsigned long start
= node_start_pfn
[nid
];
264 unsigned long end
= min(node_end_pfn
[nid
], max_pfn
);
266 memory_present(nid
, start
, end
);
267 node_remap_size
[nid
] = node_memmap_size_bytes(nid
, start
, end
);
271 printk("failed to get NUMA memory information from SRAT table\n");