All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC & PATCH]  fixing tlb flush race problem on smp
@ 2003-01-21 22:37 Jun Sun
  2003-01-22  7:43 ` Juan Quintela
  0 siblings, 1 reply; 9+ messages in thread
From: Jun Sun @ 2003-01-21 22:37 UTC (permalink / raw)
  To: linux-mips; +Cc: jsun

[-- Attachment #1: Type: text/plain, Size: 1692 bytes --]


Many of us are aware of a hole in current TLB flushing code that
could cause processes using the same ASID for a SMP machine.

Actually there are several problems:

1) get_new_mmu_context() and following set_entryhi, etc are
not called automically in switch_mm() and active_mm().  If
an IPI happens and request to flush local tlb, bad things happen.

2) if local_flush_tlb_range() and local_flush_tlb_mm() are 
called from an IPI, they may call get_new_mmu_context() which
can bump up the ASID generation number with current active_mm
totally not aware of it.  Bad things will happen later.

3) during the time window after schedule() calling switch_mm()
before switch_to(), current->active_mm may be valid but does
really mean "current->active_mm" anymore.  This is because
the "current" process will soon become "prev".  The real active_mm
is actually "next->active_mm".  Because of this, it is not
enough for those two IPI'ed flushing routines to just check
again current->active_mm.  Long story made short - bad
things will happen.

It turns out that other arches have similar problems and solved
it in various ways.  Unfortunely I like none of them.

Here is one I am pretty happy with.  It is very small and efficient.
And conceptually it is clean too.  We basically keep the semantics
of ->mm and ->active_mm unchanged and only introduce a new bit
to mark which mm is the true owner of mmu hardware on a cpu.

The only downside is that cpu_vm_mask variable does not really
mean "mask for blocking IPI" in this approach.  It actually 
indicates whether current->active_mm is really active or not.  

Tested and passed the notorious fork/malloc test.

Let me know what you think.

Jun


[-- Attachment #2: junk --]
[-- Type: text/plain, Size: 2335 bytes --]

diff -Nru link/arch/mips/mm/tlb-sb1.c.orig link/arch/mips/mm/tlb-sb1.c
--- link/arch/mips/mm/tlb-sb1.c.orig	Tue Jan 21 13:54:59 2003
+++ link/arch/mips/mm/tlb-sb1.c	Tue Jan 21 13:58:50 2003
@@ -172,9 +172,13 @@
 			}
 			write_c0_entryhi(oldpid);
 		} else {
-			get_new_mmu_context(mm, cpu);
-			if (mm == current->active_mm)
+			if (mm == current->active_mm) {
+				get_new_mmu_context(mm, cpu);
 				write_c0_entryhi(cpu_asid(cpu, mm));
+			} else {
+				/* drop the current context completely */
+				CPU_CONTEXT(cpu, mm) = 0;
+			}
 		}
 	}
 	__restore_flags(flags);
@@ -258,9 +262,12 @@
 	__save_and_cli(flags);
 	cpu = smp_processor_id();
 	if (cpu_context(cpu, mm) != 0) {
-		get_new_mmu_context(mm, smp_processor_id());
 		if (mm == current->active_mm) {
+			get_new_mmu_context(mm, smp_processor_id());
 			write_c0_entryhi(cpu_asid(cpu, mm));
+		} else {
+			/* drop the current context completely */
+			CPU_CONTEXT(cpu, mm) = 0;
 		}
 	}
 	__restore_flags(flags);
diff -Nru link/include/asm-mips/mmu_context.h.orig link/include/asm-mips/mmu_context.h
--- link/include/asm-mips/mmu_context.h.orig	Tue Jan 21 13:55:43 2003
+++ link/include/asm-mips/mmu_context.h	Tue Jan 21 14:01:19 2003
@@ -89,12 +89,25 @@
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                              struct task_struct *tsk, unsigned cpu)
 {
+	unsigned long flags;
+
+	__save_and_cli(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);
+
+	__restore_flags(flags);
 }
 
 /*
@@ -112,11 +125,17 @@
 static inline void
 activate_mm(struct mm_struct *prev, struct mm_struct *next)
 {
+	unsigned long flags;
+
+	__save_and_cli(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);
+	
+	__restore_flags(flags);
 }
 
 #endif /* _ASM_MMU_CONTEXT_H */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC & PATCH]  fixing tlb flush race problem on smp
  2003-01-21 22:37 [RFC & PATCH] fixing tlb flush race problem on smp Jun Sun
@ 2003-01-22  7:43 ` Juan Quintela
  2003-01-28  1:03   ` Jun Sun
  2003-01-29  7:28   ` Ralf Baechle
  0 siblings, 2 replies; 9+ messages in thread
