Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 185131
b: refs/heads/master
c: 9bdac91
h: refs/heads/master
i:
  185129: 77ca9c5
  185127: b1520df
v: v3
  • Loading branch information
Yinghai Lu authored and H. Peter Anvin committed Feb 12, 2010
1 parent 398a55e commit de4712a
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a4322e1bad91fbca27056fc38d2cbca3f1eae0cf
refs/heads/master: 9bdac914240759457175ac0d6529a37d2820bc4d
2 changes: 1 addition & 1 deletion trunk/arch/x86/mm/init_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,7 @@ vmemmap_populate(struct page *start_page, unsigned long size, int node)
if (pmd_none(*pmd)) {
pte_t entry;

p = vmemmap_alloc_block(PMD_SIZE, node);
p = vmemmap_alloc_block_buf(PMD_SIZE, node);
if (!p)
return -ENOMEM;

Expand Down
7 changes: 7 additions & 0 deletions trunk/include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1326,12 +1326,19 @@ extern int randomize_va_space;
const char * arch_vma_name(struct vm_area_struct *vma);
void print_vma_addr(char *prefix, unsigned long rip);

void sparse_mem_maps_populate_node(struct page **map_map,
unsigned long pnum_begin,
unsigned long pnum_end,
unsigned long map_count,
int nodeid);

struct page *sparse_mem_map_populate(unsigned long pnum, int nid);
pgd_t *vmemmap_pgd_populate(unsigned long addr, int node);
pud_t *vmemmap_pud_populate(pgd_t *pgd, unsigned long addr, int node);
pmd_t *vmemmap_pmd_populate(pud_t *pud, unsigned long addr, int node);
pte_t *vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node);
void *vmemmap_alloc_block(unsigned long size, int node);
void *vmemmap_alloc_block_buf(unsigned long size, int node);
void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
int vmemmap_populate_basepages(struct page *start_page,
unsigned long pages, int node);
Expand Down
4 changes: 4 additions & 0 deletions trunk/mm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ config SPARSEMEM_EXTREME
config SPARSEMEM_VMEMMAP_ENABLE
bool

config SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
def_bool y
depends on SPARSEMEM && X86_64

config SPARSEMEM_VMEMMAP
bool "Sparse Memory virtual memmap"
depends on SPARSEMEM && SPARSEMEM_VMEMMAP_ENABLE
Expand Down
74 changes: 73 additions & 1 deletion trunk/mm/sparse-vmemmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ static void * __init_refok __earlyonly_bootmem_alloc(int node,
return __alloc_bootmem_node_high(NODE_DATA(node), size, align, goal);
}

static void *vmemmap_buf;
static void *vmemmap_buf_end;

void * __meminit vmemmap_alloc_block(unsigned long size, int node)
{
Expand All @@ -64,6 +66,24 @@ void * __meminit vmemmap_alloc_block(unsigned long size, int node)
__pa(MAX_DMA_ADDRESS));
}

/* need to make sure size is all the same during early stage */
void * __meminit vmemmap_alloc_block_buf(unsigned long size, int node)
{
void *ptr;

if (!vmemmap_buf)
return vmemmap_alloc_block(size, node);

/* take the from buf */
ptr = (void *)ALIGN((unsigned long)vmemmap_buf, size);
if (ptr + size > vmemmap_buf_end)
return vmemmap_alloc_block(size, node);

vmemmap_buf = ptr + size;

return ptr;
}

void __meminit vmemmap_verify(pte_t *pte, int node,
unsigned long start, unsigned long end)
{
Expand All @@ -80,7 +100,7 @@ pte_t * __meminit vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node)
pte_t *pte = pte_offset_kernel(pmd, addr);
if (pte_none(*pte)) {
pte_t entry;
void *p = vmemmap_alloc_block(PAGE_SIZE, node);
void *p = vmemmap_alloc_block_buf(PAGE_SIZE, node);
if (!p)
return NULL;
entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL);
Expand Down Expand Up @@ -163,3 +183,55 @@ struct page * __meminit sparse_mem_map_populate(unsigned long pnum, int nid)

return map;
}

void __init sparse_mem_maps_populate_node(struct page **map_map,
unsigned long pnum_begin,
unsigned long pnum_end,
unsigned long map_count, int nodeid)
{
unsigned long pnum;
unsigned long size = sizeof(struct page) * PAGES_PER_SECTION;
void *vmemmap_buf_start;

size = ALIGN(size, PMD_SIZE);
vmemmap_buf_start = __earlyonly_bootmem_alloc(nodeid, size * map_count,
PMD_SIZE, __pa(MAX_DMA_ADDRESS));

if (vmemmap_buf_start) {
vmemmap_buf = vmemmap_buf_start;
vmemmap_buf_end = vmemmap_buf_start + size * map_count;
}

for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
struct mem_section *ms;

if (!present_section_nr(pnum))
continue;

map_map[pnum] = sparse_mem_map_populate(pnum, nodeid);
if (map_map[pnum])
continue;
ms = __nr_to_section(pnum);
printk(KERN_ERR "%s: sparsemem memory map backing failed "
"some memory will not be available.\n", __func__);
ms->section_mem_map = 0;
}

