~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to arch/x86/mm/numa_32.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
23
 */
24
24
 
25
 
#include <linux/mm.h>
26
25
#include <linux/bootmem.h>
27
26
#include <linux/memblock.h>
28
 
#include <linux/mmzone.h>
29
 
#include <linux/highmem.h>
30
 
#include <linux/initrd.h>
31
 
#include <linux/nodemask.h>
32
27
#include <linux/module.h>
33
 
#include <linux/kexec.h>
34
 
#include <linux/pfn.h>
35
 
#include <linux/swap.h>
36
 
#include <linux/acpi.h>
37
 
 
38
 
#include <asm/e820.h>
39
 
#include <asm/setup.h>
40
 
#include <asm/mmzone.h>
41
 
#include <asm/bios_ebda.h>
42
 
#include <asm/proto.h>
43
 
 
44
 
struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
45
 
EXPORT_SYMBOL(node_data);
46
 
 
47
 
/*
48
 
 * numa interface - we expect the numa architecture specific code to have
49
 
 *                  populated the following initialisation.
50
 
 *
51
 
 * 1) node_online_map  - the map of all nodes configured (online) in the system
52
 
 * 2) node_start_pfn   - the starting page frame number for a node
53
 
 * 3) node_end_pfn     - the ending page fram number for a node
54
 
 */
55
 
unsigned long node_start_pfn[MAX_NUMNODES] __read_mostly;
56
 
unsigned long node_end_pfn[MAX_NUMNODES] __read_mostly;
57
 
 
 
28
 
 
29
#include "numa_internal.h"
58
30
 
59
31
#ifdef CONFIG_DISCONTIGMEM
60
32
/*
99
71
}
100
72
#endif
101
73
 
102
 
extern unsigned long find_max_low_pfn(void);
103
74
extern unsigned long highend_pfn, highstart_pfn;
104
75
 
105
76
#define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE)
106
77
 
107
 
unsigned long node_remap_size[MAX_NUMNODES];
108
78
static void *node_remap_start_vaddr[MAX_NUMNODES];
109
79
void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
110
80
 
111
 
static unsigned long kva_start_pfn;
112
 
static unsigned long kva_pages;
113
 
/*
114
 
 * FLAT - support for basic PC memory model with discontig enabled, essentially
115
 
 *        a single node with all available processors in it with a flat
116
 
 *        memory map.
117
 
 */
118
 
int __init get_memcfg_numa_flat(void)
119
 
{
120
 
        printk(KERN_DEBUG "NUMA - single node, flat memory mode\n");
121
 
 
122
 
        node_start_pfn[0] = 0;
123
 
        node_end_pfn[0] = max_pfn;
124
 
        memblock_x86_register_active_regions(0, 0, max_pfn);
125
 
        memory_present(0, 0, max_pfn);
126
 
        node_remap_size[0] = node_memmap_size_bytes(0, 0, max_pfn);
127
 
 
128
 
        /* Indicate there is one node available. */
129
 
        nodes_clear(node_online_map);
130
 
        node_set_online(0);
131
 
        return 1;
132
 
}
133
 
 
134
 
/*
135
 
 * Find the highest page frame number we have available for the node
136
 
 */
137
 
static void __init propagate_e820_map_node(int nid)
138
 
{
139
 
        if (node_end_pfn[nid] > max_pfn)
140
 
                node_end_pfn[nid] = max_pfn;
141
 
        /*
142
 
         * if a user has given mem=XXXX, then we need to make sure 
143
 
         * that the node _starts_ before that, too, not just ends
144
 
         */
145
 
        if (node_start_pfn[nid] > max_pfn)
146
 
                node_start_pfn[nid] = max_pfn;
147
 
        BUG_ON(node_start_pfn[nid] > node_end_pfn[nid]);
148
 
}
149
 
 
150
 