From: Juan Quintela @ 2003-01-22  7:43 UTC (permalink / raw)
  To: Jun Sun; +Cc: linux-mips

>>>>> "jun" == Jun Sun <jsun@mvista.com> writes:

Hi
        just nickpitting.


jun> +		} else {
jun> +			/* drop the current context completely */
jun> +			CPU_CONTEXT(cpu, mm) = 0;
jun> }
jun> }
jun> __restore_flags(flags);

Perhaps creating a inline function for this, as the code is identical
in both branches?


jun> diff -Nru link/include/asm-mips/mmu_context.h.orig link/include/asm-mips/mmu_context.h
jun> --- link/include/asm-mips/mmu_context.h.orig	Tue Jan 21 13:55:43 2003
jun> +++ link/include/asm-mips/mmu_context.h	Tue Jan 21 14:01:19 2003
jun> @@ -89,12 +89,25 @@
jun> static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
jun> struct task_struct *tsk, unsigned cpu)
jun> {
jun> +	unsigned long flags;
jun> +
jun> +	__save_and_cli(flags);

s/__save_and_cli()/local_irq_save()/

jun> +	__restore_flags(flags);

s/__restore_flags()/local_irq_restore()/

Same in the other occurence, please.

Later, Juan.

-- 
In theory, practice and theory are the same, but in practice they 
are different -- Larry McVoy

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC & PATCH]  fixing tlb flush race problem on smp
  2003-01-22  7:43 ` Juan Quintela
@ 2003-01-28  1:03   ` Jun Sun
  2003-01-29  8:06     ` Ralf Baechle
  2003-01-29  7:28   ` Ralf Baechle
  1 sibling, 1 reply; 9+ messages in thread
From: Jun Sun @ 2003-01-28  1:03 UTC (permalink / raw)
  To: Juan Quintela; +Cc: linux-mips, jsun

[-- Attachment #1: Type: text/plain, Size: 330 bytes --]


Thanks, Juan.

I also find a stupid typo and a subtle hole in my original patch.
Here is an updated version, for 2.4/mips only.  If it looks ok, I 
will extend to other sub-arches/trees.

This new one is pretty nice in that all mmu related operations
are put into one file and it is much easier to ensure correctness
later.

Jun

[-- Attachment #2: 030127-fix-smp-tlb-flush-holes.patch --]
[-- Type: text/plain, Size: 2579 bytes --]

diff -Nru link/arch/mips/mm/tlb-sb1.c.orig link/arch/mips/mm/tlb-sb1.c
--- link/arch/mips/mm/tlb-sb1.c.orig	Tue Jan 21 13:54:59 2003
+++ link/arch/mips/mm/tlb-sb1.c	Mon Jan 27 16:58:54 2003
@@ -172,9 +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));
+			drop_mmu_context(mm, cpu);
 		}
 	}
 	__restore_flags(flags);
@@ -258,10 +256,7 @@
 	__save_and_cli(flags);
 	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_asid(cpu, mm));
-		}
+		drop_mmu_context(mm, cpu);
 	}
 	__restore_flags(flags);
 }
diff -Nru link/include/asm-mips/mmu_context.h.orig link/include/asm-mips/mmu_context.h
--- link/include/asm-mips/mmu_context.h.orig	Tue Jan 21 13:55:43 2003
+++ link/include/asm-mips/mmu_context.h	Mon Jan 27 16:56:44 2003
@@ -89,12 +89,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);
 }
 
 /*
@@ -112,11 +125,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);
+		set_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 */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC & PATCH]  fixing tlb flush race problem on smp
  2003-01-22  7:43 ` Juan Quintela
  2003-01-28  1:03   ` Jun Sun
