1/* 2 * TLB exception handling code for R2000/R3000. 3 * 4 * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse 5 * 6 * Multi-CPU abstraction reworking: 7 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 8 * 9 * Further modifications to make this work: 10 * Copyright (c) 1998 Harald Koerfgen 11 * Copyright (c) 1998, 1999 Gleb Raiko & Vladimir Roganov 12 * Copyright (c) 2001 Ralf Baechle 13 * Copyright (c) 2001 MIPS Technologies, Inc. 14 */ 15#include <linux/init.h> 16#include <asm/asm.h> 17#include <asm/current.h> 18#include <asm/cachectl.h> 19#include <asm/fpregdef.h> 20#include <asm/mipsregs.h> 21#include <asm/page.h> 22#include <asm/pgtable-bits.h> 23#include <asm/processor.h> 24#include <asm/regdef.h> 25#include <asm/stackframe.h> 26 27#define TLB_OPTIMIZE /* If you are paranoid, disable this. */ 28 29 .text 30 .set mips1 31 .set noreorder 32 33 __INIT 34 35 /* TLB refill, R[23]00 version */ 36 LEAF(except_vec0_r2300) 37 .set noat 38 .set mips1 39 mfc0 k0, CP0_BADVADDR 40 lw k1, pgd_current # get pgd pointer 41 srl k0, k0, 22 42 sll k0, k0, 2 43 addu k1, k1, k0 44 mfc0 k0, CP0_CONTEXT 45 lw k1, (k1) 46 and k0, k0, 0xffc 47 addu k1, k1, k0 48 lw k0, (k1) 49 nop 50 mtc0 k0, CP0_ENTRYLO0 51 mfc0 k1, CP0_EPC 52 tlbwr 53 jr k1 54 rfe 55 END(except_vec0_r2300) 56 57 __FINIT 58 59 /* ABUSE of CPP macros 101. */ 60 61 /* After this macro runs, the pte faulted on is 62 * in register PTE, a ptr into the table in which 63 * the pte belongs is in PTR. 64 */ 65#define LOAD_PTE(pte, ptr) \ 66 mfc0 pte, CP0_BADVADDR; \ 67 lw ptr, pgd_current; \ 68 srl pte, pte, 22; \ 69 sll pte, pte, 2; \ 70 addu ptr, ptr, pte; \ 71 mfc0 pte, CP0_CONTEXT; \ 72 lw ptr, (ptr); \ 73 andi pte, pte, 0xffc; \ 74 addu ptr, ptr, pte; \ 75 lw pte, (ptr); \ 76 nop; 77 78 /* This places the even/odd pte pair in the page 79 * table at PTR into ENTRYLO0 and ENTRYLO1 using 80 * TMP as a scratch register. 81 */ 82#define PTE_RELOAD(ptr) \ 83 lw ptr, (ptr) ; \ 84 nop ; \ 85 mtc0 ptr, CP0_ENTRYLO0; \ 86 nop; 87 88#define DO_FAULT(write) \ 89 .set noat; \ 90 .set macro; \ 91 SAVE_ALL; \ 92 mfc0 a2, CP0_BADVADDR; \ 93 KMODE; \ 94 .set at; \ 95 move a0, sp; \ 96 jal do_page_fault; \ 97 li a1, write; \ 98 j ret_from_exception; \ 99 nop; \ 100 .set noat; \ 101 .set nomacro; 102 103 /* Check is PTE is present, if not then jump to LABEL. 104 * PTR points to the page table where this PTE is located, 105 * when the macro is done executing PTE will be restored 106 * with it's original value. 107 */ 108#define PTE_PRESENT(pte, ptr, label) \ 109 andi pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ 110 xori pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ 111 bnez pte, label; \ 112 .set push; \ 113 .set reorder; \ 114 lw pte, (ptr); \ 115 .set pop; 116 117 /* Make PTE valid, store result in PTR. */ 118#define PTE_MAKEVALID(pte, ptr) \ 119 ori pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \ 120 sw pte, (ptr); 121 122 /* Check if PTE can be written to, if not branch to LABEL. 123 * Regardless restore PTE with value from PTR when done. 124 */ 125#define PTE_WRITABLE(pte, ptr, label) \ 126 andi pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ 127 xori pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ 128 bnez pte, label; \ 129 .set push; \ 130 .set reorder; \ 131 lw pte, (ptr); \ 132 .set pop; 133 134 135 /* Make PTE writable, update software status bits as well, 136 * then store at PTR. 137 */ 138#define PTE_MAKEWRITE(pte, ptr) \ 139 ori pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \ 140 _PAGE_VALID | _PAGE_DIRTY); \ 141 sw pte, (ptr); 142 143/* 144 * The index register may have the probe fail bit set, 145 * because we would trap on access kseg2, i.e. without refill. 146 */ 147#define TLB_WRITE(reg) \ 148 mfc0 reg, CP0_INDEX; \ 149 nop; \ 150 bltz reg, 1f; \ 151 nop; \ 152 tlbwi; \ 153 j 2f; \ 154 nop; \ 1551: tlbwr; \ 1562: 157 158#define RET(reg) \ 159 mfc0 reg, CP0_EPC; \ 160 nop; \ 161 jr reg; \ 162 rfe 163 164 .set noreorder 165 166 .align 5 167NESTED(handle_tlbl, PT_SIZE, sp) 168 .set noat 169 170#ifdef TLB_OPTIMIZE 171 /* Test present bit in entry. */ 172 LOAD_PTE(k0, k1) 173 tlbp 174 PTE_PRESENT(k0, k1, nopage_tlbl) 175 PTE_MAKEVALID(k0, k1) 176 PTE_RELOAD(k1) 177 TLB_WRITE(k0) 178 RET(k0) 179nopage_tlbl: 180#endif 181 182 DO_FAULT(0) 183END(handle_tlbl) 184 185NESTED(handle_tlbs, PT_SIZE, sp) 186 .set noat 187 188#ifdef TLB_OPTIMIZE 189 LOAD_PTE(k0, k1) 190 tlbp # find faulting entry 191 PTE_WRITABLE(k0, k1, nopage_tlbs) 192 PTE_MAKEWRITE(k0, k1) 193 PTE_RELOAD(k1) 194 TLB_WRITE(k0) 195 RET(k0) 196nopage_tlbs: 197#endif 198 199 DO_FAULT(1) 200END(handle_tlbs) 201 202 .align 5 203NESTED(handle_mod, PT_SIZE, sp) 204 .set noat 205#ifdef TLB_OPTIMIZE 206 LOAD_PTE(k0, k1) 207 tlbp # find faulting entry 208 andi k0, k0, _PAGE_WRITE 209 beqz k0, nowrite_mod 210 .set push 211 .set reorder 212 lw k0, (k1) 213 .set pop 214 215 /* Present and writable bits set, set accessed and dirty bits. */ 216 PTE_MAKEWRITE(k0, k1) 217 218 /* Now reload the entry into the tlb. */ 219 PTE_RELOAD(k1) 220 tlbwi 221 RET(k0) 222#endif 223 224nowrite_mod: 225 DO_FAULT(1) 226END(handle_mod) 227