/* 
151
 
 * Allocate memory for the pg_data_t for this node via a crude pre-bootmem
152
 
 * method.  For node zero take this from the bottom of memory, for
153
 
 * subsequent nodes place them at node_remap_start_vaddr which contains
154
 
 * node local data in physically node local memory.  See setup_memory()
155
 
 * for details.
156
 
 */
157
 
static void __init allocate_pgdat(int nid)
158
 
{
159
 
        char buf[16];
160
 
 
161
 
        if (node_has_online_mem(nid) && node_remap_start_vaddr[nid])
162
 
                NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
163
 
        else {
164
 
                unsigned long pgdat_phys;
165
 
                pgdat_phys = memblock_find_in_range(min_low_pfn<<PAGE_SHIFT,
166
 
                                 max_pfn_mapped<<PAGE_SHIFT,
167
 
                                 sizeof(pg_data_t),
168
 
                                 PAGE_SIZE);
169
 
                NODE_DATA(nid) = (pg_data_t *)(pfn_to_kaddr(pgdat_phys>>PAGE_SHIFT));
170
 
                memset(buf, 0, sizeof(buf));
171
 
                sprintf(buf, "NODE_DATA %d",  nid);
172
 
                memblock_x86_reserve_range(pgdat_phys, pgdat_phys + sizeof(pg_data_t), buf);
173
 
        }
174
 
        printk(KERN_DEBUG "allocate_pgdat: node %d NODE_DATA %08lx\n",
175
 
                nid, (unsigned long)NODE_DATA(nid));
176
 
}
177
 
 
178
 
/*
179
 
 * In the DISCONTIGMEM and SPARSEMEM memory model, a portion of the kernel
180
 
 * virtual address space (KVA) is reserved and portions of nodes are mapped
181
 
 * using it. This is to allow node-local memory to be allocated for
182
 
 * structures that would normally require ZONE_NORMAL. The memory is
183
 
 * allocated with alloc_remap() and callers should be prepared to allocate
184
 
 * from the bootmem allocator instead.
 
81
/*
 
82
 * Remap memory allocator
185
83
 */
186
84
static unsigned long node_remap_start_pfn[MAX_NUMNODES];
187
85
static void *node_remap_end_vaddr[MAX_NUMNODES];
188
86
static void *node_remap_alloc_vaddr[MAX_NUMNODES];
189
 
static unsigned long node_remap_offset[MAX_NUMNODES];
190
87
 
 
88
/**
 
89
 * alloc_remap - Allocate remapped memory
 
90
 * @nid: NUMA node to allocate memory from
 
91
 * @size: The size of allocation
 
92
 *
 
93
 * Allocate @size bytes from the remap area of NUMA node @nid.  The
 
94
 * size of the remap area is predetermined by init_alloc_remap() and
 
95
 * only the callers considered there should call this function.  For
 
96
 * more info, please read the comment on top of init_alloc_remap().
 
97
 *
 
98
 * The caller must be ready to handle allocation failure from this
 
99
 * function and fall back to regular memory allocator in such cases.
 
100
 *
 
101
 * CONTEXT:
 
102
 * Single CPU early boot context.
 
103
 *
 
104
 * RETURNS:
 
105
 * Pointer to the allocated memory on success, %NULL on failure.
 
106
 */
191
107
void *alloc_remap(int nid, unsigned long size)
192
108
{
193
109
        void *allocation = node_remap_alloc_vaddr[nid];
194
110
 
195
111
        size = ALIGN(size, L1_CACHE_BYTES);
196
112
 
197
 
        if (!allocation || (allocation + size) >= node_remap_end_vaddr[nid])
 
113
        if (!allocation || (allocation + size) > node_remap_end_vaddr[nid])
198
114
                return NULL;
199
115
 
200
116
        node_remap_alloc_vaddr[nid] += size;
203
119
        return allocation;
204
120
}
205
121
 
206
 
static void __init remap_numa_kva(void)
207
 
