patch-2.4.22 linux-2.4.22/arch/mips/mm/tlb-r3k.c

Next file: linux-2.4.22/arch/mips/mm/tlb-r4k.c
Previous file: linux-2.4.22/arch/mips/mm/sc-rm7k.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/arch/mips/mm/tlb-r3k.c linux-2.4.22/arch/mips/mm/tlb-r3k.c
@@ -7,6 +7,8 @@
  * Tx39XX R4k style caches added. HK
  * Copyright (C) 1998, 1999, 2000 Harald Koerfgen
  * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ * Copyright (C) 2002  Ralf Baechle
+ * Copyright (C) 2002  Maciej W. Rozycki
  */
 #include <linux/config.h>
 #include <linux/init.h>
@@ -23,11 +25,19 @@
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
 
+#undef DEBUG_TLB
+
 extern char except_vec0_r2300;
 
-#undef DEBUG_TLB
+/* CP0 hazard avoidance. */
+#define BARRIER				\
+	__asm__ __volatile__(		\
+		".set	push\n\t"	\
+		".set	noreorder\n\t"	\
+		"nop\n\t"		\
+		".set	pop\n\t")
 
-int r3k_have_wired_reg = 0;	/* should be in mips_cpu? */
+int r3k_have_wired_reg;		/* should be in cpu_data? */
 
 /* TLB operations. */
 void local_flush_tlb_all(void)
@@ -40,117 +50,109 @@
 	printk("[tlball]");
 #endif
 
-	save_and_cli(flags);
-	old_ctx = (get_entryhi() & 0xfc0);
-	write_32bit_cp0_register(CP0_ENTRYLO0, 0);
-#ifdef CONFIG_CPU_TX39XX
-	entry = r3k_have_wired_reg ? get_wired() : 8;
-#else
-	entry = 8;
-#endif
-	for (; entry < mips_cpu.tlbsize; entry++) {
-		write_32bit_cp0_register(CP0_INDEX, entry << 8);
-		write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x80000) << 12));
-		__asm__ __volatile__("tlbwi");
+	local_irq_save(flags);
+	old_ctx = read_c0_entryhi() & ASID_MASK;
+	write_c0_entrylo0(0);
+	entry = r3k_have_wired_reg ? read_c0_wired() : 8;
+	for (; entry < current_cpu_data.tlbsize; entry++) {
+		write_c0_index(entry << 8);
+		write_c0_entryhi((entry | 0x80000) << 12);
+		BARRIER;
+		tlb_write_indexed();
 	}
-	set_entryhi(old_ctx);
-	restore_flags(flags);
+	write_c0_entryhi(old_ctx);
+	local_irq_restore(flags);
 }
 
 void local_flush_tlb_mm(struct mm_struct *mm)
 {
-	if (mm->context != 0) {
-		unsigned long flags;
+	int cpu = smp_processor_id();
 
+	if (cpu_context(cpu, mm) != 0) {
 #ifdef DEBUG_TLB
-		printk("[tlbmm<%lu>]", (unsigned long) mm->context);
+		printk("[tlbmm<%lu>]", (unsigned long)cpu_context(cpu, mm));
 #endif
-		save_and_cli(flags);
-		get_new_mmu_context(mm, smp_processor_id());
-		if (mm == current->active_mm)
-			set_entryhi(mm->context & 0xfc0);
-		restore_flags(flags);
+		drop_mmu_context(mm, cpu);
 	}
 }
 
 void local_flush_tlb_range(struct mm_struct *mm, unsigned long start,
-                     unsigned long end)
+			   unsigned long end)
 {
-	if (mm->context != 0) {
+	int cpu = smp_processor_id();
+
+	if (cpu_context(cpu, mm) != 0) {
 		unsigned long flags;
 		int size;
 
 #ifdef DEBUG_TLB
 		printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",
-			(mm->context & 0xfc0), start, end);
+			cpu_asid(cpu, mm), start, end);
 #endif
-		save_and_cli(flags);
+		local_irq_save(flags);
 		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-		if (size <= mips_cpu.tlbsize) {
-			int oldpid = (get_entryhi() & 0xfc0);
-			int newpid = (mm->context & 0xfc0);
+		if (size <= current_cpu_data.tlbsize) {
+			int oldpid = read_c0_entryhi() & ASID_MASK;
+			int newpid = cpu_asid(cpu, mm);
 
 			start &= PAGE_MASK;
-			end += (PAGE_SIZE - 1);
+			end += PAGE_SIZE - 1;
 			end &= PAGE_MASK;
 			while (start < end) {
 				int idx;
 
-				set_entryhi(start | newpid);
-				start += PAGE_SIZE;
+				write_c0_entryhi(start | newpid);
+				start += PAGE_SIZE;	/* BARRIER */
 				tlb_probe();
-				idx = get_index();
-				set_entrylo0(0);
-				set_entryhi(KSEG0);
-				if (idx < 0)
+				idx = read_c0_index();
+				write_c0_entrylo0(0);
+				write_c0_entryhi(KSEG0);
+				if (idx < 0)		/* BARRIER */
 					continue;
 				tlb_write_indexed();
 			}
-			set_entryhi(oldpid);
+			write_c0_entryhi(oldpid);
 		} else {
-			get_new_mmu_context(mm, smp_processor_id());
-			if (mm == current->active_mm)
-				set_entryhi(mm->context & 0xfc0);
+			drop_mmu_context(mm, cpu);
 		}
-		restore_flags(flags);
+		local_irq_restore(flags);
 	}
 }
 
 void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
