sparse.c revision 29751f6991e845f7d002a6ae520bf996b38c8dcd
1d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft/*
2d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft * sparse memory mappings.
3d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft */
4d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft#include <linux/config.h>
5d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft#include <linux/mm.h>
6d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft#include <linux/mmzone.h>
7d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft#include <linux/bootmem.h>
8d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft#include <linux/module.h>
9d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft#include <asm/dma.h>
10d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft
11d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft/*
12d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft * Permanent SPARSEMEM data:
13d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft *
14d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft * 1) mem_section	- memory sections, mem_map's for valid memory
15d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft */
16d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroftstruct mem_section mem_section[NR_MEM_SECTIONS];
17d41dee369bff3b9dcb6328d4d822926c28cc2594Andy WhitcroftEXPORT_SYMBOL(mem_section);
18d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft
19d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft/* Record a memory area against a node. */
20d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroftvoid memory_present(int nid, unsigned long start, unsigned long end)
21d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft{
22d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	unsigned long pfn;
23d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft
24d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	start &= PAGE_SECTION_MASK;
25d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
26d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft		unsigned long section = pfn_to_section_nr(pfn);
27d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft		if (!mem_section[section].section_mem_map)
2829751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft			mem_section[section].section_mem_map = SECTION_MARKED_PRESENT;
29d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	}
30d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft}
31d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft
32d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft/*
33d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft * Only used by the i386 NUMA architecures, but relatively
34d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft * generic code.
35d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft */
36d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroftunsigned long __init node_memmap_size_bytes(int nid, unsigned long start_pfn,
37d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft						     unsigned long end_pfn)
38d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft{
39d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	unsigned long pfn;
40d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	unsigned long nr_pages = 0;
41d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft
42d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
43d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft		if (nid != early_pfn_to_nid(pfn))
44d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft			continue;
45d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft
46d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft		if (pfn_valid(pfn))
47d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft			nr_pages += PAGES_PER_SECTION;
48d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	}
49d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft
50d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	return nr_pages * sizeof(struct page);
51d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft}
52d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft
53d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft/*
5429751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft * Subtle, we encode the real pfn into the mem_map such that
5529751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft * the identity pfn - section_mem_map will return the actual
5629751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft * physical page frame number.
5729751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft */
5829751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroftstatic unsigned long sparse_encode_mem_map(struct page *mem_map, unsigned long pnum)
5929751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft{
6029751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	return (unsigned long)(mem_map - (section_nr_to_pfn(pnum)));
6129751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft}
6229751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
6329751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft/*
6429751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft * We need this if we ever free the mem_maps.  While not implemented yet,
6529751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft * this function is included for parity with its sibling.
6629751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft */
6729751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroftstatic __attribute((unused))
6829751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroftstruct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pnum)
6929751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft{
7029751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	return ((struct page *)coded_mem_map) + section_nr_to_pfn(pnum);
7129751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft}
7229751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
7329751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroftstatic int sparse_init_one_section(struct mem_section *ms,
7429751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft		unsigned long pnum, struct page *mem_map)
7529751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft{
7629751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	if (!valid_section(ms))
7729751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft		return -EINVAL;
7829751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
7929751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum);
8029751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
8129751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	return 1;
8229751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft}
8329751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
8429751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroftstatic struct page *sparse_early_mem_map_alloc(unsigned long pnum)
8529751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft{
8629751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	struct page *map;
8729751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	int nid = early_pfn_to_nid(section_nr_to_pfn(pnum));
8829751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
8929751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION);
9029751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	if (map)
9129751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft		return map;
9229751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
9329751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	map = alloc_bootmem_node(NODE_DATA(nid),
9429751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft			sizeof(struct page) * PAGES_PER_SECTION);
9529751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	if (map)
9629751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft		return map;
9729751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
9829751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__);
9929751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	mem_section[pnum].section_mem_map = 0;
10029751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	return NULL;
10129751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft}
10229751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
10329751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft/*
104d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft * Allocate the accumulated non-linear sections, allocate a mem_map
105d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft * for each and record the physical to section mapping.
106d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft */
107d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroftvoid sparse_init(void)
108d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft{
109d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	unsigned long pnum;
110d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	struct page *map;
111d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft
112d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
11329751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft		if (!valid_section_nr(pnum))
114d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft			continue;
115d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft
11629751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft		map = sparse_early_mem_map_alloc(pnum);
11729751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft		if (map)
11829751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft			sparse_init_one_section(&mem_section[pnum], pnum, map);
119d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft	}
120d41dee369bff3b9dcb6328d4d822926c28cc2594Andy Whitcroft}
12129751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
12229751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft/*
12329751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft * returns the number of sections whose mem_maps were properly
12429751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft * set.  If this is <=0, then that means that the passed-in
12529751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft * map was not consumed and must be freed.
12629751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft */
12729751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroftint sparse_add_one_section(unsigned long start_pfn, int nr_pages, struct page *map)
12829751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft{
12929751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	struct mem_section *ms = __pfn_to_section(start_pfn);
13029751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
13129751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	if (ms->section_mem_map & SECTION_MARKED_PRESENT)
13229751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft		return -EEXIST;
13329751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
13429751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	ms->section_mem_map |= SECTION_MARKED_PRESENT;
13529751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft
13629751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft	return sparse_init_one_section(ms, pfn_to_section_nr(start_pfn), map);
13729751f6991e845f7d002a6ae520bf996b38c8dcdAndy Whitcroft}
138