Import 2.3.9pre4
[davej-history.git] / arch / mips / kernel / r2300_misc.S
blobae52a96f22bf478ca2445c921f2e6734fb0ffa46
1 /* $Id: r2300_misc.S,v 1.1.1.1 1997/06/01 03:16:42 ralf Exp $
2  * r2300_misc.S: Misc. exception handling code for R3000/R2000.
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 #include <linux/config.h>
11 #include <asm/asm.h>
12 #include <asm/bootinfo.h>
13 #include <asm/cachectl.h>
14 #include <asm/fpregdef.h>
15 #include <asm/mipsconfig.h>
16 #include <asm/mipsregs.h>
17 #include <asm/page.h>
18 #include <asm/pgtable.h>
19 #include <asm/processor.h>
20 #include <asm/regdef.h>
21 #include <asm/stackframe.h>
23         .text
24         .set    mips1
25         .set    noreorder
27         .align  5
28         NESTED(r2300_handle_tlbl, PT_SIZE, sp)
29         .set    noat
30         /* Check whether this is a refill or an invalid exception */
31         mfc0    k0,CP0_BADVADDR
32         mfc0    k1,CP0_ENTRYHI
33         ori     k0,0xfff                        # clear ASID...
34         xori    k0,0xfff                        # in BadVAddr
35         andi    k1,0xfc0                        # get current ASID
36         or      k0,k1                           # make new entryhi
37         mfc0    k1,CP0_ENTRYHI
38         mtc0    k0,CP0_ENTRYHI
39         nop                                     # for pipeline
40         nop
41         nop
42         tlbp
43         nop                                     # for pipeline
44         nop
45         mfc0    k0,CP0_INDEX
47         bgez    k0,invalid_tlbl                 # bad addr in c0_badvaddr
48          mtc0   k1,CP0_ENTRYHI
50         /* Damn... The next nop is required on the R4400PC V5.0, but
51          * I don't know why - at least there is no documented
52          * reason as for the others :-(
53          * And I haven't tested it as being necessary on R3000 - PMA.
54          * (The R3000 pipeline has only 5 stages, so it's probably not
55          * required -- Ralf)
56          */
57         nop
59 #ifdef CONF_DEBUG_TLB
60         /* OK, this is a double fault. Let's see whether this is
61          * due to an invalid entry in the page_table.
62          */
63         /* used to be dmfc0 */
64         mfc0    k0,CP0_BADVADDR
65         /* FIXME: This srl/sll sequence is as it is for the R4xx0,
66          *        and I suspect that it should be different for
67          *        the R[23]000.  PMA
68          *        (No, it's the assembler way to do
69          *            k0 = k0 / PAGE_SIZE;
70          *            k0 = k0 * sizeof(pte_t)
71          *        Acutally the R4xx0 code will have to change when
72          *        switching to 64 bit ... -- Ralf)
73          */
74         srl     k0,12                           # get PFN?
75         sll     k0,2
76         lui     k1,%HI(TLBMAP)
77         addu    k0,k1
78         lw      k1,(k0)
79         andi    k1,(_PAGE_PRESENT|_PAGE_ACCESSED)
80         bnez    k1,reload_pgd_entries
81          nop
83         .set    noat
84         SAVE_ALL
85         .set    at
86         PRINT("Double fault caused by invalid entries in pgd:\n")
87         mfc0    a1,CP0_BADVADDR
88         PRINT("Double fault address     : %08lx\n")
89         mfc0    a1,CP0_EPC
90         PRINT("c0_epc                   : %08lx\n")
92         jal     show_regs
93          move   a0,sp
95         jal     dump_tlb_nonwired
96          nop
98         mfc0    a0,CP0_BADVADDR
100         jal     dump_list_current
101          nop
103         .set    noat
104         STI
105         .set    at
106         PANIC("Corrupted pagedir")
107         .set    noat
109 reload_pgd_entries:
110 #endif /* CONF_DEBUG_TLB */
112         /* Load missing pair of entries from the pgd and return. */
113         mfc0    k1,CP0_CONTEXT
114         lw      k0,(k1)                 # Never causes nested exception
115         mfc0    k1,CP0_EPC              # get the return PC
116         srl     k0,12                   # Convert to EntryLo format
117         mtc0    k0,CP0_ENTRYLO0
118         nop                             # for pipeline
119         tlbwr
120         nop                             # for pipeline
121         nop
122         nop
123         /* We don't know whether the original access was read or
124          * write, so return and see what happens...
125          */
126         jr      k1
127          rfe
129         /* Handle invalid exception
130          *
131          * There are two possible causes for an invalid (tlbl)
132          * exception:
133          * 1) pages with present bit set but the valid bit clear
134          * 2) nonexistant pages
135          * Case one needs fast handling, therefore don't save
136          * registers yet.
137          *
138          * k0 contains c0_index.
139          */
140 invalid_tlbl:   
141 #ifdef CONFIG_TLB_SHUTDOWN
142         /* Remove entry so we don't need to care later
143          * For sake of the pipeline the tlbwi insn has been moved down.
144          * Moving it around is juggling with explosives...
145          */
146         /* FIXME: Why is Ralf setting bit 3 of k1?  This may need to
147          *        be changed for R[236]000! PMA
148          *        (The new ENTRYHI value will then point represent a
149          *        inique virtual address outside the 32 bit address
150          *        limit.  This is just paranoia to avoid a tlb
151          *        shutdown.  This whole part of the routine is probably
152          *        no longer required and can be removed -- Ralf)
153          */
154         lui     k1,0x0008
155         or      k0,k1
156         sll     k0,12                           # make it EntryHi format
157         mtc0    k0,CP0_ENTRYHI
158         mtc0    zero,CP0_ENTRYLO0
159 #endif
160         /* Test present bit in entry */
161         mfc0    k0,CP0_BADVADDR
162         /* FIXME: This srl/sll sequence is as it is for the R4xx0,
163          *        and I suspect that it should be different for
164          *        the R[23]000.  PMA
165          *        (No, it's the assembler way to do
166          *            k0 = k0 / PAGE_SIZE;
167          *            k0 = k0 * sizeof(pte_t)
168          *        Acutally the R4xx0 code will have to change when
169          *        switching to 64 bit ... -- Ralf)
170          */
171         srl     k0,12
172         sll     k0,2
173 #ifdef CONFIG_TLB_SHUTDOWN
174         tlbwi                                           # do not move!
175 #endif
176         lui     k1,%HI(TLBMAP)
177         addu    k0,k1
178         lw      k1,(k0)
179         andi    k1,(_PAGE_PRESENT|_PAGE_READ)
180         xori    k1,(_PAGE_PRESENT|_PAGE_READ)
182         bnez    k1,nopage_tlbl
183          lw     k1,(k0)
185         /* Present and read bits are set -> set valid and accessed bits */
186         ori     k1,(_PAGE_VALID|_PAGE_ACCESSED)
187         sw      k1,(k0)
188         mfc0    k1,CP0_EPC
189         nop
191         jr      k1
192          rfe
194         /* Page doesn't exist. Lots of work which is less important
195          * for speed needs to be done, so hand it all over to the
196          * kernel memory management routines.
197          */
198 nopage_tlbl:
199         SAVE_ALL
200         mfc0    a2,CP0_BADVADDR
201         STI
202         .set    at
203         /* a0 (struct pt_regs *) regs
204          * a1 (unsigned long)    0 for read access
205          * a2 (unsigned long)    faulting virtual address
206          */
207         move    a0,sp
208         jal     do_page_fault
209          li     a1,0
211         j       ret_from_sys_call
212          nop
213         END(r2300_handle_tlbl)
216         .text
217         .align  5
218         NESTED(r2300_handle_tlbs, PT_SIZE, sp)
219         .set    noat
220         /* It is impossible that is a nested reload exception.
221          * Therefore this must be a invalid exception.
222          * Two possible cases:
223          * 1) Page exists but not dirty.
224          * 2) Page doesn't exist yet. Hand over to the kernel.
225          *
226          * Test whether present bit in entry is set
227          */
228         /* used to be dmfc0 */
229         mfc0    k0,CP0_BADVADDR
230         /* FIXME: This srl/sll sequence is as it is for the R4xx0,
231          *        and I suspect that it should be different for
232          *        the R[23]000.  PMA
233          */
234         srl     k0,12
235         sll     k0,2
236         lui     k1,%HI(TLBMAP)
237         addu    k0,k1
238         lw      k1,(k0)
239         tlbp                                    # find faulting entry
240         andi    k1,(_PAGE_PRESENT|_PAGE_WRITE)
241         xori    k1,(_PAGE_PRESENT|_PAGE_WRITE)
243         bnez    k1,nopage_tlbs
244          lw     k1,(k0)
246         /* Present and writable bits set: set accessed and dirty bits. */
247         ori     k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \
248                        _PAGE_VALID|_PAGE_DIRTY)
249         sw      k1,(k0)
250         /* Now reload the entry into the TLB */
251         /* FIXME: Why has Ralf set bit 2?  Should it be different for
252          *        R[23]000?  PMA
253          *        (The ori/xori combination actually _clears_ bit 2.
254          *        This is required for the R4xx0 these CPUs always
255          *        map page pairs; a page pair of 4k pages therfore
256          *        has always an address with bit 2 set to zero. -- Ralf)
257          */
258         ori     k0,0x0004
259         xori    k0,0x0004
260         lw      k0,(k0)
261         srl     k0,12
262         mtc0    k0,CP0_ENTRYLO0
263         mfc0    k1,CP0_EPC
264         nop                             # for pipeline
265         tlbwi
266         nop                             # for pipeline
267         nop
268         nop
270         jr      k1
271          rfe
273         /* Page doesn't exist. Lots of work which is less important
274          * for speed needs to be done, so hand it all over to the
275          * kernel memory management routines.
276          */
277 nopage_tlbs:
278 nowrite_mod:
279 #ifdef CONFIG_TLB_SHUTDOWN
280         /* Remove entry so we don't need to care later */
281         mfc0    k0,CP0_INDEX
282 #ifdef CONF_DEBUG_TLB
283         bgez    k0,2f
284          nop
285         /* We got a tlbs exception but found no matching entry in
286          * the tlb.  This should never happen.  Paranoia makes us
287          * check it, though.
288          */
289         SAVE_ALL
290         jal     show_regs
291          move   a0,sp
292         .set    at
293         mfc0    a1,CP0_BADVADDR
294         PRINT("c0_badvaddr == %08lx\n")
295         mfc0    a1,CP0_INDEX
296         PRINT("c0_index    == %08x\n")
297         mfc0    a1,CP0_ENTRYHI
298         PRINT("c0_entryhi  == %08x\n")
299         .set    noat
300         STI
301         .set    at
302         PANIC("Tlbs or tlbm exception with no matching entry in tlb")
304         j       1b
305          nop
307 #endif /* CONF_DEBUG_TLB */
308         /* FIXME: Why is Ralf setting bit 3 of k1?  This may need to
309          *        be changed for R[236]000! PMA
310          *        (The new ENTRYHI value will then point represent a
311          *        inique virtual address outside the 32 bit address
312          *        limit.  This is just paranoia to avoid a tlb
313          *        shutdown.  This whole part of the routine is probably
314          *        no longer required and can be removed -- Ralf)
315          */
316         lui     k1,0x0008
317         or      k0,k1
318         sll     k0,12
319         mtc0    k0,CP0_ENTRYHI
320         mtc0    zero,CP0_ENTRYLO0
321         nop                             # for pipeline
322         nop                             # R4000 V2.2 requires 4 NOPs
323         nop
324         nop
325         tlbwi
326 #endif /* CONFIG_TLB_SHUTDOWN */
327         .set    noat
328         SAVE_ALL
329         mfc0    a2,CP0_BADVADDR
330         STI
331         .set    at
332         /* a0 (struct pt_regs *) regs
333          * a1 (unsigned long)    1 for write access
334          * a2 (unsigned long)    faulting virtual address
335          */
336         move    a0,sp
337         jal     do_page_fault
338          li     a1,1
340         j       ret_from_sys_call
341          nop
342         END(r2300_handle_tlbs)
345         .align  5
346         NESTED(r2300_handle_mod, PT_SIZE, sp)
347         .set    noat
348         /* Two possible cases:
349          * 1) Page is writable but not dirty -> set dirty and return
350          * 2) Page is not writable -> call C handler
351          */
352         /* used to be dmfc0 */
353         mfc0    k0,CP0_BADVADDR
354         /* FIXME: This srl/sll sequence is as it is for the R4xx0,
355          *        and I suspect that it should be different for
356          *        the R[23]000.  PMA
357          */
358         srl     k0,12
359         sll     k0,2
360         lui     k1,%HI(TLBMAP)
361         addu    k0,k1
362         lw      k1,(k0)
363         tlbp                                    # find faulting entry
364         andi    k1,_PAGE_WRITE
366         beqz    k1,nowrite_mod
367          lw     k1,(k0)
369         /* Present and writable bits set: set accessed and dirty bits. */
370         ori     k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
371         sw      k1,(k0)
372         /* Now reload the entry into the tlb */
373         /* FIXME: Why has Ralf set bit 2?  Should it be different for
374          *        R[23]000?  PMA
375          *        (The ori/xori combination actually _clears_ bit 2.
376          *        This is required for the R4xx0 these CPUs always
377          *        map page pairs; a page pair of 4k pages therfore
378          *        has always an address with bit 2 set to zero. -- Ralf)
379          */
380         ori     k0,0x0004
381         xori    k0,0x0004
382         lw      k0,(k0)
383         srl     k0,12
384         mtc0    k0,CP0_ENTRYLO0
385         mfc0    k1,CP0_EPC
386         nop                             # for pipeline
387         nop
388         nop
389         tlbwi
390         nop                             # for pipeline
391         nop
392         nop
394         jr      k1
395          rfe
396         END(r2300_handle_mod)
397         .set    at