-	if (!vma || vma->vm_mm->context != 0) {
+	int cpu = smp_processor_id();
+
+	if (!vma || cpu_context(cpu, vma->vm_mm) != 0) {
 		unsigned long flags;
 		int oldpid, newpid, idx;
 
 #ifdef DEBUG_TLB
-		printk("[tlbpage<%lu,0x%08lx>]", vma->vm_mm->context, page);
+		printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page);
 #endif
-		newpid = (vma->vm_mm->context & 0xfc0);
+		newpid = cpu_asid(cpu, vma->vm_mm);
 		page &= PAGE_MASK;
-		save_and_cli(flags);
-		oldpid = (get_entryhi() & 0xfc0);
-		set_entryhi(page | newpid);
+		local_irq_save(flags);
+		oldpid = read_c0_entryhi() & ASID_MASK;
+		write_c0_entryhi(page | newpid);
+		BARRIER;
 		tlb_probe();
-		idx = get_index();
-		set_entrylo0(0);
-		set_entryhi(KSEG0);
-		if (idx < 0)
+		idx = read_c0_index();
+		write_c0_entrylo0(0);
+		write_c0_entryhi(KSEG0);
+		if (idx < 0)				/* BARRIER */
 			goto finish;
 		tlb_write_indexed();
 
 finish:
-		set_entryhi(oldpid);
-		restore_flags(flags);
+		write_c0_entryhi(oldpid);
+		local_irq_restore(flags);
 	}
 }
 
-void update_mmu_cache(struct vm_area_struct * vma, unsigned long address,
-                      pte_t pte)
+void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
 	unsigned long flags;
-	pgd_t *pgdp;
-	pmd_t *pmdp;
-	pte_t *ptep;
 	int idx, pid;
 
 	/*
@@ -159,92 +161,86 @@
 	if (current->active_mm != vma->vm_mm)
 		return;
 
-	pid = get_entryhi() & 0xfc0;
+	pid = read_c0_entryhi() & ASID_MASK;
 
 #ifdef DEBUG_TLB
-	if ((pid != (vma->vm_mm->context & 0xfc0)) || (vma->vm_mm->context == 0)) {
+	if ((pid != cpu_asid(cpu, vma->vm_mm)) || (cpu_context(cpu, vma->vm_mm) == 0)) {
 		printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",
-		       (vma->vm_mm->context & 0xfc0), pid);
+		       (cpu_context(cpu, vma->vm_mm)), pid);
 	}
 #endif
 
-	save_and_cli(flags);
+	local_irq_save(flags);
 	address &= PAGE_MASK;
-	set_entryhi(address | (pid));
-	pgdp = pgd_offset(vma->vm_mm, address);
+	write_c0_entryhi(address | pid);
+	BARRIER;
 	tlb_probe();
-	pmdp = pmd_offset(pgdp, address);
-	idx = get_index();
-	ptep = pte_offset(pmdp, address);
-	set_entrylo0(pte_val(*ptep));
-	set_entryhi(address | (pid));
-	if (idx < 0) {
+	idx = read_c0_index();
+	write_c0_entrylo0(pte_val(pte));
+	write_c0_entryhi(address | pid);
+	if (idx < 0) {					/* BARRIER */
 		tlb_write_random();
