* better
[mascara-docs.git] / i386 / linux-2.3.21 / arch / mips / kernel / r2300_misc.S
blobde55efb4ed260d30a6bb1850f73add92f642637f
1 /* $Id: r2300_misc.S,v 1.3 1999/05/01 22:40:36 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  * Further modifications to make this work:
10  * Copyright (c) 1998 Harald Koerfgen
11  * Copyright (c) 1998 Gleb Raiko & Vladimir Roganov
12  */
13 #include <asm/asm.h>
14 #include <asm/current.h>
15 #include <asm/bootinfo.h>
16 #include <asm/cachectl.h>
17 #include <asm/fpregdef.h>
18 #include <asm/mipsconfig.h>
19 #include <asm/mipsregs.h>
20 #include <asm/page.h>
21 #include <asm/pgtable.h>
22 #include <asm/processor.h>
23 #include <asm/regdef.h>
24 #include <asm/segment.h>
25 #include <asm/stackframe.h>
27         .text
28         .set    mips1
29         .set    noreorder
31 #undef NOTLB_OPTIMIZE /* If you are paranoid, define this. */
33         /* ABUSE of CPP macros 101. */
35         /* After this macro runs, the pte faulted on is
36          * in register PTE, a ptr into the table in which
37          * the pte belongs is in PTR.
38          */
39 #define LOAD_PTE(pte, ptr) \
40         mfc0    pte, CP0_BADVADDR; \
41         _GET_CURRENT(ptr); \
42         srl     pte, pte, 22; \
43         lw      ptr, THREAD_PGDIR(ptr); \
44         sll     pte, pte, 2; \
45         addu    ptr, pte, ptr; \
46         mfc0    pte, CP0_CONTEXT; \
47         lw      ptr, (ptr); \
48         andi    pte, pte, 0xffc; \
49         addu    ptr, ptr, pte; \
50         lw      pte, (ptr); \
51         nop;
53         /* This places the even/odd pte pair in the page
54          * table at PTR into ENTRYLO0 and ENTRYLO1 using
55          * TMP as a scratch register.
56          */
57 #define PTE_RELOAD(ptr) \
58         lw      ptr, (ptr)      ; \
59         nop                     ; \
60         mtc0    ptr, CP0_ENTRYLO0; \
61         nop;
63 #define DO_FAULT(write) \
64         .set    noat; \
65         .set    macro; \
66         SAVE_ALL; \
67         mfc0    a2, CP0_BADVADDR; \
68         STI; \
69         .set    at; \
70         move    a0, sp; \
71         jal     do_page_fault; \
72          li     a1, write; \
73         j       ret_from_sys_call; \
74          nop; \
75         .set    noat; \
76         .set    nomacro;
78         /* Check is PTE is present, if not then jump to LABEL.
79          * PTR points to the page table where this PTE is located,
80          * when the macro is done executing PTE will be restored
81          * with it's original value.
82          */
83 #define PTE_PRESENT(pte, ptr, label) \
84         andi    pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
85         xori    pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
86         bnez    pte, label; \
87         .set    push;       \
88         .set    reorder;    \
89          lw     pte, (ptr); \
90         .set    pop; 
92         /* Make PTE valid, store result in PTR. */
93 #define PTE_MAKEVALID(pte, ptr) \
94         ori     pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
95         sw      pte, (ptr);
97         /* Check if PTE can be written to, if not branch to LABEL.
98          * Regardless restore PTE with value from PTR when done.
99          */
100 #define PTE_WRITABLE(pte, ptr, label) \
101         andi    pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
102         xori    pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
103         bnez    pte, label; \
104         .set    push;       \
105         .set    reorder;    \
106         lw      pte, (ptr); \
107         .set    pop;
110         /* Make PTE writable, update software status bits as well,
111          * then store at PTR.
112          */
113 #define PTE_MAKEWRITE(pte, ptr) \
114         ori     pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \
115                            _PAGE_VALID | _PAGE_DIRTY); \
116         sw      pte, (ptr);
118         .set    noreorder
120         .align  5
121 NESTED(r2300_handle_tlbl, PT_SIZE, sp)
122         .set    noat
124 #ifndef NOTLB_OPTIMIZE
125         /* Test present bit in entry. */
126         LOAD_PTE(k0, k1)
127         tlbp
128         nop
129         PTE_PRESENT(k0, k1, nopage_tlbl)
130         PTE_MAKEVALID(k0, k1)
131         PTE_RELOAD(k1)
132         tlbwi
133         nop
134         mfc0    k0, CP0_EPC
135         nop
136         jr      k0
137          rfe
138 nopage_tlbl:
139 #endif
141         DO_FAULT(0)
142 END(r2300_handle_tlbl)
144 NESTED(r2300_handle_tlbs, PT_SIZE, sp)
145         .set    noat
147 #ifndef NOTLB_OPTIMIZE
148         LOAD_PTE(k0, k1)
149         tlbp                            # find faulting entry
150         nop
151         PTE_WRITABLE(k0, k1, nopage_tlbs)
152         PTE_MAKEWRITE(k0, k1)
153         PTE_RELOAD(k1)
154         tlbwi
155         nop
156         mfc0    k0, CP0_EPC
157         nop
158         jr      k0
159          rfe
160 nopage_tlbs:
161 #endif
163         DO_FAULT(1)
164 END(r2300_handle_tlbs)
166         .align  5
167 NESTED(r2300_handle_mod, PT_SIZE, sp)
168         .set    noat
169 #ifndef NOTLB_OPTIMIZE
170         LOAD_PTE(k0, k1)
171         tlbp                                    # find faulting entry
172         andi    k0, k0, _PAGE_WRITE
173         beqz    k0, nowrite_mod
174         .set    push
175         .set    reorder
176         lw      k0, (k1)
177         .set    pop
179         /* Present and writable bits set, set accessed and dirty bits. */
180         PTE_MAKEWRITE(k0, k1)
182         /* Now reload the entry into the tlb. */
183         PTE_RELOAD(k1)
184         nop
185         tlbwi
186         nop
187         mfc0    k0, CP0_EPC
188         nop
189         jr      k0
190          rfe
191 #endif
193 nowrite_mod:
194         DO_FAULT(1)
195 END(r2300_handle_mod)