2 * sparse memory mappings.
4 #include <linux/config.h>
6 #include <linux/mmzone.h>
7 #include <linux/bootmem.h>
8 #include <linux/module.h>
12 * Permanent SPARSEMEM data:
14 * 1) mem_section - memory sections, mem_map's for valid memory
16 struct mem_section mem_section
[NR_MEM_SECTIONS
];
17 EXPORT_SYMBOL(mem_section
);
19 /* Record a memory area against a node. */
20 void memory_present(int nid
, unsigned long start
, unsigned long end
)
24 start
&= PAGE_SECTION_MASK
;
25 for (pfn
= start
; pfn
< end
; pfn
+= PAGES_PER_SECTION
) {
26 unsigned long section
= pfn_to_section_nr(pfn
);
27 if (!mem_section
[section
].section_mem_map
)
28 mem_section
[section
].section_mem_map
= (void *) -1;
33 * Only used by the i386 NUMA architecures, but relatively
36 unsigned long __init
node_memmap_size_bytes(int nid
, unsigned long start_pfn
,
37 unsigned long end_pfn
)
40 unsigned long nr_pages
= 0;
42 for (pfn
= start_pfn
; pfn
< end_pfn
; pfn
+= PAGES_PER_SECTION
) {
43 if (nid
!= early_pfn_to_nid(pfn
))
47 nr_pages
+= PAGES_PER_SECTION
;
50 return nr_pages
* sizeof(struct page
);
54 * Allocate the accumulated non-linear sections, allocate a mem_map
55 * for each and record the physical to section mapping.
57 void sparse_init(void)
63 for (pnum
= 0; pnum
< NR_MEM_SECTIONS
; pnum
++) {
64 if (!mem_section
[pnum
].section_mem_map
)
67 nid
= early_pfn_to_nid(section_nr_to_pfn(pnum
));
68 map
= alloc_remap(nid
, sizeof(struct page
) * PAGES_PER_SECTION
);
70 map
= alloc_bootmem_node(NODE_DATA(nid
),
71 sizeof(struct page
) * PAGES_PER_SECTION
);
73 mem_section
[pnum
].section_mem_map
= 0;
78 * Subtle, we encode the real pfn into the mem_map such that
79 * the identity pfn - section_mem_map will return the actual
80 * physical page frame number.
82 mem_section
[pnum
].section_mem_map
= map
-
83 section_nr_to_pfn(pnum
);