-#if 0
-		printk("[MISS]");
-#endif
 	} else {
 		tlb_write_indexed();
-#if 0
-		printk("[HIT]");
-#endif
 	}
-	set_entryhi(pid);
-	restore_flags(flags);
+	write_c0_entryhi(pid);
+	local_irq_restore(flags);
 }
 
 void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
-                     unsigned long entryhi, unsigned long pagemask)
+			    unsigned long entryhi, unsigned long pagemask)
 {
 	unsigned long flags;
 	unsigned long old_ctx;
 	static unsigned long wired = 0;
 
-#ifdef CONFIG_CPU_TX39XX
-	if (r3k_have_wired_reg) {
+	if (r3k_have_wired_reg) {			/* TX39XX */
 		unsigned long old_pagemask;
 		unsigned long w;
 
 #ifdef DEBUG_TLB
-		printk("[tlbwired]");
-		printk("ently lo0 %8x, hi %8x\n, pagemask %8x\n",
+		printk("[tlbwired<entry lo0 %8x, hi %8x\n, pagemask %8x>]\n",
 		       entrylo0, entryhi, pagemask);
 #endif
-		save_and_cli(flags);
+
+		local_irq_save(flags);
 		/* Save old context and create impossible VPN2 value */
-		old_ctx = (get_entryhi() & 0xff);
-		old_pagemask = get_pagemask();
-		w = get_wired();
-		set_wired (w + 1);
-		if (get_wired() != w + 1) {
+		old_ctx = read_c0_entryhi() & ASID_MASK;
+		old_pagemask = read_c0_pagemask();
+		w = read_c0_wired();
+		write_c0_wired(w + 1);
+		if (read_c0_wired() != w + 1) {
 			printk("[tlbwired] No WIRED reg?\n");
 			return;
 		}
-		set_index (w << 8);
-		set_pagemask (pagemask);
-		set_entryhi(entryhi);
-		set_entrylo0(entrylo0);
+		write_c0_index(w << 8);
+		write_c0_pagemask(pagemask);
+		write_c0_entryhi(entryhi);
+		write_c0_entrylo0(entrylo0);
+		BARRIER;
 		tlb_write_indexed();
 
-		set_entryhi(old_ctx);
-		set_pagemask (old_pagemask);
+		write_c0_entryhi(old_ctx);
+		write_c0_pagemask(old_pagemask);
 		local_flush_tlb_all();
-		restore_flags(flags);
-		return;
-	}
+		local_irq_restore(flags);
+
+	} else if (wired < 8) {
+#ifdef DEBUG_TLB
+		printk("[tlbwired<entry lo0 %8x, hi %8x\n>]\n",
+		       entrylo0, entryhi);
 #endif
 
-	if (wired < 8) {
-		__save_and_cli(flags);
-		old_ctx = get_entryhi() & 0xfc0;
-		set_entrylo0(entrylo0);
-		set_entryhi(entryhi);
-		set_index(wired);
-		wired++;
+		local_irq_save(flags);
+		old_ctx = read_c0_entryhi() & ASID_MASK;
+		write_c0_entrylo0(entrylo0);
+		write_c0_entryhi(entryhi);
+		write_c0_index(wired);
+		wired++;				/* BARRIER */
 		tlb_write_indexed();
-		set_entryhi(old_ctx);
-	        local_flush_tlb_all();
-		__restore_flags(flags);
+		write_c0_entryhi(old_ctx);
+		local_flush_tlb_all();
+		local_irq_restore(flags);
 	}
 }
 

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