--- 2.2.18pre21aa2/arch/alpha/kernel/smp.c.~1~	Wed Nov 22 02:32:53 2000
+++ 2.2.18pre21aa2/arch/alpha/kernel/smp.c	Thu Nov 23 04:48:24 2000
@@ -95,8 +95,7 @@
 smp_store_cpu_info(int cpuid)
 {
 	cpu_data[cpuid].loops_per_jiffy = loops_per_jiffy;
-	cpu_data[cpuid].last_asn
-	  = (cpuid << WIDTH_HARDWARE_ASN) + ASN_FIRST_VERSION;
+	cpu_data[cpuid].last_asn = ASN_FIRST_VERSION;
 
         cpu_data[cpuid].irq_count = 0;
         cpu_data[cpuid].bh_count = 0;
@@ -905,6 +904,8 @@
 	struct mm_struct *mm = (struct mm_struct *) x;
 	if (mm == current->mm)
 		flush_tlb_current(mm);
+	else
+		flush_tlb_other(mm);
 }
 
 void
@@ -912,10 +913,17 @@
 {
 	if (mm == current->mm) {
 		flush_tlb_current(mm);
-		if (atomic_read(&mm->count) == 1)
+		if (atomic_read(&mm->count) == 1) {
+			int i, cpu, this_cpu = smp_processor_id();
+			for (i = 0; i < smp_num_cpus; i++) {
+				cpu = cpu_logical_map(i);
+				if (cpu == this_cpu)
+					continue;
+				mm->context[cpu] = 0;
+			}
 			return;
-	} else
-		flush_tlb_other(mm);
+		}
+	}
 
 	if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) {
 		printk(KERN_CRIT "flush_tlb_mm: timed out\n");
@@ -932,8 +940,12 @@
 ipi_flush_tlb_page(void *x)
 {
 	struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x;
-	if (data->mm == current->mm)
-		flush_tlb_current_page(data->mm, data->vma, data->addr);
+	struct mm_struct * mm = data->mm;
+
+	if (mm == current->mm)
+		flush_tlb_current_page(mm, data->vma, data->addr);
+	else
+		flush_tlb_other(mm);
 }
 
 void
@@ -944,10 +956,17 @@
 
 	if (mm == current->mm) {
 		flush_tlb_current_page(mm, vma, addr);
-		if (atomic_read(&current->mm->count) == 1)
+		if (atomic_read(&current->mm->count) == 1) {
+			int i, cpu, this_cpu = smp_processor_id();
+			for (i = 0; i < smp_num_cpus; i++) {
+				cpu = cpu_logical_map(i);
+				if (cpu == this_cpu)
+					continue;
+				mm->context[cpu] = 0;
+			}
 			return;
-	} else
-		flush_tlb_other(mm);
+		}
+	}
        
 	data.vma = vma;
 	data.mm = mm;
--- 2.2.18pre21aa2/arch/alpha/mm/fault.c.~1~	Wed Nov 22 02:32:53 2000
+++ 2.2.18pre21aa2/arch/alpha/mm/fault.c	Wed Nov 22 22:39:50 2000
@@ -41,7 +41,7 @@
 get_new_mmu_context(struct task_struct *p, struct mm_struct *mm)
 {
 	unsigned long new = __get_new_mmu_context();
-	mm->context = new;
+	mm->context[smp_processor_id()] = new;
 	p->tss.asn = new & HARDWARE_ASN_MASK;
 }
 
--- 2.2.18pre21aa2/include/asm-alpha/mmu_context.h.~1~	Wed Nov 22 02:32:53 2000
+++ 2.2.18pre21aa2/include/asm-alpha/mmu_context.h	Thu Nov 23 21:59:06 2000
@@ -65,12 +65,7 @@
 #endif /* __SMP__ */
 
 #define WIDTH_HARDWARE_ASN	8
-#ifdef __SMP__
-#define WIDTH_THIS_PROCESSOR	5
-#else
-#define WIDTH_THIS_PROCESSOR	0
-#endif
-#define ASN_FIRST_VERSION (1UL << (WIDTH_THIS_PROCESSOR + WIDTH_HARDWARE_ASN))
+#define ASN_FIRST_VERSION (1UL << WIDTH_HARDWARE_ASN)
 #define HARDWARE_ASN_MASK ((1UL << WIDTH_HARDWARE_ASN) - 1)
 
 /*
@@ -100,6 +95,7 @@
 	/* If we've wrapped, flush the whole user TLB.  */
 	if ((asn & HARDWARE_ASN_MASK) >= MAX_ASN) {
 		tbiap();
+		imb();
 		next = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION;
 	}
 	cpu_last_asn(smp_processor_id()) = next;
