# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Date 1166682991 -32400 # Node ID bddf36d06df6b8400f32875b772af3a410c03923 # Parent e4195cf98e69da255fa9705194a6b3c59d3337fd allocate contiguous_bitmap sparsely like virtual memmap. With dom0 memory assignment changed, memory might be sparse, so simple bitmap may waste too much memory. PATCHNAME: sparse_contiugous_bitmap Signed-off-by: Isaku Yamahata diff -r e4195cf98e69 -r bddf36d06df6 linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Wed Dec 20 22:06:59 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Thu Dec 21 15:36:31 2006 +0900 @@ -25,7 +25,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -56,13 +59,80 @@ static int p2m_expose_init(void); */ unsigned long *contiguous_bitmap; -void -contiguous_bitmap_init(unsigned long end_pfn) -{ - unsigned long size = (end_pfn + 2 * BITS_PER_LONG) >> 3; +#ifdef CONFIG_VIRTUAL_MEM_MAP +/* Following logic is stolen from create_mem_map_table() for virtual memmap*/ +static int +create_contiguous_bitmap(u64 start, u64 end, void *arg) +{ + unsigned long address, start_page, end_page; + unsigned long bitmap_start, bitmap_end; + unsigned char *bitmap; + int node; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + bitmap_start = (unsigned long)contiguous_bitmap + ((__pa(start) >> PAGE_SHIFT) >> 3); + bitmap_end = (unsigned long)contiguous_bitmap + (((__pa(end) >> PAGE_SHIFT) + 2 * BITS_PER_LONG) >> 3); + + start_page = bitmap_start & PAGE_MASK; + end_page = PAGE_ALIGN(bitmap_end); + node = paddr_to_nid(__pa(start)); + + bitmap = alloc_bootmem_pages_node(NODE_DATA(node), end_page - start_page); + BUG_ON(!bitmap); + memset(bitmap, 0, end_page - start_page); + + 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(bitmap + (address - start_page)) >> PAGE_SHIFT, + PAGE_KERNEL)); + } + return 0; +} +#endif + +static void +__contiguous_bitmap_init(unsigned long size) +{ contiguous_bitmap = alloc_bootmem_pages(size); BUG_ON(!contiguous_bitmap); memset(contiguous_bitmap, 0, size); +} + +void +contiguous_bitmap_init(unsigned long end_pfn) +{ + unsigned long size = (end_pfn + 2 * BITS_PER_LONG) >> 3; +#ifndef CONFIG_VIRTUAL_MEM_MAP + __contiguous_bitmap_init(size); +#else + unsigned long max_gap; + max_gap = 0; + efi_memmap_walk(find_largest_hole, (u64*)&max_gap); + if (max_gap < LARGE_GAP) { + __contiguous_bitmap_init(size); + } else { + unsigned long map_size = PAGE_ALIGN(size); + vmalloc_end -= map_size; + contiguous_bitmap = (unsigned long*)vmalloc_end; + efi_memmap_walk(create_contiguous_bitmap, NULL); + } +#endif } #if 0