{
208
 
        void *vaddr;
209
 
        unsigned long pfn;
210
 
        int node;
211
 
 
212
 
        for_each_online_node(node) {
213
 
                printk(KERN_DEBUG "remap_numa_kva: node %d\n", node);
214
 
                for (pfn=0; pfn < node_remap_size[node]; pfn += PTRS_PER_PTE) {
215
 
                        vaddr = node_remap_start_vaddr[node]+(pfn<<PAGE_SHIFT);
216
 
                        printk(KERN_DEBUG "remap_numa_kva: %08lx to pfn %08lx\n",
217
 
                                (unsigned long)vaddr,
218
 
                                node_remap_start_pfn[node] + pfn);
219
 
                        set_pmd_pfn((ulong) vaddr, 
220
 
                                node_remap_start_pfn[node] + pfn, 
221
 
                                PAGE_KERNEL_LARGE);
222
 
                }
223
 
        }
224
 
}
225
 
 
226
122
#ifdef CONFIG_HIBERNATION
227
123
/**
228
124
 * resume_map_numa_kva - add KVA mapping to the temporary page tables created
234
130
        int node;
235
131
 
236
132
        for_each_online_node(node) {
237
 
                unsigned long start_va, start_pfn, size, pfn;
 
133
                unsigned long start_va, start_pfn, nr_pages, pfn;
238
134
 
239
135
                start_va = (unsigned long)node_remap_start_vaddr[node];
240
136
                start_pfn = node_remap_start_pfn[node];
241
 
                size = node_remap_size[node];
 
137
                nr_pages = (node_remap_end_vaddr[node] -
 
138
                            node_remap_start_vaddr[node]) >> PAGE_SHIFT;
242
139
 
243
140
                printk(KERN_DEBUG "%s: node %d\n", __func__, node);
244
141
 
245
 
                for (pfn = 0; pfn < size; pfn += PTRS_PER_PTE) {
 
142
                for (pfn = 0; pfn < nr_pages; pfn += PTRS_PER_PTE) {
246
143
                        unsigned long vaddr = start_va + (pfn << PAGE_SHIFT);
247
144
                        pgd_t *pgd = pgd_base + pgd_index(vaddr);
248
145
                        pud_t *pud = pud_offset(pgd, vaddr);
258
155
}
259
156
#endif
260
157
 
261
 
static __init unsigned long calculate_numa_remap_pages(void)
262
 
{
263
 
        int nid;
264
 
        unsigned long size, reserve_pages = 0;
265
 
 
266
 
        for_each_online_node(nid) {
267
 
                u64 node_kva_target;
268
 
                u64 node_kva_final;
269
 
 
270
 
                /*
271
 
                 * The acpi/srat node info can show hot-add memroy zones
272
 
                 * where memory could be added but not currently present.
273
 
                 */
274
 
                printk(KERN_DEBUG "node %d pfn: [%lx - %lx]\n",
275
 
                        nid, node_start_pfn[nid], node_end_pfn[nid]);
276
 
                if (node_start_pfn[nid] > max_pfn)
277
 
                        continue;
278
 
                if (!node_end_pfn[nid])
279
 
                        continue;
280
 
                if (node_end_pfn[nid] > max_pfn)
281
 
                        node_end_pfn[nid] = max_pfn;
282
 
 
283
 
                /* ensure the remap includes space for the pgdat. */
284
 
                size = node_remap_size[nid] + sizeof(pg_data_t);
285
 
 
286
 
                /* convert size to large (pmd size) pages, rounding up */
287
 
                size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES;
288
 
                /* now the roundup is correct, convert to PAGE_SIZE pages */
289
 
                size = size * PTRS_PER_PTE;
290
 
 
291
 
                node_kva_target = round_down(node_end_pfn[nid] - size,
292
 
                                                 PTRS_PER_PTE);
293
 
                node_kva_target <<= PAGE_SHIFT;
