also update spec file ...
[linux-flexiantxendom0-3.2.10.git] / arch / mips / mm / tlbex-r4k.S
1 /*
2  * TLB exception handling code for r4k.
3  *
4  * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
5  *
6  * Multi-cpu abstraction and reworking:
7  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
8  *
9  * Carsten Langgaard, carstenl@mips.com
10  * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
11  */
12 #include <linux/init.h>
13 #include <linux/config.h>
14
15 #include <asm/asm.h>
16 #include <asm/offset.h>
17 #include <asm/cachectl.h>
18 #include <asm/fpregdef.h>
19 #include <asm/mipsregs.h>
20 #include <asm/page.h>
21 #include <asm/pgtable-bits.h>
22 #include <asm/processor.h>
23 #include <asm/regdef.h>
24 #include <asm/stackframe.h>
25 #include <asm/war.h>
26
27 #define TLB_OPTIMIZE /* If you are paranoid, disable this. */
28
29 #ifdef CONFIG_64BIT_PHYS_ADDR
30 #define PTE_L           ld
31 #define PTE_S           sd
32 #define PTE_SRL         dsrl
33 #define P_MTC0          dmtc0
34 #define PTE_SIZE        8
35 #define PTEP_INDX_MSK   0xff0
36 #define PTE_INDX_MSK    0xff8
37 #define PTE_INDX_SHIFT  9
38 #else
39 #define PTE_L           lw
40 #define PTE_S           sw
41 #define PTE_SRL         srl
42 #define P_MTC0          mtc0
43 #define PTE_SIZE        4
44 #define PTEP_INDX_MSK   0xff8
45 #define PTE_INDX_MSK    0xffc
46 #define PTE_INDX_SHIFT  10
47 #endif
48
49 /*
50  * ABUSE of CPP macros 101.
51  *
52  * After this macro runs, the pte faulted on is
53  * in register PTE, a ptr into the table in which
54  * the pte belongs is in PTR.
55  */
56
57 #ifdef CONFIG_SMP
58 #define GET_PGD(scratch, ptr)        \
59         mfc0    ptr, CP0_CONTEXT;    \
60         la      scratch, pgd_current;\
61         srl     ptr, 23;             \
62         sll     ptr, 2;              \
63         addu    ptr, scratch, ptr;   \
64         lw      ptr, (ptr);
65 #else
66 #define GET_PGD(scratch, ptr)    \
67         lw      ptr, pgd_current;
68 #endif
69
70 #define LOAD_PTE(pte, ptr) \
71         GET_PGD(pte, ptr)          \
72         mfc0    pte, CP0_BADVADDR; \
73         srl     pte, pte, _PGDIR_SHIFT; \
74         sll     pte, pte, 2; \
75         addu    ptr, ptr, pte; \
76         mfc0    pte, CP0_BADVADDR; \
77         lw      ptr, (ptr); \
78         srl     pte, pte, PTE_INDX_SHIFT; \
79         and     pte, pte, PTE_INDX_MSK; \
80         addu    ptr, ptr, pte; \
81         PTE_L   pte, (ptr);
82
83         /* This places the even/odd pte pair in the page
84          * table at PTR into ENTRYLO0 and ENTRYLO1 using
85          * TMP as a scratch register.
86          */
87 #define PTE_RELOAD(ptr, tmp) \
88         ori     ptr, ptr, PTE_SIZE; \
89         xori    ptr, ptr, PTE_SIZE; \
90         PTE_L   tmp, PTE_SIZE(ptr); \
91         PTE_L   ptr, 0(ptr); \
92         PTE_SRL tmp, tmp, 6; \
93         P_MTC0  tmp, CP0_ENTRYLO1; \
94         PTE_SRL ptr, ptr, 6; \
95         P_MTC0  ptr, CP0_ENTRYLO0;
96
97 #define DO_FAULT(write) \
98         .set    noat; \
99         SAVE_ALL; \
100         mfc0    a2, CP0_BADVADDR; \
101         KMODE; \
102         .set    at; \
103         move    a0, sp; \
104         jal     do_page_fault; \
105          li     a1, write; \
106         j       ret_from_exception; \
107          nop; \
108         .set    noat;
109
110         /* Check is PTE is present, if not then jump to LABEL.
111          * PTR points to the page table where this PTE is located,
112          * when the macro is done executing PTE will be restored
113          * with it's original value.
114          */
115 #define PTE_PRESENT(pte, ptr, label) \
116         andi    pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
117         xori    pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
118         bnez    pte, label; \
119          PTE_L  pte, (ptr);
120
121         /* Make PTE valid, store result in PTR. */
122 #define PTE_MAKEVALID(pte, ptr) \
123         ori     pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
124         PTE_S   pte, (ptr);
125
126         /* Check if PTE can be written to, if not branch to LABEL.
127          * Regardless restore PTE with value from PTR when done.
128          */
129 #define PTE_WRITABLE(pte, ptr, label) \
130         andi    pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
131         xori    pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
132         bnez    pte, label; \
133          PTE_L  pte, (ptr);
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         PTE_S   pte, (ptr);
142
143         __INIT
144
145 #ifdef CONFIG_64BIT_PHYS_ADDR
146 #define GET_PTE_OFF(reg)
147 #elif CONFIG_CPU_VR41XX
148 #define GET_PTE_OFF(reg)        srl     reg, reg, 3
149 #else
150 #define GET_PTE_OFF(reg)        srl     reg, reg, 1
151 #endif
152
153 /*
154  * These handlers much be written in a relocatable manner
155  * because based upon the cpu type an arbitrary one of the
156  * following pieces of code will be copied to the KSEG0
157  * vector location.
158  */
159         /* TLB refill, EXL == 0, R4xx0, non-R4600 version */
160         .set    noreorder
161         .set    noat
162         LEAF(except_vec0_r4000)
163         .set    mips3
164         GET_PGD(k0, k1)                         # get pgd pointer
165         mfc0    k0, CP0_BADVADDR                # Get faulting address
166         srl     k0, k0, _PGDIR_SHIFT            # get pgd only bits
167
168         sll     k0, k0, 2
169         addu    k1, k1, k0                      # add in pgd offset
170         mfc0    k0, CP0_CONTEXT                 # get context reg
171         lw      k1, (k1)
172         GET_PTE_OFF(k0)                         # get pte offset
173         and     k0, k0, PTEP_INDX_MSK
174         addu    k1, k1, k0                      # add in offset
175         PTE_L   k0, 0(k1)                       # get even pte
176         PTE_L   k1, PTE_SIZE(k1)                # get odd pte
177         PTE_SRL k0, k0, 6                       # convert to entrylo0
178         P_MTC0  k0, CP0_ENTRYLO0                # load it
179         PTE_SRL k1, k1, 6                       # convert to entrylo1
180         P_MTC0  k1, CP0_ENTRYLO1                # load it
181         b       1f
182         tlbwr                                   # write random tlb entry
183 1:
184         nop
185         eret                                    # return from trap
186         END(except_vec0_r4000)
187
188         /* TLB refill, EXL == 0, R4600 version */
189         LEAF(except_vec0_r4600)
190         .set    mips3
191         GET_PGD(k0, k1)                         # get pgd pointer
192         mfc0    k0, CP0_BADVADDR
193         srl     k0, k0, _PGDIR_SHIFT
194         sll     k0, k0, 2                       # log2(sizeof(pgd_t)
195         addu    k1, k1, k0
196         mfc0    k0, CP0_CONTEXT
197         lw      k1, (k1)
198         GET_PTE_OFF(k0)                         # get pte offset
199         and     k0, k0, PTEP_INDX_MSK
200         addu    k1, k1, k0
201         PTE_L   k0, 0(k1)
202         PTE_L   k1, PTE_SIZE(k1)
203         PTE_SRL k0, k0, 6
204         P_MTC0  k0, CP0_ENTRYLO0
205         PTE_SRL k1, k1, 6
206         P_MTC0  k1, CP0_ENTRYLO1
207         nop
208         tlbwr
209         nop
210         eret
211         END(except_vec0_r4600)
212
213         /* TLB refill, EXL == 0, R52x0 "Nevada" version */
214         /*
215          * This version has a bug workaround for the Nevada.  It seems
216          * as if under certain circumstances the move from cp0_context
217          * might produce a bogus result when the mfc0 instruction and
218          * it's consumer are in a different cacheline or a load instruction,
219          * probably any memory reference, is between them.  This is
220          * potencially slower than the R4000 version, so we use this
221          * special version.
222          */
223         .set    noreorder
224         .set    noat
225         LEAF(except_vec0_nevada)
226         .set    mips3
227         mfc0    k0, CP0_BADVADDR                # Get faulting address
228         srl     k0, k0, _PGDIR_SHIFT            # get pgd only bits
229         lw      k1, pgd_current                 # get pgd pointer
230         sll     k0, k0, 2                       # log2(sizeof(pgd_t)
231         addu    k1, k1, k0                      # add in pgd offset
232         lw      k1, (k1)
233         mfc0    k0, CP0_CONTEXT                 # get context reg
234         GET_PTE_OFF(k0)                         # get pte offset
235         and     k0, k0, PTEP_INDX_MSK
236         addu    k1, k1, k0                      # add in offset
237         PTE_L   k0, 0(k1)                       # get even pte
238         PTE_L   k1, PTE_SIZE(k1)                # get odd pte
239         PTE_SRL k0, k0, 6                       # convert to entrylo0
240         P_MTC0  k0, CP0_ENTRYLO0                # load it
241         PTE_SRL k1, k1, 6                       # convert to entrylo1
242         P_MTC0  k1, CP0_ENTRYLO1                # load it
243         nop                                     # QED specified nops
244         nop
245         tlbwr                                   # write random tlb entry
246         nop                                     # traditional nop
247         eret                                    # return from trap
248         END(except_vec0_nevada)
249
250         /* TLB refill, EXL == 0, SB1 with M3 errata handling version */
251         LEAF(except_vec0_sb1)
252 #if BCM1250_M3_WAR
253         mfc0    k0, CP0_BADVADDR
254         mfc0    k1, CP0_ENTRYHI
255         xor     k0, k1
256         srl     k0, k0, PAGE_SHIFT+1
257         bnez    k0, 1f
258 #endif
259         GET_PGD(k0, k1)                         # get pgd pointer
260         mfc0    k0, CP0_BADVADDR                # Get faulting address
261         srl     k0, k0, _PGDIR_SHIFT            # get pgd only bits
262         sll     k0, k0, 2
263         addu    k1, k1, k0                      # add in pgd offset
264         mfc0    k0, CP0_CONTEXT                 # get context reg
265         lw      k1, (k1)
266         GET_PTE_OFF(k0)                         # get pte offset
267         and     k0, k0, PTEP_INDX_MSK
268         addu    k1, k1, k0                      # add in offset
269         PTE_L   k0, 0(k1)                       # get even pte
270         PTE_L   k1, PTE_SIZE(k1)                # get odd pte
271         PTE_SRL k0, k0, 6                       # convert to entrylo0
272         P_MTC0  k0, CP0_ENTRYLO0                # load it
273         PTE_SRL k1, k1, 6                       # convert to entrylo1
274         P_MTC0  k1, CP0_ENTRYLO1                # load it
275         tlbwr                                   # write random tlb entry
276 1:      eret                                    # return from trap
277         END(except_vec0_sb1)
278
279         /* TLB refill, EXL == 0, R4[40]00/R5000 badvaddr hwbug version */
280         LEAF(except_vec0_r45k_bvahwbug)
281         .set    mips3
282         GET_PGD(k0, k1)                         # get pgd pointer
283         mfc0    k0, CP0_BADVADDR
284         srl     k0, k0, _PGDIR_SHIFT
285         sll     k0, k0, 2                       # log2(sizeof(pgd_t)
286         addu    k1, k1, k0
287         mfc0    k0, CP0_CONTEXT
288         lw      k1, (k1)
289 #ifndef CONFIG_64BIT_PHYS_ADDR
290         srl     k0, k0, 1
291 #endif
292         and     k0, k0, PTEP_INDX_MSK
293         addu    k1, k1, k0
294         PTE_L   k0, 0(k1)
295         PTE_L   k1, PTE_SIZE(k1)
296         nop                             /* XXX */
297         tlbp
298         PTE_SRL k0, k0, 6
299         P_MTC0  k0, CP0_ENTRYLO0
300         PTE_SRL k1, k1, 6
301         mfc0    k0, CP0_INDEX
302         P_MTC0  k1, CP0_ENTRYLO1
303         bltzl   k0, 1f
304         tlbwr
305 1:
306         nop
307         eret
308         END(except_vec0_r45k_bvahwbug)
309
310 #ifdef CONFIG_SMP
311         /* TLB refill, EXL == 0, R4000 MP badvaddr hwbug version */
312         LEAF(except_vec0_r4k_mphwbug)
313         .set    mips3
314         GET_PGD(k0, k1)                         # get pgd pointer
315         mfc0    k0, CP0_BADVADDR
316         srl     k0, k0, _PGDIR_SHIFT
317         sll     k0, k0, 2                       # log2(sizeof(pgd_t)
318         addu    k1, k1, k0
319         mfc0    k0, CP0_CONTEXT
320         lw      k1, (k1)
321 #ifndef CONFIG_64BIT_PHYS_ADDR
322         srl     k0, k0, 1
323 #endif
324         and     k0, k0, PTEP_INDX_MSK
325         addu    k1, k1, k0
326         PTE_L   k0, 0(k1)
327         PTE_L   k1, PTE_SIZE(k1)
328         nop                             /* XXX */
329         tlbp
330         PTE_SRL k0, k0, 6
331         P_MTC0  k0, CP0_ENTRYLO0
332         PTE_SRL k1, k1, 6
333         mfc0    k0, CP0_INDEX
334         P_MTC0  k1, CP0_ENTRYLO1
335         bltzl   k0, 1f
336         tlbwr
337 1:
338         nop
339         eret
340         END(except_vec0_r4k_mphwbug)
341 #endif
342
343         /* TLB refill, EXL == 0, R4000 UP 250MHZ entrylo[01] hwbug version */
344         LEAF(except_vec0_r4k_250MHZhwbug)
345         .set    mips3
346         GET_PGD(k0, k1)                         # get pgd pointer
347         mfc0    k0, CP0_BADVADDR
348         srl     k0, k0, _PGDIR_SHIFT
349         sll     k0, k0, 2                       # log2(sizeof(pgd_t)
350         addu    k1, k1, k0
351         mfc0    k0, CP0_CONTEXT
352         lw      k1, (k1)
353 #ifndef CONFIG_64BIT_PHYS_ADDR
354         srl     k0, k0, 1
355 #endif
356         and     k0, k0, PTEP_INDX_MSK
357         addu    k1, k1, k0
358         PTE_L   k0, 0(k1)
359         PTE_L   k1, PTE_SIZE(k1)
360         PTE_SRL k0, k0, 6
361         P_MTC0  zero, CP0_ENTRYLO0
362         P_MTC0  k0, CP0_ENTRYLO0
363         PTE_SRL k1, k1, 6
364         P_MTC0  zero, CP0_ENTRYLO1
365         P_MTC0  k1, CP0_ENTRYLO1
366         b       1f
367         tlbwr
368 1:
369         nop
370         eret
371         END(except_vec0_r4k_250MHZhwbug)
372
373 #ifdef CONFIG_SMP
374         /* TLB refill, EXL == 0, R4000 MP 250MHZ entrylo[01]+badvaddr bug version */
375         LEAF(except_vec0_r4k_MP250MHZhwbug)
376         .set    mips3
377         GET_PGD(k0, k1)                         # get pgd pointer
378         mfc0    k0, CP0_BADVADDR
379         srl     k0, k0, _PGDIR_SHIFT
380         sll     k0, k0, 2                       # log2(sizeof(pgd_t)
381         addu    k1, k1, k0
382         mfc0    k0, CP0_CONTEXT
383         lw      k1, (k1)
384 #ifndef CONFIG_64BIT_PHYS_ADDR
385         srl     k0, k0, 1
386 #endif
387         and     k0, k0, PTEP_INDX_MSK
388         addu    k1, k1, k0
389         PTE_L   k0, 0(k1)
390         PTE_L   k1, PTE_SIZE(k1)
391         nop                             /* XXX */
392         tlbp
393         PTE_SRL k0, k0, 6
394         P_MTC0  zero, CP0_ENTRYLO0
395         P_MTC0  k0, CP0_ENTRYLO0
396         mfc0    k0, CP0_INDEX
397         PTE_SRL k1, k1, 6
398         P_MTC0  zero, CP0_ENTRYLO1
399         P_MTC0  k1, CP0_ENTRYLO1
400         bltzl   k0, 1f
401         tlbwr
402 1:
403         nop
404         eret
405         END(except_vec0_r4k_MP250MHZhwbug)
406 #endif
407
408         __FINIT
409
410         .set    noreorder
411
412 /*
413  * From the IDT errata for the QED RM5230 (Nevada), processor revision 1.0:
414  * 2. A timing hazard exists for the TLBP instruction.
415  *
416  *      stalling_instruction
417  *      TLBP
418  *
419  * The JTLB is being read for the TLBP throughout the stall generated by the
420  * previous instruction. This is not really correct as the stalling instruction
421  * can modify the address used to access the JTLB.  The failure symptom is that
422  * the TLBP instruction will use an address created for the stalling instruction
423  * and not the address held in C0_ENHI and thus report the wrong results.
424  *
425  * The software work-around is to not allow the instruction preceding the TLBP
426  * to stall - make it an NOP or some other instruction guaranteed not to stall.
427  *
428  * Errata 2 will not be fixed.  This errata is also on the R5000.
429  *
430  * As if we MIPS hackers wouldn't know how to nop pipelines happy ...
431  */
432 #define R5K_HAZARD nop
433
434         /*
435          * Note for many R4k variants tlb probes cannot be executed out
436          * of the instruction cache else you get bogus results.
437          */
438         .align  5
439         NESTED(handle_tlbl, PT_SIZE, sp)
440         .set    noat
441 #if BCM1250_M3_WAR
442         mfc0    k0, CP0_BADVADDR
443         mfc0    k1, CP0_ENTRYHI
444         xor     k0, k1
445         srl     k0, k0, PAGE_SHIFT+1
446         beqz    k0, 1f
447          nop
448         .set    mips3
449         eret
450         .set    mips0
451 1:
452 #endif
453 invalid_tlbl:
454 #ifdef TLB_OPTIMIZE
455         /* Test present bit in entry. */
456         LOAD_PTE(k0, k1)
457         R5K_HAZARD
458         tlbp
459         PTE_PRESENT(k0, k1, nopage_tlbl)
460         PTE_MAKEVALID(k0, k1)
461         PTE_RELOAD(k1, k0)
462         nop
463         b       1f
464          tlbwi
465 1:
466         nop
467         .set    mips3
468         eret
469         .set    mips0
470 #endif
471
472 nopage_tlbl:
473         DO_FAULT(0)
474         END(handle_tlbl)
475
476         .align  5
477         NESTED(handle_tlbs, PT_SIZE, sp)
478         .set    noat
479 #ifdef TLB_OPTIMIZE
480         .set    mips3
481         li      k0,0
482         LOAD_PTE(k0, k1)
483         R5K_HAZARD
484         tlbp                            # find faulting entry
485         PTE_WRITABLE(k0, k1, nopage_tlbs)
486         PTE_MAKEWRITE(k0, k1)
487         PTE_RELOAD(k1, k0)
488         nop
489         b       1f
490          tlbwi
491 1:
492         nop
493         .set    mips3
494         eret
495         .set    mips0
496 #endif
497
498 nopage_tlbs:
499         DO_FAULT(1)
500         END(handle_tlbs)
501
502         .align  5
503         NESTED(handle_mod, PT_SIZE, sp)
504         .set    noat
505 #ifdef TLB_OPTIMIZE
506         .set    mips3
507         LOAD_PTE(k0, k1)
508         R5K_HAZARD
509         tlbp                                    # find faulting entry
510         andi    k0, k0, _PAGE_WRITE
511         beqz    k0, nowrite_mod
512          PTE_L  k0, (k1)
513
514         /* Present and writable bits set, set accessed and dirty bits. */
515         PTE_MAKEWRITE(k0, k1)
516
517         /* Now reload the entry into the tlb. */
518         PTE_RELOAD(k1, k0)
519         nop
520         b       1f
521          tlbwi
522 1:
523         nop
524         .set    mips3
525         eret
526         .set    mips0
527 #endif
528
529 nowrite_mod:
530         DO_FAULT(1)
531         END(handle_mod)
532