also update spec file ...
[linux-flexiantxendom0-3.2.10.git] / arch / mips64 / mm / tlbex-r4k.S
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>
19
20         .data
21         .comm   pgd_current, NR_CPUS * 8, 8
22
23         /*
24          * After this macro runs we have a pointer to the pte of the address
25          * that caused the fault in PTR.
26          */
27         .macro  LOAD_PTE2, ptr, tmp, kaddr
28 #ifdef CONFIG_SMP
29         dmfc0   \ptr, CP0_CONTEXT
30         dmfc0   \tmp, CP0_BADVADDR
31         dsra    \ptr, 23                        # get pgd_current[cpu]
32 #else
33         dmfc0   \tmp, CP0_BADVADDR
34         dla     \ptr, pgd_current
35 #endif
36         bltz    \tmp, \kaddr
37          ld     \ptr, (\ptr)
38         dsrl    \tmp, (PGDIR_SHIFT-3)           # get pgd offset in bytes
39         andi    \tmp, ((PTRS_PER_PGD - 1)<<3)
40         daddu   \ptr, \tmp                      # add in pgd offset
41         dmfc0   \tmp, CP0_BADVADDR
42         ld      \ptr, (\ptr)                    # get pmd pointer
43         dsrl    \tmp, (PMD_SHIFT-3)             # get pmd offset in bytes
44         andi    \tmp, ((PTRS_PER_PMD - 1)<<3)
45         daddu   \ptr, \tmp                      # add in pmd offset
46         dmfc0   \tmp, CP0_XCONTEXT
47         ld      \ptr, (\ptr)                    # get pte pointer
48         andi    \tmp, 0xff0                     # get pte offset
49         daddu   \ptr, \tmp
50         .endm
51
52
53         /*
54          * Ditto for the kernel table.
55          */
56         .macro  LOAD_KPTE2, ptr, tmp, not_vmalloc
57         /*
58          * First, determine that the address is in/above vmalloc range.
59          */
60         dmfc0   \tmp, CP0_BADVADDR
61         dli     \ptr, VMALLOC_START
62
63         /*
64          * Now find offset into kptbl.
65          */
66         dsubu   \tmp, \tmp, \ptr
67         dla     \ptr, kptbl
68         dsrl    \tmp, (PAGE_SHIFT+1)            # get vpn2
69         dsll    \tmp, 4                         # byte offset of pte
70         daddu   \ptr, \ptr, \tmp
71
72         /*
73          * Determine that fault address is within vmalloc range.
74          */
75         dla     \tmp, ekptbl
76         slt     \tmp, \ptr, \tmp
77         beqz    \tmp, \not_vmalloc              # not vmalloc
78          nop
79         .endm
80
81
82         /*
83          * This places the even/odd pte pair in the page table at the pte
84          * entry pointed to by PTE into ENTRYLO0 and ENTRYLO1.
85          */
86         .macro  PTE_RELOAD, pte0, pte1
87         dsrl    \pte0, 6                        # convert to entrylo0
88         dmtc0   \pte0, CP0_ENTRYLO0             # load it
89         dsrl    \pte1, 6                        # convert to entrylo1
90         dmtc0   \pte1, CP0_ENTRYLO1             # load it
91         .endm
92
93
94         .text
95         .set    noreorder
96         .set    mips3
97
98         __INIT
99
100         .align  5
101 LEAF(except_vec0_generic)
102         .set    noat
103         PANIC("Unused vector called")
104 1:      b       1b
105          nop
106 END(except_vec0_generic)
107
108
109         /*
110          * TLB refill handlers for the R4000 and SB1.
111          * Attention:  We may only use 32 instructions / 128 bytes.
112          */
113         .align  5
114 LEAF(except_vec1_r4k)
115         .set    noat
116         dla     k0, handle_vec1_r4k
117         jr      k0
118          nop
119 END(except_vec1_r4k)
120
121 LEAF(except_vec1_sb1)
122 #if BCM1250_M3_WAR
123         dmfc0   k0, CP0_BADVADDR
124         dmfc0   k1, CP0_ENTRYHI
125         xor     k0, k1
126         dsrl    k0, k0, PAGE_SHIFT+1
127         bnez    k0, 1f
128 #endif
129         .set    noat
130         dla     k0, handle_vec1_r4k
131         jr      k0
132          nop
133
134 1:      eret
135         nop
136 END(except_vec1_sb1)
137
138         __FINIT
139
140         .align  5
141 LEAF(handle_vec1_r4k)
142         .set    noat
143         LOAD_PTE2 k1 k0 9f
144         ld      k0, 0(k1)                       # get even pte
145         ld      k1, 8(k1)                       # get odd pte
146         PTE_RELOAD k0 k1
147         b       1f
148          tlbwr
149 1:      nop
150         eret
151
152 9:                                              # handle the vmalloc range
153         LOAD_KPTE2 k1 k0 invalid_vmalloc_address
154         ld      k0, 0(k1)                       # get even pte
155         ld      k1, 8(k1)                       # get odd pte
156         PTE_RELOAD k0 k1
157         b       1f
158          tlbwr
159 1:      nop
160         eret
161 END(handle_vec1_r4k)
162
163
164         __INIT
165
166         /*
167          * TLB refill handler for the R10000.
168          * Attention:  We may only use 32 instructions / 128 bytes.
169          */
170         .align  5
171 LEAF(except_vec1_r10k)
172         .set    noat
173         dla     k0, handle_vec1_r10k
174         jr      k0
175          nop
176 END(except_vec1_r10k)
177
178         __FINIT
179
180         .align  5
181 LEAF(handle_vec1_r10k)
182         .set    noat
183         LOAD_PTE2 k1 k0 9f
184         ld      k0, 0(k1)                       # get even pte
185         ld      k1, 8(k1)                       # get odd pte
186         PTE_RELOAD k0 k1
187         nop
188         tlbwr
189         eret
190
191 9:                                              # handle the vmalloc range
192         LOAD_KPTE2 k1 k0 invalid_vmalloc_address
193         ld      k0, 0(k1)                       # get even pte
194         ld      k1, 8(k1)                       # get odd pte
195         PTE_RELOAD k0 k1
196         nop
197         tlbwr
198         eret
199 END(handle_vec1_r10k)
200
201
202         .align  5
203 LEAF(invalid_vmalloc_address)
204         .set    noat
205         PANIC("Invalid kernel address")
206 1:      b       1b
207          nop
208 END(invalid_vmalloc_address)