diff -ur linux-2.4.18.org/arch/i386/kernel/process.c linux-2.4.18/arch/i386/kernel/process.c --- linux-2.4.18.org/arch/i386/kernel/process.c Mon Feb 25 11:37:53 2002 +++ linux-2.4.18/arch/i386/kernel/process.c Tue May 21 11:21:07 2002 @@ -311,7 +311,7 @@ /* * Use `swapper_pg_dir' as our page directory. */ - asm volatile("movl %0,%%cr3": :"r" (__pa(swapper_pg_dir))); + load_cr3(swapper_pg_dir); /* Write 0x1234 to absolute memory location 0x472. The BIOS reads this on booting to tell it to "Bypass memory test (also warm diff -ur linux-2.4.18.org/arch/i386/kernel/smp.c linux-2.4.18/arch/i386/kernel/smp.c --- linux-2.4.18.org/arch/i386/kernel/smp.c Fri Dec 21 09:41:53 2001 +++ linux-2.4.18/arch/i386/kernel/smp.c Tue May 21 18:19:55 2002 @@ -298,12 +298,16 @@ /* * We cannot call mmdrop() because we are in interrupt context, * instead update mm->cpu_vm_mask. + * + * We need to reload %cr3 since the page tables may be going + * away from under us.. */ static void inline leave_mm (unsigned long cpu) { if (cpu_tlbstate[cpu].state == TLBSTATE_OK) BUG(); clear_bit(cpu, &cpu_tlbstate[cpu].active_mm->cpu_vm_mask); + load_cr3(swapper_pg_dir); } /* diff -ur linux-2.4.18.org/arch/i386/mm/init.c linux-2.4.18/arch/i386/mm/init.c --- linux-2.4.18.org/arch/i386/mm/init.c Fri Dec 21 09:41:53 2001 +++ linux-2.4.18/arch/i386/mm/init.c Tue May 21 11:21:07 2002 @@ -334,7 +334,7 @@ { pagetable_init(); - __asm__( "movl %%ecx,%%cr3\n" ::"c"(__pa(swapper_pg_dir))); + load_cr3(swapper_pg_dir); #if CONFIG_X86_PAE /* diff -ur linux-2.4.18.org/include/asm-generic/tlb.h linux-2.4.18/include/asm-generic/tlb.h --- linux-2.4.18.org/include/asm-generic/tlb.h Fri Sep 14 08:41:04 2001 +++ linux-2.4.18/include/asm-generic/tlb.h Tue May 21 11:21:07 2002 @@ -55,8 +55,9 @@ #define tlb_remove_page(ctxp, pte, addr) do {\ /* Handle the common case fast, first. */\ if ((ctxp)->nr == ~0UL) {\ - __free_pte(*(pte));\ - pte_clear((pte));\ + pte_t __pte = *(pte);\ + pte_clear(pte);\ + __free_pte(__pte);\ break;\ }\ if (!(ctxp)->nr) \ diff -ur linux-2.4.18.org/include/asm-i386/mmu_context.h linux-2.4.18/include/asm-i386/mmu_context.h --- linux-2.4.18.org/include/asm-i386/mmu_context.h Thu Nov 22 11:46:19 2001 +++ linux-2.4.18/include/asm-i386/mmu_context.h Tue May 21 12:09:51 2002 @@ -42,7 +42,7 @@ set_bit(cpu, &next->cpu_vm_mask); set_bit(cpu, &next->context.cpuvalid); /* Re-load page tables */ - asm volatile("movl %0,%%cr3": :"r" (__pa(next->pgd))); + load_cr3(next->pgd); } #ifdef CONFIG_SMP else { @@ -51,9 +51,9 @@ BUG(); if(!test_and_set_bit(cpu, &next->cpu_vm_mask)) { /* We were in lazy tlb mode and leave_mm disabled - * tlb flush IPI delivery. We must flush our tlb. + * tlb flush IPI delivery. We must reload %cr3. */ - local_flush_tlb(); + load_cr3(next->pgd); } if (!test_and_set_bit(cpu, &next->context.cpuvalid)) load_LDT(next); diff -ur linux-2.4.18.org/include/asm-i386/pgalloc.h linux-2.4.18/include/asm-i386/pgalloc.h --- linux-2.4.18.org/include/asm-i386/pgalloc.h Fri Dec 21 09:42:03 2001 +++ linux-2.4.18/include/asm-i386/pgalloc.h Tue May 21 12:09:51 2002 @@ -139,7 +139,7 @@ free_page((unsigned long)pte); } -#define pte_free(pte) pte_free_slow(pte) +#define pte_free(pte) pte_free_fast(pte) #define pgd_free(pgd) free_pgd_slow(pgd) #define pgd_alloc(mm) get_pgd_fast() @@ -227,13 +227,12 @@ }; extern struct tlb_state cpu_tlbstate[NR_CPUS]; - -#endif +#endif /* CONFIG_SMP */ static inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end) { - /* i386 does not keep any page table caches in TLB */ + flush_tlb_mm(mm); } #endif /* _I386_PGALLOC_H */ diff -ur linux-2.4.18.org/include/asm-i386/processor.h linux-2.4.18/include/asm-i386/processor.h --- linux-2.4.18.org/include/asm-i386/processor.h Thu Nov 22 11:46:19 2001 +++ linux-2.4.18/include/asm-i386/processor.h Tue May 21 12:09:51 2002 @@ -190,6 +190,9 @@ #define X86_CR4_OSFXSR 0x0200 /* enable fast FPU save and restore */ #define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */ +#define load_cr3(pgdir) \ + asm volatile("movl %0,%%cr3": :"r" (__pa(pgdir))); + /* * Save the cr4 feature set we're using (ie * Pentium 4MB enable and PPro Global page diff -ur linux-2.4.18.org/mm/memory.c linux-2.4.18/mm/memory.c --- linux-2.4.18.org/mm/memory.c Mon Feb 25 11:38:13 2002 +++ linux-2.4.18/mm/memory.c Tue May 21 11:21:07 2002 @@ -144,6 +144,7 @@ void clear_page_tables(struct mm_struct *mm, unsigned long first, int nr) { pgd_t * page_dir = mm->pgd; + unsigned long last = first + nr; spin_lock(&mm->page_table_lock); page_dir += first; @@ -153,6 +154,8 @@ } while (--nr); spin_unlock(&mm->page_table_lock); + flush_tlb_pgtables(mm, first * PGDIR_SIZE, last * PGDIR_SIZE); + /* keep the page table cache within bounds */ check_pgt_cache(); } diff -ur linux-2.4.18.org/mm/mmap.c linux-2.4.18/mm/mmap.c --- linux-2.4.18.org/mm/mmap.c Mon Feb 25 11:38:14 2002 +++ linux-2.4.18/mm/mmap.c Tue May 21 18:55:54 2002 @@ -885,7 +885,6 @@ end_index = pgd_index(last); if (end_index > start_index) { clear_page_tables(mm, start_index, end_index - start_index); - flush_tlb_pgtables(mm, first & PGDIR_MASK, last & PGDIR_MASK); } }