diff -urN orig/arch/x86_64/mm/init.c work/arch/x86_64/mm/init.c --- orig/arch/x86_64/mm/init.c 2006-07-28 13:57:35.000000000 -0400 +++ work/arch/x86_64/mm/init.c 2006-07-28 14:38:53.000000000 -0400 @@ -252,9 +252,11 @@ static void __meminit phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end) { - int i; + int i = pmd_index(address); - for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) { + pmd = pmd + i; + + for (; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) { unsigned long entry; if (address >= end) { @@ -263,6 +265,11 @@ set_pmd(pmd, __pmd(0)); break; } + + if (pmd_val(*pmd)) { + printk (KERN_ERR "%s trying to trample pte entry \ + %08lx@%08lx\n",__func__,pmd_val(*pmd),address); + } entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address; entry &= __supported_pte_mask; set_pmd(pmd, __pmd(entry)); @@ -272,45 +279,42 @@ static void __meminit phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) { - pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address)); - - if (pmd_none(*pmd)) { - spin_lock(&init_mm.page_table_lock); - phys_pmd_init(pmd, address, end); - spin_unlock(&init_mm.page_table_lock); - __flush_tlb_all(); - } + pmd_t *pmd = pmd_offset(pud,0); + spin_lock(&init_mm.page_table_lock); + phys_pmd_init(pmd, address, end); + spin_unlock(&init_mm.page_table_lock); + __flush_tlb_all(); } static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) { - long i = pud_index(address); + int i = pud_index(address); pud = pud + i; - if (after_bootmem && pud_val(*pud)) { - phys_pmd_update(pud, address, end); - return; - } - - for (; i < PTRS_PER_PUD; pud++, i++) { + for (; i < PTRS_PER_PUD; pud++, i++, \ + address = (address & PUD_MASK) + PUD_SIZE ) { int map; - unsigned long paddr, pmd_phys; + unsigned long pmd_phys; pmd_t *pmd; - paddr = (address & PGDIR_MASK) + i*PUD_SIZE; - if (paddr >= end) + if (address >= end) break; - if (!after_bootmem && !e820_any_mapped(paddr, paddr+PUD_SIZE, 0)) { + if (!after_bootmem && !e820_any_mapped(address, address+PUD_SIZE, 0)) { set_pud(pud, __pud(0)); continue; } + if (pud_val(*pud)) { + phys_pmd_update(pud, address, end); + continue; + } + pmd = alloc_low_page(&map, &pmd_phys); spin_lock(&init_mm.page_table_lock); set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); - phys_pmd_init(pmd, paddr, end); + phys_pmd_init(pmd, address, end); spin_unlock(&init_mm.page_table_lock); unmap_low_page(map); }