@ 2003-01-29  7:28   ` Ralf Baechle
  1 sibling, 0 replies; 9+ messages in thread
From: Ralf Baechle @ 2003-01-29  7:28 UTC (permalink / raw)
  To: Juan Quintela; +Cc: Jun Sun, linux-mips

On Wed, Jan 22, 2003 at 08:43:26AM +0100, Juan Quintela wrote:

> jun> +	__save_and_cli(flags);
> 
> s/__save_and_cli()/local_irq_save()/
> 
> jun> +	__restore_flags(flags);
> 
> s/__restore_flags()/local_irq_restore()/
> 
> Same in the other occurence, please.

I've already done this recently for large parts of arch/mips* and
include/asm-mips*.

  Ralf

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC & PATCH]  fixing tlb flush race problem on smp
  2003-01-28  1:03   ` Jun Sun
@ 2003-01-29  8:06     ` Ralf Baechle
  2003-02-05  0:02         ` Jun Sun
  0 siblings, 1 reply; 9+ messages in thread
From: Ralf Baechle @ 2003-01-29  8:06 UTC (permalink / raw)
  To: Jun Sun; +Cc: Juan Quintela, linux-mips

On Mon, Jan 27, 2003 at 05:03:46PM -0800, Jun Sun wrote:

> I also find a stupid typo and a subtle hole in my original patch.
> Here is an updated version, for 2.4/mips only.  If it looks ok, I 
> will extend to other sub-arches/trees.
> 
> This new one is pretty nice in that all mmu related operations
> are put into one file and it is much easier to ensure correctness
> later.

I like this one.

> +
> +	/*
> +	 * 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);

I don't think it's necessary to protect the clear_bit and set_bit operations
with local_irq_save ... local_irq_restore.

In addition because switch_mm is always called with interrupts enabled you
can simplify that to local_irq_disable ... local_irq_enable.

  Ralf

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC & PATCH]  fixing tlb flush race problem on smp
@ 2003-02-05  0:02         ` Jun Sun
  0 siblings, 0 replies; 9+ messages in thread
From: Jun Sun @ 2003-02-05  0:02 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Juan Quintela, linux-mips, jsun, Ralf Baechle

[-- Attachment #1: Type: text/plain, Size: 1364 bytes --]


Here is a complete patch for both mips/mips64, 2.4 and 
2.5.  Of course only 2.4/mips combo is tested.

The clear_bit/set_bit actually need to be protected.
The flag setting needs to be in sync with the actual
hardware setting (set_entry_hi/set current pgd).  Otherwise
an tlb flushing IPI may does the wrong thing.

Jun

On Wed, Jan 29, 2003 at 09:06:27AM +0100, Ralf Baechle wrote:
> On Mon, Jan 27, 2003 at 05:03:46PM -0800, Jun Sun wrote:
> 
> > I also find a stupid typo and a subtle hole in my original patch.
> > Here is an updated version, for 2.4/mips only.  If it looks ok, I 
> > will extend to other sub-arches/trees.
> > 
> > This new one is pretty nice in that all mmu related operations
> > are put into one file and it is much easier to ensure correctness
> > later.
> 
> I like this one.
> 
> > +
> > +	/*
> > +	 * 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);
> 
> I don't think it's necessary to protect the clear_bit and set_bit operations
> with local_irq_save ... local_irq_restore.
> 
> In addition because switch_mm is always called with interrupts enabled you
> can simplify that to local_irq_disable ... local_irq_enable.
> 
>   Ralf
> 

[-- Attachment #2: 030204-2.4-smp-tlb-flush.patch --]
[-- Type: text/plain, Size: 9209 bytes --]

diff -Nru linux/arch/mips/mm/tlb-sb1.c.orig linux/arch/mips/mm/tlb-sb1.c
--- linux/arch/mips/mm/tlb-sb1.c.orig	Tue Feb  4 13:50:55 2003
+++ linux/arch/mips/mm/tlb-sb1.c	Tue Feb  4 14:01:24 2003
@@ -172,9 +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));
+			drop_mmu_context(mm, cpu);
 		}
 	}
 	local_irq_restore(flags);
@@ -253,17 +251,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_asid(cpu, mm));
-		}
+		drop_mmu_context(mm, cpu);
 	}
-	local_irq_restore(flags);
 }
 
 /* Stolen from mips32 routines */
