www.usr.com/support/gpl/USR9113_release1.0.tar.gz
[bcm963xx.git] / kernel / linux / arch / mips / mm / tlbex64-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
14 #include <asm/asm.h>
15 #include <asm/hazards.h>
16 #include <asm/regdef.h>
17 #include <asm/mipsregs.h>
18 #include <asm/stackframe.h>
19 #include <asm/war.h>
20
21 #define _VMALLOC_START  0xc000000000000000
22
23         .macro  GET_PGD, ptr
24 #ifdef CONFIG_SMP
25         /*
26          * Fixme - this is b0rked for pgd_current outside of CKSEG0
27          */
28         dmfc0   \ptr, CP0_CONTEXT
29         dsra    \ptr, 23                        # get pgd_current[cpu]
30         ld      \ptr, (\ptr)
31 #else
32         ld      \ptr, pgd_current
33 #endif
34         .endm
35
36         /*
37          * After this macro runs we have a pointer to the pte of the address
38          * that caused the fault in PTR.  Expects register containing the
39          * the pagetable root pointer as the ptr argument and c0_badvaddr
40          * passed as tmp argument.
41          */
42         .macro  LOAD_PTE2, ptr, tmp
43         dsrl    \tmp, (_PGDIR_SHIFT-3)          # get pgd offset in bytes
44         andi    \tmp, ((_PTRS_PER_PGD - 1)<<3)
45         daddu   \ptr, \tmp                      # add in pgd offset
46         dmfc0   \tmp, CP0_BADVADDR
47         ld      \ptr, (\ptr)                    # get pmd pointer
48         dsrl    \tmp, (_PMD_SHIFT-3)            # get pmd offset in bytes
49         andi    \tmp, ((_PTRS_PER_PMD - 1)<<3)
50         daddu   \ptr, \tmp                      # add in pmd offset
51         dmfc0   \tmp, CP0_XCONTEXT
52         ld      \ptr, (\ptr)                    # get pte pointer
53         andi    \tmp, 0xff0                     # get pte offset
54         daddu   \ptr, \tmp
55         .endm
56
57         /*
58          * This places the even/odd pte pair in the page table at the pte
59          * entry pointed to by PTE into ENTRYLO0 and ENTRYLO1.
60          */
61         .macro  PTE_RELOAD, pte0, pte1
62         dsrl    \pte0, 6                        # convert to entrylo0
63         dmtc0   \pte0, CP0_ENTRYLO0             # load it
64         dsrl    \pte1, 6                        # convert to entrylo1
65         dmtc0   \pte1, CP0_ENTRYLO1             # load it
66         .endm
67
68
69         .text
70         .set    noreorder
71         .set    mips3
72
73         __INIT
74
75         /*
76          * TLB refill handlers for the R4000 and SB1.
77          * Attention:  We may only use 32 instructions / 128 bytes.
78          */
79         .align  5
80 LEAF(except_vec1_r4k)
81         .set    noat
82         dla     k0, handle_vec1_r4k
83         jr      k0
84          nop
85 END(except_vec1_r4k)
86
87 LEAF(except_vec1_sb1)
88 #if BCM1250_M3_WAR
89         dmfc0   k0, CP0_BADVADDR
90         dmfc0   k1, CP0_ENTRYHI
91         xor     k0, k1
92         dsrl    k0, k0, _PAGE_SHIFT+1
93         bnez    k0, 1f
94 #endif
95         .set    noat
96         dla     k0, handle_vec1_r4k
97         jr      k0
98          nop
99
100 1:      eret
101         nop
102 END(except_vec1_sb1)
103
104         __FINIT
105
106         .align  5
107 LEAF(handle_vec1_r4k)
108         .set    noat
109         dmfc0   k0, CP0_BADVADDR
110         bltz    k0, 9f
111
112          GET_PGD k1                             # pointer to root of pgd
113         LOAD_PTE2 k1 k0
114         ld      k0, 0(k1)                       # get even pte
115         ld      k1, 8(k1)                       # get odd pte
116         PTE_RELOAD k0 k1
117         mtc0_tlbw_hazard
118         tlbwr
119         tlbw_eret_hazard
120         eret
121
122 9:                                              # handle the vmalloc range
123         dli     k1, _VMALLOC_START
124         dsubu   k0, k1
125         dla     k1, swapper_pg_dir              # pointer to root of pgd
126         LOAD_PTE2 k1 k0
127         ld      k0, 0(k1)                       # get even pte
128         ld      k1, 8(k1)                       # get odd pte
129         PTE_RELOAD k0 k1
130         mtc0_tlbw_hazard
131          tlbwr
132         tlbw_eret_hazard
133         eret
134 END(handle_vec1_r4k)