more debug output
[linux-2.4.git] / arch / mips / mm / tlbex-r3k.S
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; \
155 1:      tlbwr; \
156 2:
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
167 NESTED(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)
179 nopage_tlbl:
180 #endif
181
182         DO_FAULT(0)
183 END(handle_tlbl)
184
185 NESTED(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)
196 nopage_tlbs:
197 #endif
198
199         DO_FAULT(1)
200 END(handle_tlbs)
201
202         .align  5
203 NESTED(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
224 nowrite_mod:
225         DO_FAULT(1)
226 END(handle_mod)