@@ -125,19 +121,21 @@
 __EXTERN_INLINE void
 ev5_get_mmu_context(struct task_struct *p)
 {
-	/* Check if our ASN is of an older version, or on a different CPU,
-	   and thus invalid.  */
-	/* ??? If we have two threads on different cpus, we'll continually
-	   fight over the context.  Find a way to record a per-mm, per-cpu
-	   value for the asn.  */
-
-	unsigned long asn = cpu_last_asn(smp_processor_id());
-	struct mm_struct *mm = p->mm;
-	unsigned long mmc = mm->context;
+	/* Check if our ASN is of an older version, and thus invalid. */
+	int cpu;
+	unsigned long asn;
+	struct mm_struct *mm;
+	unsigned long mmc;
 	
+	cpu = smp_processor_id();
+	mm = p->mm;
+	ctx_cli();
+	asn = cpu_last_asn(cpu);
+	mmc = mm->context[cpu];
+
 	if ((mmc ^ asn) & ~HARDWARE_ASN_MASK) {
 		mmc = __get_new_mmu_context();
-		mm->context = mmc;
+		mm->context[cpu] = mmc;
 	}
 
 	/* Always update the PCB ASN.  Another thread may have allocated
@@ -159,7 +157,10 @@
 extern inline void
 init_new_context(struct mm_struct *mm)
 {
-	mm->context = 0;
+	int i;
+
+	for (i = 0; i < smp_num_cpus; i++)
+		mm->context[cpu_logical_map(i)] = 0;
 }
 
 extern inline void
@@ -213,6 +214,13 @@
 extern inline void
 activate_context(struct task_struct *task)
 {
+	int i, cpu, this_cpu = smp_processor_id();
+	for (i = 0; i < smp_num_cpus; i++) {
+		cpu = cpu_logical_map(i);
+		if (cpu == this_cpu)
+			continue;
+		task->mm->context[cpu] = 0;
+	}
 	get_new_mmu_context(task, task->mm);
 	reload_context(task);
 }
--- 2.2.18pre21aa2/include/asm-alpha/pgtable.h.~1~	Wed Nov 22 05:30:43 2000
+++ 2.2.18pre21aa2/include/asm-alpha/pgtable.h	Thu Nov 23 05:55:22 2000
@@ -73,7 +73,7 @@
 __EXTERN_INLINE void
 ev5_flush_tlb_other(struct mm_struct *mm)
 {
-	mm->context = 0;
+	mm->context[smp_processor_id()] = 0;
 }
 
 /*
--- 2.2.18pre21aa2/include/asm-alpha/system.h.~1~	Thu Nov 16 17:55:21 2000
+++ 2.2.18pre21aa2/include/asm-alpha/system.h	Thu Nov 23 21:58:57 2000
@@ -112,12 +112,21 @@
 
 extern void halt(void) __attribute__((noreturn));
 
+#ifdef CONFIG_SMP
+#define ctx_cli()	__cli()
+#define ctx_sti()	__sti()
+#else
+#define ctx_cli()	do { } while(0)
+#define ctx_sti()	do { } while(0)
+#endif
+
 #define switch_to(prev,next,last)			\
 do {							\
 	unsigned long pcbb;				\
 	current = (next);				\
 	pcbb = virt_to_phys(&current->tss);		\
 	(last) = alpha_switch_to(pcbb, (prev));		\
+	ctx_sti();					\
 } while (0)
 
 extern struct task_struct* alpha_switch_to(unsigned long, struct task_struct*);
--- 2.2.18pre21aa2/include/linux/sched.h.~1~	Wed Nov 22 02:32:53 2000
+++ 2.2.18pre21aa2/include/linux/sched.h	Thu Nov 23 22:02:53 2000
@@ -181,7 +181,11 @@
 	atomic_t count;
 	int map_count;				/* number of VMAs */
 	struct semaphore mmap_sem;
+#ifdef __alpha__
+	unsigned long context[NR_CPUS];
+#else
 	unsigned long context;
+#endif
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long start_brk, brk, start_stack;
 	unsigned long arg_start, arg_end, env_start, env_end;
@@ -197,12 +201,18 @@
 	void * segments;
 };
 
+#ifdef __alpha__
+#define CONTEXT_INIT	{ 0, }
+#else
+#define CONTEXT_INIT	0
+#endif
+
 #define INIT_MM {					\
 		&init_mmap, NULL, NULL,			\
 		swapper_pg_dir, 			\
 		ATOMIC_INIT(1), 1,			\
 		MUTEX,					\
-		0,					\
+		CONTEXT_INIT,				\
 		0, 0, 0, 0,				\
 		0, 0, 0, 				\
 		0, 0, 0, 0,				\