Merge branch 'kvm-updates/2.6.28' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6] / arch / sparc / mm / viking.S
1 /*
2  * viking.S: High speed Viking cache/mmu operations
3  *
4  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
5  * Copyright (C) 1997,1998,1999  Jakub Jelinek  (jj@ultra.linux.cz)
6  * Copyright (C) 1999  Pavel Semerad  (semerad@ss1000.ms.mff.cuni.cz)
7  */
8
9 #include <asm/ptrace.h>
10 #include <asm/psr.h>
11 #include <asm/asm-offsets.h>
12 #include <asm/asi.h>
13 #include <asm/mxcc.h>
14 #include <asm/page.h>
15 #include <asm/pgtsrmmu.h>
16 #include <asm/viking.h>
17 #include <asm/btfixup.h>
18
19 #ifdef CONFIG_SMP
20         .data
21         .align  4
22 sun4dsmp_flush_tlb_spin:
23         .word   0
24 #endif
25
26         .text
27         .align  4
28
29         .globl  viking_flush_cache_all, viking_flush_cache_mm
30         .globl  viking_flush_cache_range, viking_flush_cache_page
31         .globl  viking_flush_page, viking_mxcc_flush_page
32         .globl  viking_flush_page_for_dma, viking_flush_page_to_ram
33         .globl  viking_flush_sig_insns
34         .globl  viking_flush_tlb_all, viking_flush_tlb_mm
35         .globl  viking_flush_tlb_range, viking_flush_tlb_page
36
37 viking_flush_page:
38         sethi   %hi(PAGE_OFFSET), %g2
39         sub     %o0, %g2, %g3
40         srl     %g3, 12, %g1            ! ppage >> 12
41
42         clr     %o1                     ! set counter, 0 - 127
43         sethi   %hi(PAGE_OFFSET + PAGE_SIZE - 0x80000000), %o3
44         sethi   %hi(0x80000000), %o4
45         sethi   %hi(VIKING_PTAG_VALID), %o5
46         sethi   %hi(2*PAGE_SIZE), %o0
47         sethi   %hi(PAGE_SIZE), %g7
48         clr     %o2                     ! block counter, 0 - 3
49 5:
50         sll     %o1, 5, %g4
51         or      %g4, %o4, %g4           ! 0x80000000 | (set << 5)
52
53         sll     %o2, 26, %g5            ! block << 26
54 6:
55         or      %g5, %g4, %g5
56         ldda    [%g5] ASI_M_DATAC_TAG, %g2
57         cmp     %g3, %g1                ! ptag == ppage?
58         bne     7f
59          inc    %o2
60
61         andcc   %g2, %o5, %g0           ! ptag VALID?
62         be      7f
63          add    %g4, %o3, %g2           ! (PAGE_OFFSET + PAGE_SIZE) | (set << 5)
64         ld      [%g2], %g3
65         ld      [%g2 + %g7], %g3
66         add     %g2, %o0, %g2
67         ld      [%g2], %g3
68         ld      [%g2 + %g7], %g3
69         add     %g2, %o0, %g2
70         ld      [%g2], %g3
71         ld      [%g2 + %g7], %g3
72         add     %g2, %o0, %g2
73         ld      [%g2], %g3
74         b       8f
75          ld     [%g2 + %g7], %g3
76
77 7:
78         cmp     %o2, 3
79         ble     6b
80          sll    %o2, 26, %g5                    ! block << 26
81
82 8:      inc     %o1
83         cmp     %o1, 0x7f
84         ble     5b
85          clr    %o2
86
87 9:      retl
88          nop
89
90 viking_mxcc_flush_page:
91         sethi   %hi(PAGE_OFFSET), %g2
92         sub     %o0, %g2, %g3
93         sub     %g3, -PAGE_SIZE, %g3            ! ppage + PAGE_SIZE
94         sethi   %hi(MXCC_SRCSTREAM), %o3        ! assume %hi(MXCC_SRCSTREAM) == %hi(MXCC_DESTSTREAM)
95         mov     0x10, %g2                       ! set cacheable bit
96         or      %o3, %lo(MXCC_SRCSTREAM), %o2
97         or      %o3, %lo(MXCC_DESSTREAM), %o3
98         sub     %g3, MXCC_STREAM_SIZE, %g3
99 6:
100         stda    %g2, [%o2] ASI_M_MXCC
101         stda    %g2, [%o3] ASI_M_MXCC
102         andncc  %g3, PAGE_MASK, %g0
103         bne     6b
104          sub    %g3, MXCC_STREAM_SIZE, %g3
105
106 9:      retl
107          nop
108
109 viking_flush_cache_page:
110 viking_flush_cache_range:
111 #ifndef CONFIG_SMP
112         ld      [%o0 + 0x0], %o0                /* XXX vma->vm_mm, GROSS XXX */
113 #endif
114 viking_flush_cache_mm:
115 #ifndef CONFIG_SMP
116         ld      [%o0 + AOFF_mm_context], %g1
117         cmp     %g1, -1
118         bne     viking_flush_cache_all
119          nop
120         b,a     viking_flush_cache_out
121 #endif
122 viking_flush_cache_all:
123         WINDOW_FLUSH(%g4, %g5)
124 viking_flush_cache_out:
125         retl
126          nop
127
128 viking_flush_tlb_all:
129         mov     0x400, %g1
130         retl
131          sta    %g0, [%g1] ASI_M_FLUSH_PROBE
132
133 viking_flush_tlb_mm:
134         mov     SRMMU_CTX_REG, %g1
135         ld      [%o0 + AOFF_mm_context], %o1
136         lda     [%g1] ASI_M_MMUREGS, %g5
137 #ifndef CONFIG_SMP
138         cmp     %o1, -1
139         be      1f
140 #endif
141         mov     0x300, %g2
142         sta     %o1, [%g1] ASI_M_MMUREGS
143         sta     %g0, [%g2] ASI_M_FLUSH_PROBE
144         retl
145          sta    %g5, [%g1] ASI_M_MMUREGS
146 #ifndef CONFIG_SMP
147 1:      retl
148          nop
149 #endif
150
151 viking_flush_tlb_range:
152         ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
153         mov     SRMMU_CTX_REG, %g1
154         ld      [%o0 + AOFF_mm_context], %o3
155         lda     [%g1] ASI_M_MMUREGS, %g5
156 #ifndef CONFIG_SMP
157         cmp     %o3, -1
158         be      2f
159 #endif
160         sethi   %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4
161         sta     %o3, [%g1] ASI_M_MMUREGS
162         and     %o1, %o4, %o1
163         add     %o1, 0x200, %o1
164         sta     %g0, [%o1] ASI_M_FLUSH_PROBE
165 1:      sub     %o1, %o4, %o1
166         cmp     %o1, %o2
167         blu,a   1b
168          sta    %g0, [%o1] ASI_M_FLUSH_PROBE
169         retl
170          sta    %g5, [%g1] ASI_M_MMUREGS
171 #ifndef CONFIG_SMP
172 2:      retl
173          nop
174 #endif
175
176 viking_flush_tlb_page:
177         ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
178         mov     SRMMU_CTX_REG, %g1
179         ld      [%o0 + AOFF_mm_context], %o3
180         lda     [%g1] ASI_M_MMUREGS, %g5
181 #ifndef CONFIG_SMP
182         cmp     %o3, -1
183         be      1f
184 #endif
185         and     %o1, PAGE_MASK, %o1
186         sta     %o3, [%g1] ASI_M_MMUREGS
187         sta     %g0, [%o1] ASI_M_FLUSH_PROBE
188         retl
189          sta    %g5, [%g1] ASI_M_MMUREGS
190 #ifndef CONFIG_SMP
191 1:      retl
192          nop
193 #endif
194
195 viking_flush_page_to_ram:
196 viking_flush_page_for_dma:
197 viking_flush_sig_insns:
198         retl
199          nop
200
201 #ifdef CONFIG_SMP
202         .globl  sun4dsmp_flush_tlb_all, sun4dsmp_flush_tlb_mm
203         .globl  sun4dsmp_flush_tlb_range, sun4dsmp_flush_tlb_page
204 sun4dsmp_flush_tlb_all:
205         sethi   %hi(sun4dsmp_flush_tlb_spin), %g3
206 1:      ldstub  [%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
207         tst     %g5
208         bne     2f
209          mov    0x400, %g1
210         sta     %g0, [%g1] ASI_M_FLUSH_PROBE
211         retl
212          stb    %g0, [%g3 + %lo(sun4dsmp_flush_tlb_spin)]
213 2:      tst     %g5
214         bne,a   2b
215          ldub   [%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
216         b,a     1b
217
218 sun4dsmp_flush_tlb_mm:
219         sethi   %hi(sun4dsmp_flush_tlb_spin), %g3
220 1:      ldstub  [%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
221         tst     %g5
222         bne     2f
223          mov    SRMMU_CTX_REG, %g1
224         ld      [%o0 + AOFF_mm_context], %o1
225         lda     [%g1] ASI_M_MMUREGS, %g5
226         mov     0x300, %g2
227         sta     %o1, [%g1] ASI_M_MMUREGS
228         sta     %g0, [%g2] ASI_M_FLUSH_PROBE
229         sta     %g5, [%g1] ASI_M_MMUREGS
230         retl
231          stb    %g0, [%g3 + %lo(sun4dsmp_flush_tlb_spin)]
232 2:      tst     %g5
233         bne,a   2b
234          ldub   [%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
235         b,a     1b
236
237 sun4dsmp_flush_tlb_range:
238         sethi   %hi(sun4dsmp_flush_tlb_spin), %g3
239 1:      ldstub  [%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
240         tst     %g5
241         bne     3f
242          mov    SRMMU_CTX_REG, %g1
243         ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
244         ld      [%o0 + AOFF_mm_context], %o3
245         lda     [%g1] ASI_M_MMUREGS, %g5
246         sethi   %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4
247         sta     %o3, [%g1] ASI_M_MMUREGS
248         and     %o1, %o4, %o1
249         add     %o1, 0x200, %o1
250         sta     %g0, [%o1] ASI_M_FLUSH_PROBE
251 2:      sub     %o1, %o4, %o1
252         cmp     %o1, %o2
253         blu,a   2b
254          sta    %g0, [%o1] ASI_M_FLUSH_PROBE
255         sta     %g5, [%g1] ASI_M_MMUREGS
256         retl
257          stb    %g0, [%g3 + %lo(sun4dsmp_flush_tlb_spin)]
258 3:      tst     %g5
259         bne,a   3b
260          ldub   [%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
261         b,a     1b
262
263 sun4dsmp_flush_tlb_page:
264         sethi   %hi(sun4dsmp_flush_tlb_spin), %g3
265 1:      ldstub  [%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
266         tst     %g5
267         bne     2f
268          mov    SRMMU_CTX_REG, %g1
269         ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
270         ld      [%o0 + AOFF_mm_context], %o3
271         lda     [%g1] ASI_M_MMUREGS, %g5
272         and     %o1, PAGE_MASK, %o1
273         sta     %o3, [%g1] ASI_M_MMUREGS
274         sta     %g0, [%o1] ASI_M_FLUSH_PROBE
275         sta     %g5, [%g1] ASI_M_MMUREGS
276         retl
277          stb    %g0, [%g3 + %lo(sun4dsmp_flush_tlb_spin)]
278 2:      tst     %g5
279         bne,a   2b
280          ldub   [%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
281         b,a     1b
282          nop
283 #endif