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