Abstract out the pte scanning loop that searches for anonymous pages to fault in. diff -prauN pgcl-2.5.70-bk13-2/mm/memory.c pgcl-2.5.70-bk13-3/mm/memory.c --- pgcl-2.5.70-bk13-2/mm/memory.c 2003-06-08 08:54:25.000000000 -0700 +++ pgcl-2.5.70-bk13-3/mm/memory.c 2003-06-08 09:24:21.000000000 -0700 @@ -1016,6 +1016,64 @@ static inline void break_cow(struct vm_a establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(pte))); } +static pte_t *fill_anonymizable_ptevec(struct vm_area_struct *vma, + pmd_t *pmd, pte_t *page_table, + pte_t *ptes[], unsigned long addr, + int write_access) +{ + unsigned long lo_vaddr, hi_vaddr, dn_vaddr, up_vaddr, + dn_subpfn, up_subpfn; + pte_t *up_pte, *dn_pte; + + lo_vaddr = max(addr & ~(PAGE_MMUCOUNT*PMD_SIZE - 1), vma->vm_start); + hi_vaddr = min(vma->vm_end, (addr + PAGE_MMUCOUNT*PMD_SIZE - 1) + & ~(PAGE_MMUCOUNT*PMD_SIZE - 1)); + dn_subpfn = 0; + up_subpfn = PAGE_MMUCOUNT - 1; + dn_vaddr = addr & MMUPAGE_MASK; + up_vaddr = MMUPAGE_ALIGN(addr + 1); + + pr_debug("vma->vm_start = 0x%lx, vma->vm_end = 0x%lx\n", + vma->vm_start, vma->vm_end); + pr_debug("lo_vaddr = 0x%lx, hi_vaddr = 0x%lx\n", lo_vaddr, hi_vaddr); + pr_debug("dn_vaddr = 0x%lx, up_vaddr = 0x%lx\n", dn_vaddr, up_vaddr); + pr_debug("starting PTE search loop\n"); + if (write_access) + page_table = dn_pte = pte_offset_map(pmd, dn_vaddr); + else + dn_pte = page_table; + up_pte = dn_pte + 1; + + do { + if (up_vaddr < hi_vaddr && up_subpfn > dn_subpfn) { + if (pte_none(*up_pte)) { + ptes[up_subpfn] = up_pte; + up_subpfn--; + } + up_vaddr += MMUPAGE_SIZE; + up_pte++; + } + + if (dn_vaddr >= lo_vaddr && dn_subpfn < up_subpfn) { + if (pte_none(*dn_pte)) { + ptes[dn_subpfn] = dn_pte; + dn_subpfn++; + } + dn_vaddr -= MMUPAGE_SIZE; + dn_pte--; + } + pr_debug("dn_vaddr = 0x%lx, up_vaddr = 0x%lx\n", + dn_vaddr, up_vaddr); + pr_debug("dn_subpfn = 0x%lx, up_subpfn = 0x%lx\n", + dn_subpfn, up_subpfn); + } while ((up_vaddr < hi_vaddr || dn_vaddr >= lo_vaddr) && + up_subpfn > dn_subpfn); + + pr_debug("finishing PTE search loop\n"); + pr_debug("starting PTE instantiation loop\n"); + return page_table; +} + /* * This routine handles present pages, when users try to write * to a shared page. It is done by copying the page to a new address @@ -1431,60 +1489,10 @@ do_anonymous_page(struct mm_struct *mm, clear_user_highpage(page, addr); } - lo_vaddr = max(addr & ~(PAGE_MMUCOUNT*PMD_SIZE - 1), vma->vm_start); - hi_vaddr = min(vma->vm_end, (addr + PAGE_MMUCOUNT*PMD_SIZE - 1) - & ~(PAGE_MMUCOUNT*PMD_SIZE - 1)); - dn_subpfn = 0; - up_subpfn = PAGE_MMUCOUNT - 1; - dn_vaddr = addr & MMUPAGE_MASK; - up_vaddr = MMUPAGE_ALIGN(addr + 1); - - pr_debug("vma->vm_start = 0x%lx, vma->vm_end = 0x%lx\n", - vma->vm_start, vma->vm_end); - pr_debug("lo_vaddr = 0x%lx, hi_vaddr = 0x%lx\n", lo_vaddr, hi_vaddr); - pr_debug("dn_vaddr = 0x%lx, up_vaddr = 0x%lx\n", dn_vaddr, up_vaddr); - - if (write_access) { - pr_debug("about to take mm->page_table_lock\n"); - if (spin_is_locked(&mm->page_table_lock)) - printk("hmm, I see a deadlock coming\n"); - spin_lock(&mm->page_table_lock); - } - - pr_debug("starting PTE search loop\n"); if (write_access) - page_table = dn_pte = pte_offset_map(pmd, dn_vaddr); - else - dn_pte = page_table; - up_pte = dn_pte + 1; - - do { - if (up_vaddr < hi_vaddr && up_subpfn > dn_subpfn) { - if (pte_none(*up_pte)) { - ptes[up_subpfn] = up_pte; - up_subpfn--; - } - up_vaddr += MMUPAGE_SIZE; - up_pte++; - } - - if (dn_vaddr >= lo_vaddr && dn_subpfn < up_subpfn) { - if (pte_none(*dn_pte)) { - ptes[dn_subpfn] = dn_pte; - dn_subpfn++; - } - dn_vaddr -= MMUPAGE_SIZE; - dn_pte--; - } - pr_debug("dn_vaddr = 0x%lx, up_vaddr = 0x%lx\n", - dn_vaddr, up_vaddr); - pr_debug("dn_subpfn = 0x%lx, up_subpfn = 0x%lx\n", - dn_subpfn, up_subpfn); - } while ((up_vaddr < hi_vaddr || dn_vaddr >= lo_vaddr) && - up_subpfn > dn_subpfn); - - pr_debug("finishing PTE search loop\n"); - pr_debug("starting PTE instantiation loop\n"); + spin_lock(&mm->page_table_lock); + page_table = fill_anonymizable_ptevec(vma, pmd, page_table, + ptes, addr, write_access); pfn = page_to_pfn(page); rss = 0;