diff -Nru linux/arch/mips/mm/tlb-r4k.c.orig linux/arch/mips/mm/tlb-r4k.c
--- linux/arch/mips/mm/tlb-r4k.c.orig	Mon Jan 27 17:13:31 2003
+++ linux/arch/mips/mm/tlb-r4k.c	Tue Feb  4 14:15:04 2003
@@ -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_asid(cpu, mm));
-		local_irq_restore(flags);
+		drop_mmu_context(mm,cpu);
 	}
 }
 
@@ -133,9 +127,7 @@
 			}
 			write_c0_entryhi(oldpid);
 		} else {
-			get_new_mmu_context(mm, smp_processor_id());
-			if (mm == current->active_mm)
-				write_c0_entryhi(cpu_asid(cpu, mm));
+			drop_mmu_context(mm, cpu);
 		}
 		local_irq_restore(flags);
 	}
diff -Nru linux/arch/mips/mm/tlb-r3k.c.orig linux/arch/mips/mm/tlb-r3k.c
--- linux/arch/mips/mm/tlb-r3k.c.orig	Mon Jan 27 17:13:31 2003
+++ linux/arch/mips/mm/tlb-r3k.c	Tue Feb  4 14:09:04 2003
@@ -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, smp_processor_id());
-		if (mm == current->active_mm)
-			write_c0_entryhi(cpu_asid(cpu, mm));
-		local_irq_restore(flags);
+		drop_mmu_context(mm, cpu);
 	}
 }
 
@@ -119,9 +113,7 @@
 			}
 			write_c0_entryhi(oldpid);
 		} else {
-			get_new_mmu_context(mm, smp_processor_id());
-			if (mm == current->active_mm)
-				write_c0_entryhi(cpu_asid(cpu, mm));
+			drop_mmu_context(mm, cpu);
 		}
 		local_irq_restore(flags);
 	}
diff -Nru linux/arch/mips64/mm/tlb-sb1.c.orig linux/arch/mips64/mm/tlb-sb1.c
--- linux/arch/mips64/mm/tlb-sb1.c.orig	Mon Jan 27 17:13:34 2003
+++ linux/arch/mips64/mm/tlb-sb1.c	Tue Feb  4 14:45:58 2003
@@ -180,9 +180,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);
@@ -231,17 +229,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_asid(cpu, mm));
-		}
+		drop_mmu_context(mm, cpu);
 	}
-	local_irq_restore(flags);
 }
 
 /* Stolen from mips32 routines */
diff -Nru linux/arch/mips64/mm/tlb-r4k.c.orig linux/arch/mips64/mm/tlb-r4k.c
--- linux/arch/mips64/mm/tlb-r4k.c.orig	Mon Jan 27 17:13:34 2003
+++ linux/arch/mips64/mm/tlb-r4k.c	Tue Feb  4 14:47:52 2003
@@ -80,16 +80,10 @@
 	int cpu = smp_processor_id();
 
 	if (cpu_context(cpu, mm) != 0) {
-		unsigned long flags;
-
 #ifdef DEBUG_TLB
 		printk("[tlbmm<%d>]", mm->context);
 #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);
 	}
 }
 
@@ -137,9 +131,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);
 	}
diff -Nru linux/arch/mips64/mm/tlb-andes.c.orig linux/arch/mips64/mm/tlb-andes.c
--- linux/arch/mips64/mm/tlb-andes.c.orig	Tue Feb  4 13:13:43 2003
+++ linux/arch/mips64/mm/tlb-andes.c	Tue Feb  4 14:49:59 2003
@@ -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);
 	}
 }
 
@@ -106,10 +100,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);
 	}
diff -Nru linux/include/asm-mips/mmu_context.h.orig linux/include/asm-mips/mmu_context.h
--- linux/include/asm-mips/mmu_context.h.orig	Tue Feb  4 13:50:55 2003
+++ linux/include/asm-mips/mmu_context.h	Tue Feb  4 13:51:03 2003
@@ -89,12 +89,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);
 }
 
 /*
@@ -112,11 +125,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);
+		set_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 */
diff -Nru linux/include/asm-mips64/mmu_context.h.orig linux/include/asm-mips64/mmu_context.h
--- linux/include/asm-mips64/mmu_context.h.orig	Tue Jan 21 13:55:43 2003
+++ linux/include/asm-mips64/mmu_context.h	Tue Feb  4 14:46:00 2003
@@ -80,12 +80,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);
 }
 
 /*
@@ -103,11 +116,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);
+		set_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 */