if (vmemmap_buf_start) {
/* need to free left buf */
#ifdef CONFIG_NO_BOOTMEM
free_early(__pa(vmemmap_buf_start), __pa(vmemmap_buf_end));
if (vmemmap_buf_start < vmemmap_buf) {
char name[15];

snprintf(name, sizeof(name), "MEMMAP %d", nodeid);
reserve_early_without_check(__pa(vmemmap_buf_start),
__pa(vmemmap_buf), name);
}
#else
free_bootmem(__pa(vmemmap_buf), vmemmap_buf_end - vmemmap_buf);
#endif
vmemmap_buf = NULL;
vmemmap_buf_end = NULL;
}
}
111 changes: 110 additions & 1 deletion trunk/mm/sparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,65 @@ struct page __init *sparse_mem_map_populate(unsigned long pnum, int nid)
PAGE_ALIGN(sizeof(struct page) * PAGES_PER_SECTION));
return map;
}
void __init sparse_mem_maps_populate_node(struct page **map_map,
unsigned long pnum_begin,
unsigned long pnum_end,
unsigned long map_count, int nodeid)
{
void *map;
unsigned long pnum;
unsigned long size = sizeof(struct page) * PAGES_PER_SECTION;

map = alloc_remap(nodeid, size * map_count);
if (map) {
for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
if (!present_section_nr(pnum))
continue;
map_map[pnum] = map;
map += size;
}
return;
}

size = PAGE_ALIGN(size);
map = alloc_bootmem_pages_node(NODE_DATA(nodeid), size * map_count);
if (map) {
for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
if (!present_section_nr(pnum))
continue;
map_map[pnum] = map;
map += size;
}
return;
}

/* fallback */
for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
struct mem_section *ms;

if (!present_section_nr(pnum))
continue;
map_map[pnum] = sparse_mem_map_populate(pnum, nodeid);
if (map_map[pnum])
continue;
ms = __nr_to_section(pnum);
printk(KERN_ERR "%s: sparsemem memory map backing failed "
"some memory will not be available.\n", __func__);
ms->section_mem_map = 0;
}
}
#endif /* !CONFIG_SPARSEMEM_VMEMMAP */

static void __init sparse_early_mem_maps_alloc_node(struct page **map_map,
unsigned long pnum_begin,
unsigned long pnum_end,
unsigned long map_count, int nodeid)
{
sparse_mem_maps_populate_node(map_map, pnum_begin, pnum_end,
map_count, nodeid);
}

#ifndef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
{
struct page *map;
Expand All @@ -407,6 +464,7 @@ static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
ms->section_mem_map = 0;
return NULL;
}
#endif

void __attribute__((weak)) __meminit vmemmap_populate_print_last(void)
{
Expand All @@ -420,12 +478,14 @@ void __init sparse_init(void)
{
unsigned long pnum;
struct page *map;
struct page **map_map;
unsigned long *usemap;
unsigned long **usemap_map;
int size;
int size, size2;
int nodeid_begin = 0;
unsigned long pnum_begin = 0;
unsigned long usemap_count;
unsigned long map_count;

/*
* map is using big page (aka 2M in x86 64 bit)
Expand Down Expand Up @@ -478,6 +538,48 @@ void __init sparse_init(void)
sparse_early_usemaps_alloc_node(usemap_map, pnum_begin, NR_MEM_SECTIONS,
usemap_count, nodeid_begin);

#ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
size2 = sizeof(struct page *) * NR_MEM_SECTIONS;
map_map = alloc_bootmem(size2);
if (!map_map)
panic("can not allocate map_map\n");

for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
struct mem_section *ms;

if (!present_section_nr(pnum))
continue;
ms = __nr_to_section(pnum);
nodeid_begin = sparse_early_nid(ms);
pnum_begin = pnum;
break;
}
map_count = 1;
for (pnum = pnum_begin + 1; pnum < NR_MEM_SECTIONS; pnum++) {
struct mem_section *ms;
int nodeid;

if (!present_section_nr(pnum))
continue;
ms = __nr_to_section(pnum);
nodeid = sparse_early_nid(ms);
if (nodeid == nodeid_begin) {
map_count++;
continue;
}
/* ok, we need to take cake of from pnum_begin to pnum - 1*/
sparse_early_mem_maps_alloc_node(map_map, pnum_begin, pnum,
map_count, nodeid_begin);
/* new start, update count etc*/
nodeid_begin = nodeid;
pnum_begin = pnum;
map_count = 1;
}
/* ok, last chunk */
sparse_early_mem_maps_alloc_node(map_map, pnum_begin, NR_MEM_SECTIONS,
map_count, nodeid_begin);
#endif

for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
if (!present_section_nr(pnum))
continue;
Expand All @@ -486,7 +588,11 @@ void __init sparse_init(void)
if (!usemap)
continue;

#ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
map = map_map[pnum];
#else
map = sparse_early_mem_map_alloc(pnum);
#endif
if (!map)
continue;

Expand All @@ -496,6 +602,9 @@ void __init sparse_init(void)

vmemmap_populate_print_last();

#ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
free_bootmem(__pa(map_map), size2);
#endif
free_bootmem(__pa(usemap_map), size);
}

Expand Down

0 comments on commit de4712a

Please sign in to comment.