294
 
                do {
295
 
                        node_kva_final = memblock_find_in_range(node_kva_target,
296
 
                                        ((u64)node_end_pfn[nid])<<PAGE_SHIFT,
297
 
                                                ((u64)size)<<PAGE_SHIFT,
298
 
                                                LARGE_PAGE_BYTES);
299
 
                        node_kva_target -= LARGE_PAGE_BYTES;
300
 
                } while (node_kva_final == MEMBLOCK_ERROR &&
301
 
                         (node_kva_target>>PAGE_SHIFT) > (node_start_pfn[nid]));
302
 
 
303
 
                if (node_kva_final == MEMBLOCK_ERROR)
304
 
                        panic("Can not get kva ram\n");
305
 
 
306
 
                node_remap_size[nid] = size;
307
 
                node_remap_offset[nid] = reserve_pages;
308
 
                reserve_pages += size;
309
 
                printk(KERN_DEBUG "Reserving %ld pages of KVA for lmem_map of"
310
 
                                  " node %d at %llx\n",
311
 
                                size, nid, node_kva_final>>PAGE_SHIFT);
312
 
 
313
 
                /*
314
 
                 *  prevent kva address below max_low_pfn want it on system
315
 
                 *  with less memory later.
316
 
                 *  layout will be: KVA address , KVA RAM
317
 
                 *
318
 
                 *  we are supposed to only record the one less then max_low_pfn
319
 
                 *  but we could have some hole in high memory, and it will only
320
 
                 *  check page_is_ram(pfn) && !page_is_reserved_early(pfn) to decide
321
 
                 *  to use it as free.
322
 
                 *  So memblock_x86_reserve_range here, hope we don't run out of that array
323
 
                 */
324
 
                memblock_x86_reserve_range(node_kva_final,
325
 
                              node_kva_final+(((u64)size)<<PAGE_SHIFT),
326
 
                              "KVA RAM");
327
 
 
328
 
                node_remap_start_pfn[nid] = node_kva_final>>PAGE_SHIFT;
329
 
        }
330
 
        printk(KERN_INFO "Reserving total of %lx pages for numa KVA remap\n",
331
 
                        reserve_pages);
332
 
        return reserve_pages;
333
 
}
334
 
 
335
 
static void init_remap_allocator(int nid)
336
 
{
337
 
        node_remap_start_vaddr[nid] = pfn_to_kaddr(
338
 
                        kva_start_pfn + node_remap_offset[nid]);
339
 
        node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] +
340
 
                (node_remap_size[nid] * PAGE_SIZE);
341
 
        node_remap_alloc_vaddr[nid] = node_remap_start_vaddr[nid] +
342
 
                ALIGN(sizeof(pg_data_t), PAGE_SIZE);
343
 
 
344
 
        printk(KERN_DEBUG "node %d will remap to vaddr %08lx - %08lx\n", nid,
345
 
                (ulong) node_remap_start_vaddr[nid],
346
 
                (ulong) node_remap_end_vaddr[nid]);
347
 
}
348
 
 
349
 
void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
350
 
                                int acpi, int k8)
351
 