[-- Attachment #3: 030204-2.5-smp-tlb-flush.patch --]
[-- Type: text/plain, Size: 9558 bytes --]

diff -Nru linux/arch/mips/mm/tlb-sb1.c.orig linux/arch/mips/mm/tlb-sb1.c
--- linux/arch/mips/mm/tlb-sb1.c.orig	Wed Dec 11 17:04:17 2002
+++ linux/arch/mips/mm/tlb-sb1.c	Tue Feb  4 15:00:53 2003
@@ -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 */
diff -Nru linux/arch/mips/mm/tlb-r4k.c.orig linux/arch/mips/mm/tlb-r4k.c
--- linux/arch/mips/mm/tlb-r4k.c.orig	Mon Jan 27 18:03:21 2003
+++ linux/arch/mips/mm/tlb-r4k.c	Tue Feb  4 15:04:29 2003
@@ -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);
 	}
diff -Nru linux/arch/mips/mm/tlb-r3k.c.orig linux/arch/mips/mm/tlb-r3k.c
--- linux/arch/mips/mm/tlb-r3k.c.orig	Mon Jan 27 18:03:21 2003
+++ linux/arch/mips/mm/tlb-r3k.c	Tue Feb  4 15:05:22 2003
@@ -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);
 	}
diff -Nru linux/arch/mips64/mm/tlb-sb1.c.orig linux/arch/mips64/mm/tlb-sb1.c
--- linux/arch/mips64/mm/tlb-sb1.c.orig	Wed Dec 11 17:04:19 2002
+++ linux/arch/mips64/mm/tlb-sb1.c	Tue Feb  4 15:07:42 2003
@@ -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 */
diff -Nru linux/arch/mips64/mm/tlb-r4k.c.orig linux/arch/mips64/mm/tlb-r4k.c
--- linux/arch/mips64/mm/tlb-r4k.c.orig	Mon Jan 27 18:03:22 2003
+++ linux/arch/mips64/mm/tlb-r4k.c	Tue Feb  4 15:08:21 2003
@@ -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);
 	}
diff -Nru linux/arch/mips64/mm/tlb-andes.c.orig linux/arch/mips64/mm/tlb-andes.c
--- linux/arch/mips64/mm/tlb-andes.c.orig	Tue Feb  4 13:14:43 2003
+++ linux/arch/mips64/mm/tlb-andes.c	Tue Feb  4 14:53:28 2003
@@ -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);
 	}
