Index: arch/mips/mm/tlb-r3k.c =================================================================== RCS file: /home/cvs/linux/arch/mips/mm/tlb-r3k.c,v retrieving revision 1.16 diff -u -r1.16 tlb-r3k.c --- arch/mips/mm/tlb-r3k.c 17 Jan 2003 04:23:08 -0000 1.16 +++ arch/mips/mm/tlb-r3k.c 6 Feb 2003 23:02:05 -0000 @@ -69,16 +69,10 @@ int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { - unsigned long flags; - #ifdef DEBUG_TLB printk("[tlbmm<%lu>]", (unsigned long)cpu_context(cpu, mm)); #endif - local_irq_save(flags); - get_new_mmu_context(mm, cpu); - if (mm == current->active_mm) - write_c0_entryhi(cpu_context(cpu, mm) & ASID_MASK); - local_irq_restore(flags); + drop_mmu_context(mm, cpu); } } @@ -120,9 +114,7 @@ } write_c0_entryhi(oldpid); } else { - get_new_mmu_context(mm, smp_processor_id()); - if (mm == current->active_mm) - write_c0_entryhi(cpu_context(cpu, mm) & ASID_MASK); + drop_mmu_context(mm, cpu); } local_irq_restore(flags); } Index: arch/mips/mm/tlb-r4k.c =================================================================== RCS file: /home/cvs/linux/arch/mips/mm/tlb-r4k.c,v retrieving revision 1.19 diff -u -r1.19 tlb-r4k.c --- arch/mips/mm/tlb-r4k.c 17 Jan 2003 04:23:08 -0000 1.19 +++ arch/mips/mm/tlb-r4k.c 6 Feb 2003 23:02:05 -0000 @@ -76,16 +76,10 @@ int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { - unsigned long flags; - #ifdef DEBUG_TLB printk("[tlbmm<%d>]", cpu_context(cpu, mm)); #endif - local_irq_save(flags); - get_new_mmu_context(mm, smp_processor_id()); - if (mm == current->active_mm) - write_c0_entryhi(cpu_context(cpu, mm) & ASID_MASK); - local_irq_restore(flags); + drop_mmu_context(mm,cpu); } } @@ -134,9 +128,7 @@ } write_c0_entryhi(oldpid); } else { - get_new_mmu_context(mm, smp_processor_id()); - if (mm == current->active_mm) - write_c0_entryhi(cpu_context(cpu, mm) & ASID_MASK); + drop_mmu_context(mm, cpu); } local_irq_restore(flags); } Index: arch/mips/mm/tlb-sb1.c =================================================================== RCS file: /home/cvs/linux/arch/mips/mm/tlb-sb1.c,v retrieving revision 1.21 diff -u -r1.21 tlb-sb1.c --- arch/mips/mm/tlb-sb1.c 2 Dec 2002 00:27:47 -0000 1.21 +++ arch/mips/mm/tlb-sb1.c 6 Feb 2003 23:02:05 -0000 @@ -172,15 +172,7 @@ } write_c0_entryhi(oldpid); } else { - get_new_mmu_context(mm, cpu); - if (mm == current->active_mm) { - write_c0_entryhi(cpu_asid(cpu, mm)); - } else if (!(cpu_asid(cpu, mm)) && - cpu_context(cpu, current->active_mm)) { - /* Just wrapped ASIDs, bump the active one */ - get_new_mmu_context(current->active_mm, cpu); - write_c0_entryhi(cpu_context(cpu, current->active_mm)& 0xff); - } + drop_mmu_context(mm, cpu); } } local_irq_restore(flags); @@ -325,17 +317,10 @@ these entries, we just bump the asid. */ void local_flush_tlb_mm(struct mm_struct *mm) { - unsigned long flags; - int cpu; - local_irq_save(flags); - cpu = smp_processor_id(); + int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { - get_new_mmu_context(mm, smp_processor_id()); - if (mm == current->active_mm) { - write_c0_entryhi(cpu_context(cpu, mm) & 0xff); - } + drop_mmu_context(mm, cpu); } - local_irq_restore(flags); } /* Stolen from mips32 routines */ Index: arch/mips64/mm/tlb-andes.c =================================================================== RCS file: /home/cvs/linux/arch/mips64/mm/tlb-andes.c,v retrieving revision 1.7 diff -u -r1.7 tlb-andes.c --- arch/mips64/mm/tlb-andes.c 3 Feb 2003 06:13:29 -0000 1.7 +++ arch/mips64/mm/tlb-andes.c 6 Feb 2003 23:02:06 -0000 @@ -53,18 +53,12 @@ void local_flush_tlb_mm(struct mm_struct *mm) { - if (cpu_context(smp_processor_id(), mm) != 0) { - unsigned long flags; - + int cpu = smp_processor_id(); + if (cpu_context(cpu, mm) != 0) { #ifdef DEBUG_TLB printk("[tlbmm<%d>]", mm->context); #endif - local_irq_save(flags); - get_new_mmu_context(mm, smp_processor_id()); - if (mm == current->active_mm) - write_c0_entryhi(cpu_context(smp_processor_id(), mm) - & ASID_MASK); - local_irq_restore(flags); + drop_mmu_context(mm,cpu); } } @@ -108,10 +102,7 @@ } write_c0_entryhi(oldpid); } else { - get_new_mmu_context(mm, smp_processor_id()); - if (mm == current->active_mm) - write_c0_entryhi(cpu_context(smp_processor_id(), mm) - & ASID_MASK); + drop_mmu_context(mm, cpu); } local_irq_restore(flags); } Index: arch/mips64/mm/tlb-r4k.c =================================================================== RCS file: /home/cvs/linux/arch/mips64/mm/tlb-r4k.c,v retrieving revision 1.14 diff -u -r1.14 tlb-r4k.c --- arch/mips64/mm/tlb-r4k.c 17 Jan 2003 04:23:08 -0000 1.14 +++ arch/mips64/mm/tlb-r4k.c 6 Feb 2003 23:02:06 -0000 @@ -80,16 +80,10 @@ int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { - unsigned long flags; - #ifdef DEBUG_TLB printk("[tlbmm<%d>]", cpu_context(cpu, mm)); #endif - local_irq_save(flags); - get_new_mmu_context(mm, cpu); - if (mm == current->active_mm) - write_c0_entryhi(cpu_asid(cpu, mm)); - local_irq_restore(flags); + drop_mmu_context(mm,cpu); } } @@ -138,9 +132,7 @@ } write_c0_entryhi(oldpid); } else { - get_new_mmu_context(mm, cpu); - if (mm == current->active_mm) - write_c0_entryhi(cpu_asid(cpu, mm)); + drop_mmu_context(mm, cpu); } local_irq_restore(flags); } Index: arch/mips64/mm/tlb-sb1.c =================================================================== RCS file: /home/cvs/linux/arch/mips64/mm/tlb-sb1.c,v retrieving revision 1.15 diff -u -r1.15 tlb-sb1.c --- arch/mips64/mm/tlb-sb1.c 2 Dec 2002 00:27:49 -0000 1.15 +++ arch/mips64/mm/tlb-sb1.c 6 Feb 2003 23:02:06 -0000 @@ -180,9 +180,7 @@ } write_c0_entryhi(oldpid); } else { - get_new_mmu_context(mm, cpu); - if (mm == current->active_mm) - write_c0_entryhi(cpu_context(cpu, mm) & 0xff); + drop_mmu_context(mm, cpu); } } local_irq_restore(flags); @@ -268,17 +266,10 @@ these entries, we just bump the asid. */ void local_flush_tlb_mm(struct mm_struct *mm) { - unsigned long flags; - int cpu; - local_irq_save(flags); - cpu = smp_processor_id(); + int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) { - get_new_mmu_context(mm, smp_processor_id()); - if (mm == current->active_mm) { - write_c0_entryhi(cpu_context(cpu, mm) & 0xff); - } + drop_mmu_context(mm, cpu); } - local_irq_restore(flags); } /* Stolen from mips32 routines */ Index: include/asm-mips/mmu_context.h =================================================================== RCS file: /home/cvs/linux/include/asm-mips/mmu_context.h,v retrieving revision 1.32 diff -u -r1.32 mmu_context.h --- include/asm-mips/mmu_context.h 17 Jan 2003 04:23:08 -0000 1.32 +++ include/asm-mips/mmu_context.h 6 Feb 2003 23:02:10 -0000 @@ -92,12 +92,25 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu) { + unsigned long flags; + + local_irq_save(flags); + /* Check if our ASID is of an older version and thus invalid */ if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK) get_new_mmu_context(next, cpu); write_c0_entryhi(cpu_context(cpu, next)); TLBMISS_HANDLER_SETUP_PGD(next->pgd); + + /* + * Mark current->active_mm as not "active" anymore. + * We don't want to mislead possible IPI tlb flush routines. + */ + clear_bit(cpu, &prev->cpu_vm_mask); + set_bit(cpu, &next->cpu_vm_mask); + + local_irq_restore(flags); } /* @@ -115,11 +128,39 @@ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) { + unsigned long flags; + + local_irq_save(flags); + /* Unconditionally get a new ASID. */ get_new_mmu_context(next, smp_processor_id()); write_c0_entryhi(cpu_context(smp_processor_id(), next)); TLBMISS_HANDLER_SETUP_PGD(next->pgd); + + local_irq_restore(flags); +} + +/* + * If mm is currently active_mm, we can't really drop it. Instead, + * we will get a new one for it. + */ +static inline void +drop_mmu_context(struct mm_struct *mm, unsigned cpu) +{ + unsigned long flags; + + local_irq_save(flags); + + if (test_bit(cpu, &mm->cpu_vm_mask)) { + get_new_mmu_context(mm, cpu); + write_c0_entryhi(cpu_context(cpu, mm) & 0xff); + } else { + /* will get a new context next time */ + cpu_context(cpu, mm) = 0; + } + + local_irq_restore(flags); } #endif /* _ASM_MMU_CONTEXT_H */ Index: include/asm-mips64/mmu_context.h =================================================================== RCS file: /home/cvs/linux/include/asm-mips64/mmu_context.h,v retrieving revision 1.33 diff -u -r1.33 mmu_context.h --- include/asm-mips64/mmu_context.h 17 Jan 2003 04:23:08 -0000 1.33 +++ include/asm-mips64/mmu_context.h 6 Feb 2003 23:02:10 -0000 @@ -83,12 +83,25 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu) { + unsigned long flags; + + local_irq_save(flags); + /* Check if our ASID is of an older version and thus invalid */ if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK) get_new_mmu_context(next, cpu); write_c0_entryhi(cpu_context(cpu, next)); TLBMISS_HANDLER_SETUP_PGD(next->pgd); + + /* + * Mark current->active_mm as not "active" anymore. + * We don't want to mislead possible IPI tlb flush routines. + */ + clear_bit(cpu, &prev->cpu_vm_mask); + set_bit(cpu, &next->cpu_vm_mask); + + local_irq_restore(flags); } /* @@ -106,11 +119,39 @@ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) { + unsigned long flags; + + local_irq_save(flags); + /* Unconditionally get a new ASID. */ get_new_mmu_context(next, smp_processor_id()); write_c0_entryhi(cpu_context(smp_processor_id(), next)); TLBMISS_HANDLER_SETUP_PGD(next->pgd); + + local_irq_restore(flags); +} + +/* + * If mm is currently active_mm, we can't really drop it. Instead, + * we will get a new one for it. + */ +static inline void +drop_mmu_context(struct mm_struct *mm, unsigned cpu) +{ + unsigned long flags; + + local_irq_save(flags); + + if (test_bit(cpu, &mm->cpu_vm_mask)) { + get_new_mmu_context(mm, cpu); + write_c0_entryhi(cpu_context(cpu, mm) & 0xff); + } else { + /* will get a new context next time */ + cpu_context(cpu, mm) = 0; + } + + local_irq_restore(flags); } #endif /* _ASM_MMU_CONTEXT_H */