--- linux/mm/memory.c.save Mon Jun 4 17:55:58 2001 +++ linux/mm/memory.c Mon Jun 4 18:27:35 2001 @@ -271,45 +271,40 @@ } } -static inline int zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long address, unsigned long size) +static inline int zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long address, unsigned long end) { - unsigned long offset; pte_t * ptep; int freed = 0; if (pmd_none(*pmd)) return 0; if (pmd_bad(*pmd)) { + printk("debug: pmd=%p, address = %08lx end= %08lx\n", pmd, address, end); pmd_ERROR(*pmd); pmd_clear(pmd); return 0; } ptep = pte_offset(pmd, address); - offset = address & ~PMD_MASK; - if (offset + size > PMD_SIZE) - size = PMD_SIZE - offset; - size &= PAGE_MASK; - for (offset=0; offset < size; ptep++, offset += PAGE_SIZE) { + do { pte_t pte = *ptep; - if (pte_none(pte)) - continue; if (pte_present(pte)) { freed ++; /* This will eventually call __free_pte on the pte. */ - tlb_remove_page(tlb, ptep, address + offset); - } else { + tlb_remove_page(tlb, ptep, address); + } else if (!pte_none(pte)) { swap_free(pte_to_swp_entry(pte)); pte_clear(ptep); } - } + address += PAGE_SIZE; + ptep++; + } while ((address & PAGE_MASK & (PMD_SIZE - 1)) && (address < end)); return freed; } -static inline int zap_pmd_range(mmu_gather_t *tlb, pgd_t * dir, unsigned long address, unsigned long size) +static inline int zap_pmd_range(mmu_gather_t *tlb, pgd_t * dir, unsigned long address, unsigned long end) { pmd_t * pmd; - unsigned long end; int freed; if (pgd_none(*dir)) @@ -320,16 +315,12 @@ return 0; } pmd = pmd_offset(dir, address); - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; freed = 0; do { - freed += zap_pte_range(tlb, pmd, address, end - address); + freed += zap_pte_range(tlb, pmd, address, end); address = (address + PMD_SIZE) & PMD_MASK; pmd++; - } while (address < end); + } while ((address & (PGDIR_SIZE - 1)) && (address < end)); return freed; } @@ -357,9 +348,10 @@ spin_lock(&mm->page_table_lock); flush_cache_range(mm, address, end); tlb = tlb_gather_mmu(mm); + address &= PAGE_MASK; do { - freed += zap_pmd_range(tlb, dir, address, end - address); + freed += zap_pmd_range(tlb, dir, address, end); address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++; } while (address && (address < end));