patch-2.4.22 linux-2.4.22/include/asm-mips/mmu_context.h

Next file: linux-2.4.22/include/asm-mips/module.h
Previous file: linux-2.4.22/include/asm-mips/mmu.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/include/asm-mips/mmu_context.h linux-2.4.22/include/asm-mips/mmu_context.h
@@ -27,16 +27,13 @@
 #define TLBMISS_HANDLER_SETUP_PGD(pgd) \
 	pgd_current[smp_processor_id()] = (unsigned long)(pgd)
 #define TLBMISS_HANDLER_SETUP() \
-	set_context((unsigned long) smp_processor_id() << (23 + 3)); \
+	write_c0_context((unsigned long) smp_processor_id() << (23 + 3)); \
 	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 extern unsigned long pgd_current[];
 
-#ifndef CONFIG_SMP
-#define CPU_CONTEXT(cpu, mm)	(mm)->context
-#else
-#define CPU_CONTEXT(cpu, mm)	(*((unsigned long *)((mm)->context) + cpu))
-#endif
-#define ASID_CACHE(cpu)		cpu_data[cpu].asid_cache
+#define cpu_context(cpu, mm)	((mm)->context[cpu])
+#define cpu_asid(cpu, mm)	(cpu_context((cpu), (mm)) & ASID_MASK)
+#define asid_cache(cpu)		cpu_data[cpu].asid_cache
 
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
@@ -64,7 +61,7 @@
 static inline void
 get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
 {
-	unsigned long asid = ASID_CACHE(cpu);
+	unsigned long asid = asid_cache(cpu);
 
 	if (! ((asid += ASID_INC) & ASID_MASK) ) {
 		flush_icache_all();
@@ -72,7 +69,7 @@
 		if (!asid)		/* fix version if needed */
 			asid = ASID_FIRST_VERSION;
 	}
-	CPU_CONTEXT(cpu, mm) = ASID_CACHE(cpu) = asid;
+	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
 }
 
 /*
@@ -82,31 +79,35 @@
 static inline int
 init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
-#ifndef CONFIG_SMP
-	mm->context = 0;
-#else
-	mm->context = (unsigned long)kmalloc(smp_num_cpus *
-				sizeof(unsigned long), GFP_KERNEL);
-	/*
- 	 * Init the "context" values so that a tlbpid allocation
-	 * happens on the first switch.
- 	 */
-	if (mm->context == 0)
-		return -ENOMEM;
-	memset((void *)mm->context, 0, smp_num_cpus * sizeof(unsigned long));
-#endif
+	int i;
+
+	for (i = 0; i < smp_num_cpus; i++)
+		cpu_context(i, mm) = 0;
 	return 0;
 }
 
 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)
+	if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
 		get_new_mmu_context(next, cpu);
 
-	set_entryhi(CPU_CONTEXT(cpu, next));
+	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,10 +116,6 @@
  */
 static inline void destroy_context(struct mm_struct *mm)
 {
-#ifdef CONFIG_SMP
-	if (mm->context)
-		kfree((void *)mm->context);
-#endif
 }
 
 /*
@@ -128,11 +125,44 @@
 static inline void
 activate_mm(struct mm_struct *prev, struct mm_struct *next)
 {
+	unsigned long flags;
+	int cpu = smp_processor_id();
+
+	local_irq_save(flags);
+
 	/* Unconditionally get a new ASID.  */
-	get_new_mmu_context(next, smp_processor_id());
+	get_new_mmu_context(next, cpu);
 
-	set_entryhi(CPU_CONTEXT(smp_processor_id(), next));
+	write_c0_entryhi(cpu_context(cpu, next));
 	TLBMISS_HANDLER_SETUP_PGD(next->pgd);
+
+	/* mark mmu ownership change */	
+	clear_bit(cpu, &prev->cpu_vm_mask);
+	set_bit(cpu, &next->cpu_vm_mask);
+
+	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_asid(cpu, mm));
+	} else {
+		/* will get a new context next time */
+		cpu_context(cpu, mm) = 0;
+	}
+
+	local_irq_restore(flags);
 }
 
 #endif /* _ASM_MMU_CONTEXT_H */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)