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
- Lines: 148
- Date:
2003-08-25 04:44:43.000000000 -0700
- Orig file:
linux-2.4.21/include/asm-mips/mmu_context.h
- Orig date:
2002-11-28 15:53:15.000000000 -0800
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)