--- 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));