diff -Nru linux/include/asm-mips/mmu_context.h.orig linux/include/asm-mips/mmu_context.h
--- linux/include/asm-mips/mmu_context.h.orig	Mon Jan 27 18:03:23 2003
+++ linux/include/asm-mips/mmu_context.h	Tue Feb  4 14:53:28 2003
@@ -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);
+		set_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 */
diff -Nru linux/include/asm-mips64/mmu_context.h.orig linux/include/asm-mips64/mmu_context.h
--- linux/include/asm-mips64/mmu_context.h.orig	Mon Jan 27 18:03:23 2003
+++ linux/include/asm-mips64/mmu_context.h	Tue Feb  4 14:53:28 2003
@@ -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);
+		set_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 */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC & PATCH]  fixing tlb flush race problem on smp
@ 2003-02-05  0:02         ` Jun Sun
  0 siblings, 0 replies; 9+ messages in thread
From: Jun Sun @ 2003-02-05  0:02 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Juan Quintela, linux-mips, jsun

[-- Attachment #1: Type: text/plain, Size: 1364 bytes --]


Here is a complete patch for both mips/mips64, 2.4 and 
2.5.  Of course only 2.4/mips combo is tested.

The clear_bit/set_bit actually need to be protected.
The flag setting needs to be in sync with the actual
hardware setting (set_entry_hi/set current pgd).  Otherwise
an tlb flushing IPI may does the wrong thing.

Jun

On Wed, Jan 29, 2003 at 09:06:27AM +0100, Ralf Baechle wrote:
> On Mon, Jan 27, 2003 at 05:03:46PM -0800, Jun Sun wrote:
> 
> > I also find a stupid typo and a subtle hole in my original patch.
> > Here is an updated version, for 2.4/mips only.  If it looks ok, I 
> > will extend to other sub-arches/trees.
> > 
> > This new one is pretty nice in that all mmu related operations
> > are put into one file and it is much easier to ensure correctness
> > later.
> 
> I like this one.
> 
> > +
> > +	/*
> > +	 * 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);
> 
> I don't think it's necessary to protect the clear_bit and set_bit operations
> with local_irq_save ... local_irq_restore.
> 
> In addition because switch_mm is always called with interrupts enabled you
> can simplify that to local_irq_disable ... local_irq_enable.
> 
>   Ralf
> 

[-- Attachment #2: 030204-2.4-smp-tlb-flush.patch --]
[-- Type: text/plain, Size: 9209 bytes --]

diff -Nru linux/arch/mips/mm/tlb-sb1.c.orig linux/arch/mips/mm/tlb-sb1.c
--- linux/arch/mips/mm/tlb-sb1.c.orig	Tue Feb  4 13:50:55 2003
+++ linux/arch/mips/mm/tlb-sb1.c	Tue Feb  4 14:01:24 2003
@@ -172,9 +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));
+			drop_mmu_context(mm, cpu);
 		}
 	}
 	local_irq_restore(flags);
@@ -253,17 +251,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_asid(cpu, mm));
-		}
+		drop_mmu_context(mm, cpu);
 	}
-	local_irq_restore(flags);
 }
 
 /* Stolen from mips32 routines */
diff -Nru linux/arch/mips/mm/tlb-r4k.c.orig linux/arch/mips/mm/tlb-r4k.c
--- linux/arch/mips/mm/tlb-r4k.c.orig	Mon Jan 27 17:13:31 2003
+++ linux/arch/mips/mm/tlb-r4k.c	Tue Feb  4 14:15:04 2003
@@ -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_asid(cpu, mm));
-		local_irq_restore(flags);
+		drop_mmu_context(mm,cpu);
 	}
 }
 
@@ -133,9 +127,7 @@
 			}
 			write_c0_entryhi(oldpid);
 		} else {
-			get_new_mmu_context(mm, smp_processor_id());
-			if (mm == current->active_mm)
-				write_c0_entryhi(cpu_asid(cpu, mm));
+			drop_mmu_context(mm, cpu);
 		}
 		local_irq_restore(flags);
 	}
diff -Nru linux/arch/mips/mm/tlb-r3k.c.orig linux/arch/mips/mm/tlb-r3k.c
--- linux/arch/mips/mm/tlb-r3k.c.orig	Mon Jan 27 17:13:31 2003
+++ linux/arch/mips/mm/tlb-r3k.c	Tue Feb  4 14:09:04 2003
@@ -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, smp_processor_id());
-		if (mm == current->active_mm)
-			write_c0_entryhi(cpu_asid(cpu, mm));
-		local_irq_restore(flags);
+		drop_mmu_context(mm, cpu);
 	}
 }
 
@@ -119,9 +113,7 @@
 			}
 			write_c0_entryhi(oldpid);
 		} else {
-			get_new_mmu_context(mm, smp_processor_id());
-			if (mm == current->active_mm)
-				write_c0_entryhi(cpu_asid(cpu, mm));
+			drop_mmu_context(mm, cpu);
 		}
 		local_irq_restore(flags);
 	}
diff -Nru linux/arch/mips64/mm/tlb-sb1.c.orig linux/arch/mips64/mm/tlb-sb1.c
--- linux/arch/mips64/mm/tlb-sb1.c.orig	Mon Jan 27 17:13:34 2003
+++ linux/arch/mips64/mm/tlb-sb1.c	Tue Feb  4 14:45:58 2003
@@ -180,9 +180,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);
@@ -231,17 +229,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_asid(cpu, mm));
-		}
+		drop_mmu_context(mm, cpu);
 	}
-	local_irq_restore(flags);
 }
 
 /* Stolen from mips32 routines */
diff -Nru linux/arch/mips64/mm/tlb-r4k.c.orig linux/arch/mips64/mm/tlb-r4k.c
--- linux/arch/mips64/mm/tlb-r4k.c.orig	Mon Jan 27 17:13:34 2003
+++ linux/arch/mips64/mm/tlb-r4k.c	Tue Feb  4 14:47:52 2003
@@ -80,16 +80,10 @@
 	int cpu = smp_processor_id();
 
 	if (cpu_context(cpu, mm) != 0) {
-		unsigned long flags;
-
 #ifdef DEBUG_TLB
 		printk("[tlbmm<%d>]", mm->context);
 #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);
 	}
 }
 
@@ -137,9 +131,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);
 	}
diff -Nru linux/arch/mips64/mm/tlb-andes.c.orig linux/arch/mips64/mm/tlb-andes.c
--- linux/arch/mips64/mm/tlb-andes.c.orig	Tue Feb  4 13:13:43 2003
+++ linux/arch/mips64/mm/tlb-andes.c	Tue Feb  4 14:49:59 2003
@@ -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);
 	}
 }
 
@@ -106,10 +100,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);
 	}
diff -Nru linux/include/asm-mips/mmu_context.h.orig linux/include/asm-mips/mmu_context.h
--- linux/include/asm-mips/mmu_context.h.orig	Tue Feb  4 13:50:55 2003
+++ linux/include/asm-mips/mmu_context.h	Tue Feb  4 13:51:03 2003
@@ -89,12 +89,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);
 }
 
 /*
@@ -112,11 +125,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);
+		set_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 */
diff -Nru linux/include/asm-mips64/mmu_context.h.orig linux/include/asm-mips64/mmu_context.h
--- linux/include/asm-mips64/mmu_context.h.orig	Tue Jan 21 13:55:43 2003
+++ linux/include/asm-mips64/mmu_context.h	Tue Feb  4 14:46:00 2003
@@ -80,12 +80,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);
 }
 
 /*
@@ -103,11 +116,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);
+		set_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 */

[-- Attachment #3: 030204-2.5-smp-tlb-flush.patch --]
[-- Type: text/plain, Size: 9558 bytes --]

diff -Nru linux/arch/mips/mm/tlb-sb1.c.orig linux/arch/mips/mm/tlb-sb1.c
--- linux/arch/mips/mm/tlb-sb1.c.orig	Wed Dec 11 17:04:17 2002
+++ linux/arch/mips/mm/tlb-sb1.c	Tue Feb  4 15:00:53 2003
@@ -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 */
diff -Nru linux/arch/mips/mm/tlb-r4k.c.orig linux/arch/mips/mm/tlb-r4k.c
--- linux/arch/mips/mm/tlb-r4k.c.orig	Mon Jan 27 18:03:21 2003
+++ linux/arch/mips/mm/tlb-r4k.c	Tue Feb  4 15:04:29 2003
@@ -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);
 	}
diff -Nru linux/arch/mips/mm/tlb-r3k.c.orig linux/arch/mips/mm/tlb-r3k.c
--- linux/arch/mips/mm/tlb-r3k.c.orig	Mon Jan 27 18:03:21 2003
+++ linux/arch/mips/mm/tlb-r3k.c	Tue Feb  4 15:05:22 2003
@@ -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);
 	}
diff -Nru linux/arch/mips64/mm/tlb-sb1.c.orig linux/arch/mips64/mm/tlb-sb1.c
--- linux/arch/mips64/mm/tlb-sb1.c.orig	Wed Dec 11 17:04:19 2002
+++ linux/arch/mips64/mm/tlb-sb1.c	Tue Feb  4 15:07:42 2003
@@ -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 */
diff -Nru linux/arch/mips64/mm/tlb-r4k.c.orig linux/arch/mips64/mm/tlb-r4k.c
--- linux/arch/mips64/mm/tlb-r4k.c.orig	Mon Jan 27 18:03:22 2003
+++ linux/arch/mips64/mm/tlb-r4k.c	Tue Feb  4 15:08:21 2003
@@ -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);
 	}
diff -Nru linux/arch/mips64/mm/tlb-andes.c.orig linux/arch/mips64/mm/tlb-andes.c
--- linux/arch/mips64/mm/tlb-andes.c.orig	Tue Feb  4 13:14:43 2003
+++ linux/arch/mips64/mm/tlb-andes.c	Tue Feb  4 14:53:28 2003
@@ -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);
 	}
diff -Nru linux/include/asm-mips/mmu_context.h.orig linux/include/asm-mips/mmu_context.h
--- linux/include/asm-mips/mmu_context.h.orig	Mon Jan 27 18:03:23 2003
+++ linux/include/asm-mips/mmu_context.h	Tue Feb  4 14:53:28 2003
@@ -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);
+		set_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 */
diff -Nru linux/include/asm-mips64/mmu_context.h.orig linux/include/asm-mips64/mmu_context.h
--- linux/include/asm-mips64/mmu_context.h.orig	Mon Jan 27 18:03:23 2003
+++ linux/include/asm-mips64/mmu_context.h	Tue Feb  4 14:53:28 2003
@@ -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);
+		set_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 */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC & PATCH] fixing tlb flush race problem on smp
  2003-02-05  0:02         ` Jun Sun
  (?)