{
352
 
        int nid;
353
 
        long kva_target_pfn;
 
158
/**
 
159
 * init_alloc_remap - Initialize remap allocator for a NUMA node
 
160
 * @nid: NUMA node to initizlie remap allocator for
 
161
 *
 
162
 * NUMA nodes may end up without any lowmem.  As allocating pgdat and
 
163
 * memmap on a different node with lowmem is inefficient, a special
 
164
 * remap allocator is implemented which can be used by alloc_remap().
 
165
 *
 
166
 * For each node, the amount of memory which will be necessary for
 
167
 * pgdat and memmap is calculated and two memory areas of the size are
 
168
 * allocated - one in the node and the other in lowmem; then, the area
 
169
 * in the node is remapped to the lowmem area.
 
170
 *
 
171
 * As pgdat and memmap must be allocated in lowmem anyway, this
 
172
 * doesn't waste lowmem address space; however, the actual lowmem
 
173
 * which gets remapped over is wasted.  The amount shouldn't be
 
174
 * problematic on machines this feature will be used.
 
175
 *
 
176
 * Initialization failure isn't fatal.  alloc_remap() is used
 
177
 * opportunistically and the callers will fall back to other memory
 
178
 * allocation mechanisms on failure.
 
179
 */
 
180
void __init init_alloc_remap(int nid, u64 start, u64 end)
 
181
{
 
182
        unsigned long start_pfn = start >> PAGE_SHIFT;
 
183
        unsigned long end_pfn = end >> PAGE_SHIFT;
 
184
        unsigned long size, pfn;
 
185
        u64 node_pa, remap_pa;
 
186
        void *remap_va;
354
187
 
355
188
        /*
356
 
         * When mapping a NUMA machine we allocate the node_mem_map arrays
357
 
         * from node local memory.  They are then mapped directly into KVA
358
 
         * between zone normal and vmalloc space.  Calculate the size of
359
 
         * this space and use it to adjust the boundary between ZONE_NORMAL
360
 
         * and ZONE_HIGHMEM.
 
189
         * The acpi/srat node info can show hot-add memroy zones where
 
190
         * memory could be added but not currently present.
361
191
         */
362
 
 
363
 
        get_memcfg_numa();
364
 
 
365
 
        kva_pages = roundup(calculate_numa_remap_pages(), PTRS_PER_PTE);
366
 
 
367
 
        kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE);
368
 
        do {
369
 
                kva_start_pfn = memblock_find_in_range(kva_target_pfn<<PAGE_SHIFT,
370
 
                                        max_low_pfn<<PAGE_SHIFT,
371
 
                                        kva_pages<<PAGE_SHIFT,
372
 
                                        PTRS_PER_PTE<<PAGE_SHIFT) >> PAGE_SHIFT;
373
 
                kva_target_pfn -= PTRS_PER_PTE;
374
 
        } while (kva_start_pfn == MEMBLOCK_ERROR && kva_target_pfn > min_low_pfn);
375
 
 
376
 
        if (kva_start_pfn == MEMBLOCK_ERROR)
377
 
                panic("Can not get kva space\n");
378
 
 
379
 
        printk(KERN_INFO "kva_start_pfn ~ %lx max_low_pfn ~ %lx\n",
380
 
                kva_start_pfn, max_low_pfn);
381
 
        printk(KERN_INFO "max_pfn = %lx\n", max_pfn);
382
 
 
383
 
        /* avoid clash with initrd */
384
 
        memblock_x86_reserve_range(kva_start_pfn<<PAGE_SHIFT,
385
 
                      (kva_start_pfn + kva_pages)<<PAGE_SHIFT,
386
 
                     "KVA PG");
 
192
        printk(KERN_DEBUG "node %d pfn: [%lx - %lx]\n",
 
193
               nid, start_pfn, end_pfn);
 
194
 
 
195
        /* calculate the necessary space aligned to large page size */
 
196
        size = node_memmap_size_bytes(nid, start_pfn, end_pfn);
 
197
        size += ALIGN(sizeof(pg_data_t), PAGE_SIZE);
 
198
        size = ALIGN(size, LARGE_PAGE_BYTES);
 
199
 
 
200
        /* allocate node memory and the lowmem remap area */
 
201
        node_pa = memblock_find_in_range(start, end, size, LARGE_PAGE_BYTES);
 
202
        if (node_pa == MEMBLOCK_ERROR) {
 
203
                pr_warning("remap_alloc: failed to allocate %lu bytes for node %d\n",
 
204
                           size, nid);
 
205
                return;
 
206
        }
 
207
        memblock_x86_reserve_range(node_pa, node_pa + size, "KVA RAM");
 
208
 
 
209
        remap_pa = memblock_find_in_range(min_low_pfn << PAGE_SHIFT,
 
210
                                          max_low_pfn << PAGE_SHIFT,
 
211
                                          size, LARGE_PAGE_BYTES);
 
212
        if (remap_pa == MEMBLOCK_ERROR) {
 
213
                pr_warning("remap_alloc: failed to allocate %lu bytes remap area for node %d\n",
 
214
                           size, nid);
 
215
                memblock_x86_free_range(node_pa, node_pa + size);
 
216
                return;
 
217
        }
 
218
        memblock_x86_reserve_range(remap_pa, remap_pa + size, "KVA PG");
 
219
        remap_va = phys_to_virt(remap_pa);
 
220
 
 
221
        /* perform actual remap */
 
222
        for (pfn = 0; pfn < size >> PAGE_SHIFT; pfn += PTRS_PER_PTE)
 
223
                set_pmd_pfn((unsigned long)remap_va + (pfn << PAGE_SHIFT),
 
224
                            (node_pa >> PAGE_SHIFT) + pfn,
 
225
                            PAGE_KERNEL_LARGE);
 
226
 
 
227
        /* initialize remap allocator parameters */
 
228
        node_remap_start_pfn[nid] = node_pa >> PAGE_SHIFT;
 
229
        node_remap_start_vaddr[nid] = remap_va;
 
230
        node_remap_end_vaddr[nid] = remap_va + size;
 
231
        node_remap_alloc_vaddr[nid] = remap_va;
 
232
 
 
233
        printk(KERN_DEBUG "remap_alloc: node %d [%08llx-%08llx) -> [%p-%p)\n",
 
234
               nid, node_pa, node_pa + size, remap_va, remap_va + size);
 
235
}
 
