IP22 has externally controlled S-cache.
[linux-2.6/linux-mips.git] / arch / mips64 / mm / tlbex-r4k.S
blobea57f241ae0637b067b0fa624bc7af619018e0c9
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2000 Silicon Graphics, Inc.
7  * Written by Ulf Carlsson (ulfc@engr.sgi.com)
8  * Copyright (C) 2002  Maciej W. Rozycki
9  */
10 #include <linux/config.h>
11 #include <linux/init.h>
12 #include <linux/threads.h>
13 #include <asm/asm.h>
14 #include <asm/regdef.h>
15 #include <asm/mipsregs.h>
16 #include <asm/pgtable.h>
17 #include <asm/stackframe.h>
18 #include <asm/war.h>
20         /*
21          * After this macro runs we have a pointer to the pte of the address
22          * that caused the fault in PTR.
23          */
24         .macro  LOAD_PTE2, ptr, tmp, kaddr
25 #ifdef CONFIG_SMP
26         dmfc0   \ptr, CP0_CONTEXT
27         dmfc0   \tmp, CP0_BADVADDR
28         dsra    \ptr, 23                        # get pgd_current[cpu]
29 #else
30         dmfc0   \tmp, CP0_BADVADDR
31         dla     \ptr, pgd_current
32 #endif
33         bltz    \tmp, \kaddr
34          ld     \ptr, (\ptr)
35         dsrl    \tmp, (PGDIR_SHIFT-3)           # get pgd offset in bytes
36         andi    \tmp, ((PTRS_PER_PGD - 1)<<3)
37         daddu   \ptr, \tmp                      # add in pgd offset
38         dmfc0   \tmp, CP0_BADVADDR
39         ld      \ptr, (\ptr)                    # get pmd pointer
40         dsrl    \tmp, (PMD_SHIFT-3)             # get pmd offset in bytes
41         andi    \tmp, ((PTRS_PER_PMD - 1)<<3)
42         daddu   \ptr, \tmp                      # add in pmd offset
43         dmfc0   \tmp, CP0_XCONTEXT
44         ld      \ptr, (\ptr)                    # get pte pointer
45         andi    \tmp, 0xff0                     # get pte offset
46         daddu   \ptr, \tmp
47         .endm
50         /*
51          * Ditto for the kernel table.
52          */
53         .macro  LOAD_KPTE2, ptr, tmp, not_vmalloc
54         /*
55          * First, determine that the address is in/above vmalloc range.
56          */
57         dmfc0   \tmp, CP0_BADVADDR
58         dli     \ptr, VMALLOC_START
60         /*
61          * Now find offset into kptbl.
62          */
63         dsubu   \tmp, \tmp, \ptr
64         dla     \ptr, kptbl
65         dsrl    \tmp, (PAGE_SHIFT+1)            # get vpn2
66         dsll    \tmp, 4                         # byte offset of pte
67         daddu   \ptr, \ptr, \tmp
69         /*
70          * Determine that fault address is within vmalloc range.
71          */
72         dla     \tmp, ekptbl
73         slt     \tmp, \ptr, \tmp
74         beqz    \tmp, \not_vmalloc              # not vmalloc
75          nop
76         .endm
79         /*
80          * This places the even/odd pte pair in the page table at the pte
81          * entry pointed to by PTE into ENTRYLO0 and ENTRYLO1.
82          */
83         .macro  PTE_RELOAD, pte0, pte1
84         dsrl    \pte0, 6                        # convert to entrylo0
85         dmtc0   \pte0, CP0_ENTRYLO0             # load it
86         dsrl    \pte1, 6                        # convert to entrylo1
87         dmtc0   \pte1, CP0_ENTRYLO1             # load it
88         .endm
91         .text
92         .set    noreorder
93         .set    mips3
95         __INIT
97         .align  5
98 LEAF(except_vec0_generic)
99         .set    noat
100         PANIC("Unused vector called")
101 1:      b       1b
102          nop
103 END(except_vec0_generic)
106         /*
107          * TLB refill handlers for the R4000 and SB1.
108          * Attention:  We may only use 32 instructions / 128 bytes.
109          */
110         .align  5
111 LEAF(except_vec1_r4k)
112         .set    noat
113         dla     k0, handle_vec1_r4k
114         jr      k0
115          nop
116 END(except_vec1_r4k)
118 LEAF(except_vec1_sb1)
119 #if BCM1250_M3_WAR
120         dmfc0   k0, CP0_BADVADDR
121         dmfc0   k1, CP0_ENTRYHI
122         xor     k0, k1
123         dsrl    k0, k0, PAGE_SHIFT+1
124         bnez    k0, 1f
125 #endif
126         .set    noat
127         dla     k0, handle_vec1_r4k
128         jr      k0
129          nop
131 1:      eret
132         nop
133 END(except_vec1_sb1)
135         __FINIT
137         .align  5
138 LEAF(handle_vec1_r4k)
139         .set    noat
140         LOAD_PTE2 k1 k0 9f
141         ld      k0, 0(k1)                       # get even pte
142         ld      k1, 8(k1)                       # get odd pte
143         PTE_RELOAD k0 k1
144         b       1f
145          tlbwr
146 1:      nop
147         eret
149 9:                                              # handle the vmalloc range
150         LOAD_KPTE2 k1 k0 invalid_vmalloc_address
151         ld      k0, 0(k1)                       # get even pte
152         ld      k1, 8(k1)                       # get odd pte
153         PTE_RELOAD k0 k1
154         b       1f
155          tlbwr
156 1:      nop
157         eret
158 END(handle_vec1_r4k)
161         __INIT
163         /*
164          * TLB refill handler for the R10000.
165          * Attention:  We may only use 32 instructions / 128 bytes.
166          */
167         .align  5
168 LEAF(except_vec1_r10k)
169         .set    noat
170         dla     k0, handle_vec1_r10k
171         jr      k0
172          nop
173 END(except_vec1_r10k)
175         __FINIT
177         .align  5
178 LEAF(handle_vec1_r10k)
179         .set    noat
180         LOAD_PTE2 k1 k0 9f
181         ld      k0, 0(k1)                       # get even pte
182         ld      k1, 8(k1)                       # get odd pte
183         PTE_RELOAD k0 k1
184         nop
185         tlbwr
186         eret
188 9:                                              # handle the vmalloc range
189         LOAD_KPTE2 k1 k0 invalid_vmalloc_address
190         ld      k0, 0(k1)                       # get even pte
191         ld      k1, 8(k1)                       # get odd pte
192         PTE_RELOAD k0 k1
193         nop
194         tlbwr
195         eret
196 END(handle_vec1_r10k)
199         .align  5
200 LEAF(invalid_vmalloc_address)
201         .set    noat
202         PANIC("Invalid kernel address")
203 1:      b       1b
204          nop
205 END(invalid_vmalloc_address)