@ 2003-02-14  4:48         ` Atsushi Nemoto
  2003-02-14 11:06           ` Maciej W. Rozycki
  -1 siblings, 1 reply; 9+ messages in thread
From: Atsushi Nemoto @ 2003-02-14  4:48 UTC (permalink / raw)
  To: jsun; +Cc: ralf, quintela, linux-mips, nemoto

>>>>> On Tue, 4 Feb 2003 16:02:50 -0800, Jun Sun <jsun@mvista.com> said:
jsun> Here is a complete patch for both mips/mips64, 2.4 and 2.5.  Of
jsun> course only 2.4/mips combo is tested.

The attached patch seems to break r3k codes.  Here is a patch to fix
it (only for 2.4/mips).

diff -ur linux-mips-cvs/include/asm-mips/mmu_context.h linux.new/include/asm-mips/mmu_context.h
--- linux-mips-cvs/include/asm-mips/mmu_context.h	Fri Feb 14 09:41:31 2003
+++ linux.new/include/asm-mips/mmu_context.h	Fri Feb 14 13:40:24 2003
@@ -151,7 +151,7 @@
 
 	if (test_bit(cpu, &mm->cpu_vm_mask))  {
 		get_new_mmu_context(mm, cpu);
-		write_c0_entryhi(cpu_context(cpu, mm) & 0xff);
+		write_c0_entryhi(cpu_context(cpu, mm) & ASID_MASK);
 	} else {
 		/* will get a new context next time */
 		cpu_context(cpu, mm) = 0;
---
Atsushi Nemoto

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC & PATCH] fixing tlb flush race problem on smp
  2003-02-14  4:48         ` Atsushi Nemoto
@ 2003-02-14 11:06           ` Maciej W. Rozycki
  0 siblings, 0 replies; 9+ messages in thread
