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
- Lines: 336
- Date:
2003-08-25 04:44:40.000000000 -0700
- Orig file:
linux-2.4.21/arch/mips/mm/tlb-r3k.c
- Orig date:
2002-11-28 15:53:10.000000000 -0800
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)