236
 
 
237
void __init initmem_init(void)
 
238
{
 
239
        x86_numa_init();
 
240
 
387
241
#ifdef CONFIG_HIGHMEM
388
242
        highstart_pfn = highend_pfn = max_pfn;
389
243
        if (max_pfn > max_low_pfn)
403
257
 
404
258
        printk(KERN_DEBUG "Low memory ends at vaddr %08lx\n",
405
259
                        (ulong) pfn_to_kaddr(max_low_pfn));
406
 
        for_each_online_node(nid) {
407
 
                init_remap_allocator(nid);
408
 
 
409
 
                allocate_pgdat(nid);
410
 
        }
411
 
        remap_numa_kva();
412
260
 
413
261
        printk(KERN_DEBUG "High memory starts at vaddr %08lx\n",
414
262
                        (ulong) pfn_to_kaddr(highstart_pfn));
415
 
        for_each_online_node(nid)
416
 
                propagate_e820_map_node(nid);
417
 
 
418
 
        for_each_online_node(nid) {
419
 
                memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
420
 
                NODE_DATA(nid)->node_id = nid;
421
 
        }
422
263
 
423
264
        setup_bootmem_allocator();
424
265
}
425
 
 
426
 
#ifdef CONFIG_MEMORY_HOTPLUG
427
 
static int paddr_to_nid(u64 addr)
428
 
{
429
 
        int nid;
430
 
        unsigned long pfn = PFN_DOWN(addr);
431
 
 
432
 
        for_each_node(nid)
433
 
                if (node_start_pfn[nid] <= pfn &&
434
 
                    pfn < node_end_pfn[nid])
435
 
                        return nid;
436
 
 
437
 
        return -1;
438
 
}
439
 
 
440
 
/*
441
 
 * This function is used to ask node id BEFORE memmap and mem_section's
442
 
 * initialization (pfn_to_nid() can't be used yet).
443
 
 * If _PXM is not defined on ACPI's DSDT, node id must be found by this.
444
 
 */
445
 
int memory_add_physaddr_to_nid(u64 addr)
446
 
{
447
 
        int nid = paddr_to_nid(addr);
448
 
        return (nid >= 0) ? nid : 0;
449
 
}
450
 
 
451
 
EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
452
 
#endif
453