Genericize IA64 virtual memory map population function Provide a function populate_vmmmap that can be used to populate the Virtual memory map during bootup. This function is limited to early boot and it here only supports VMAP_PAGE_SIZE == PAGE_SIZE. Signed-off-by: Christoph Lameter Index: linux-2.6.18-mm3/mm/bootmem.c =================================================================== --- linux-2.6.18-mm3.orig/mm/bootmem.c 2006-10-04 21:48:59.889553051 -0500 +++ linux-2.6.18-mm3/mm/bootmem.c 2006-10-04 22:18:47.757607451 -0500 @@ -16,6 +16,7 @@ #include #include #include +#include #include "internal.h" @@ -485,3 +486,66 @@ void * __init __alloc_bootmem_low_node(p return __alloc_bootmem_core(pgdat->bdata, size, align, goal, ARCH_LOW_ADDRESS_LIMIT); } + +#if defined(CONFIG_VIRTUAL_MEM_MAP) && !defined(ARCH_HAS_POPULATE_VMEMMAP) +/* + * Generic VMMAP populate function. This function is only useful + * at boot time. In order to populate more segments of the + * virtual memory map later (memory hotplug) another function would need + * to be supplied. + * + * This function only supports the case that VMAP_PAGE_SIZE == PAGE_SIZE + * and is suitable to share the page table with VMALLOC which supports the + * same page size. + * + * Note that using regular pages for mapping the virtual memory map + * may cause TLB pressure on architectures with small page size (4k?). + * If an architecture has a small page size but also allows higher + * page sizes then arch code should define its own populate_virtual_memmap() + * function and support the larger page size. + */ + +#if VMEMMAP_PAGE_SIZE != PAGE_SIZE +#error "Generic populate_virtual_memmap() function only supports PAGE_SIZE!" +#endif + +void __init populate_virtual_memmap(int nid, unsigned long start_pfn, + unsigned long end_pfn) +{ + unsigned long addr, start, end; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + struct pglist_data *pgdat = NODE_DATA(nid); + + start = (unsigned long)&mem_map[start_pfn] & ~(VMEMMAP_PAGE_SIZE - 1); + end = ALIGN((unsigned long)&mem_map[end_pfn], VMEMMAP_PAGE_SIZE); + + for (addr = start; addr < end; addr += VMEMMAP_PAGE_SIZE) { + + pgd = pgd_offset_k(addr); + if (pgd_none(*pgd)) + pgd_populate(&init_mm, pgd, + alloc_bootmem_pages_node(pgdat, PAGE_SIZE)); + + pud = pud_offset(pgd, addr); + if (pud_none(*pud)) + pud_populate(&init_mm, pud, + alloc_bootmem_pages_node(pgdat, PAGE_SIZE)); + + pmd = pmd_offset(pud, addr); + if (pmd_none(*pmd)) + pmd_populate_kernel(&init_mm, pmd, + alloc_bootmem_pages_node(pgdat, PAGE_SIZE)); + + pte = pte_offset_kernel(pmd, addr); + if (pte_none(*pte)) + set_pte(pte, pfn_pte(__pa( + alloc_bootmem_pages_node(pgdat, + VMEMMAP_PAGE_SIZE)) >> PAGE_SHIFT, + PAGE_KERNEL)); + } +} +#endif + Index: linux-2.6.18-mm3/arch/ia64/mm/init.c =================================================================== --- linux-2.6.18-mm3.orig/arch/ia64/mm/init.c 2006-10-04 21:51:09.545114056 -0500 +++ linux-2.6.18-mm3/arch/ia64/mm/init.c 2006-10-04 22:02:33.375776717 -0500 @@ -472,39 +472,10 @@ retry_pte: int __init create_mem_map_page_table (u64 start, u64 end, void *arg) { - unsigned long address, start_page, end_page; - struct page *map_start, *map_end; - int node; - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; + populate_virtual_memmap(paddr_to_nid(__pa(start)), + __pa(start) >> PAGE_SHIFT, + __pa(end) >> PAGE_SHIFT); - map_start = mem_map + (__pa(start) >> PAGE_SHIFT); - map_end = mem_map + (__pa(end) >> PAGE_SHIFT); - - start_page = (unsigned long) map_start & PAGE_MASK; - end_page = PAGE_ALIGN((unsigned long) map_end); - node = paddr_to_nid(__pa(start)); - - for (address = start_page; address < end_page; address += PAGE_SIZE) { - pgd = pgd_offset_k(address); - if (pgd_none(*pgd)) - pgd_populate(&init_mm, pgd, alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE)); - pud = pud_offset(pgd, address); - - if (pud_none(*pud)) - pud_populate(&init_mm, pud, alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE)); - pmd = pmd_offset(pud, address); - - if (pmd_none(*pmd)) - pmd_populate_kernel(&init_mm, pmd, alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE)); - pte = pte_offset_kernel(pmd, address); - - if (pte_none(*pte)) - set_pte(pte, pfn_pte(__pa(alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE)) >> PAGE_SHIFT, - PAGE_KERNEL)); - } return 0; } Index: linux-2.6.18-mm3/include/linux/bootmem.h =================================================================== --- linux-2.6.18-mm3.orig/include/linux/bootmem.h 2006-10-04 21:48:59.912992544 -0500 +++ linux-2.6.18-mm3/include/linux/bootmem.h 2006-10-04 22:02:37.930852056 -0500 @@ -132,5 +132,6 @@ extern void *alloc_large_system_hash(con #endif extern int hashdist; /* Distribute hashes across NUMA nodes? */ - +extern void populate_virtual_memmap(int nid, unsigned long start_pfn, + unsigned long end_pfn); #endif /* _LINUX_BOOTMEM_H */