From: Maciej W. Rozycki @ 2003-02-14 11:06 UTC (permalink / raw)
  To: Atsushi Nemoto; +Cc: jsun, ralf, quintela, linux-mips, nemoto

On Fri, 14 Feb 2003, Atsushi Nemoto wrote:

> The attached patch seems to break r3k codes.  Here is a patch to fix
> it (only for 2.4/mips).
> 
> diff -ur linux-mips-cvs/include/asm-mips/mmu_context.h linux.new/include/asm-mips/mmu_context.h
> --- linux-mips-cvs/include/asm-mips/mmu_context.h	Fri Feb 14 09:41:31 2003
> +++ linux.new/include/asm-mips/mmu_context.h	Fri Feb 14 13:40:24 2003
> @@ -151,7 +151,7 @@
>  
>  	if (test_bit(cpu, &mm->cpu_vm_mask))  {
>  		get_new_mmu_context(mm, cpu);
> -		write_c0_entryhi(cpu_context(cpu, mm) & 0xff);
> +		write_c0_entryhi(cpu_context(cpu, mm) & ASID_MASK);
>  	} else {
>  		/* will get a new context next time */
>  		cpu_context(cpu, mm) = 0;

 I've checked in a slightly different fix.  Thanks for spotting the
problem.

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: macro@ds2.pg.gda.pl, PGP key available        +

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2003-02-14 11:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-01-21 22:37 [RFC & PATCH] fixing tlb flush race problem on smp Jun Sun
2003-01-22  7:43 ` Juan Quintela
2003-01-28  1:03   ` Jun Sun
2003-01-29  8:06     ` Ralf Baechle
2003-02-05  0:02       ` Jun Sun
2003-02-05  0:02         ` Jun Sun
2003-02-14  4:48         ` Atsushi Nemoto
2003-02-14 11:06           ` Maciej W. Rozycki
2003-01-29  7:28   ` Ralf Baechle

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.