Import 2.3.16
[davej-history.git] / arch / sparc / mm / hypersparc.S
blob19b698a9b66828be3c7ebe6fc9ca7bce0b428970
1 /* $Id: hypersparc.S,v 1.14 1999/08/14 03:51:47 anton Exp $
2  * hypersparc.S: High speed Hypersparc mmu/cache operations.
3  *
4  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
5  */
7 #include <asm/ptrace.h>
8 #include <asm/psr.h>
9 #include <asm/asi.h>
10 #include <asm/page.h>
11 #include <asm/pgtsrmmu.h>
12 #include <linux/init.h>
14 #define WINDOW_FLUSH(tmp1, tmp2)                                        \
15         mov     0, tmp1;                                                \
16 98:     ld      [%g6 + AOFF_task_thread + AOFF_thread_uwinmask], tmp2;  \
17         orcc    %g0, tmp2, %g0;                                         \
18         add     tmp1, 1, tmp1;                                          \
19         bne     98b;                                                    \
20          save   %sp, -64, %sp;                                          \
21 99:     subcc   tmp1, 1, tmp1;                                          \
22         bne     99b;                                                    \
23          restore %g0, %g0, %g0;
25         .text
26         .align  4
28         .globl  hypersparc_flush_cache_all, hypersparc_flush_cache_mm
29         .globl  hypersparc_flush_cache_range, hypersparc_flush_cache_page
30         .globl  hypersparc_flush_page_to_ram, hypersparc_flush_chunk
31         .globl  hypersparc_flush_page_for_dma, hypersparc_flush_sig_insns
32         .globl  hypersparc_flush_tlb_all, hypersparc_flush_tlb_mm
33         .globl  hypersparc_flush_tlb_range, hypersparc_flush_tlb_page
35 hypersparc_flush_cache_all:
36         WINDOW_FLUSH(%g4, %g5)
37         sethi   %hi(vac_cache_size), %g4
38         ld      [%g4 + %lo(vac_cache_size)], %g5
39         sethi   %hi(vac_line_size), %g1
40         ld      [%g1 + %lo(vac_line_size)], %g2
41 1:      
42         subcc   %g5, %g2, %g5                   ! hyper_flush_unconditional_combined
43         bne     1b
44          sta    %g0, [%g5] ASI_M_FLUSH_CTX
45         retl
46          sta    %g0, [%g0] ASI_M_FLUSH_IWHOLE   ! hyper_flush_whole_icache
48         /* We expand the window flush to get maximum performance. */
49 hypersparc_flush_cache_mm:
50 #ifndef __SMP__
51         ld      [%o0 + AOFF_mm_context], %g1
52         cmp     %g1, -1
53         be      hypersparc_flush_cache_mm_out
54 #endif
55         WINDOW_FLUSH(%g4, %g5)
57         sethi   %hi(vac_line_size), %g1
58         ld      [%g1 + %lo(vac_line_size)], %o1
59         sethi   %hi(vac_cache_size), %g2
60         ld      [%g2 + %lo(vac_cache_size)], %o0
61         add     %o1, %o1, %g1
62         add     %o1, %g1, %g2
63         add     %o1, %g2, %g3
64         add     %o1, %g3, %g4
65         add     %o1, %g4, %g5
66         add     %o1, %g5, %o4
67         add     %o1, %o4, %o5
69         /* BLAMMO! */
71         subcc   %o0, %o5, %o0                           ! hyper_flush_cache_user
72         sta     %g0, [%o0 + %g0] ASI_M_FLUSH_USER
73         sta     %g0, [%o0 + %o1] ASI_M_FLUSH_USER
74         sta     %g0, [%o0 + %g1] ASI_M_FLUSH_USER
75         sta     %g0, [%o0 + %g2] ASI_M_FLUSH_USER
76         sta     %g0, [%o0 + %g3] ASI_M_FLUSH_USER
77         sta     %g0, [%o0 + %g4] ASI_M_FLUSH_USER
78         sta     %g0, [%o0 + %g5] ASI_M_FLUSH_USER
79         bne     1b
80          sta    %g0, [%o0 + %o4] ASI_M_FLUSH_USER
81 hypersparc_flush_cache_mm_out:
82         retl
83          nop
85         /* The things we do for performance... */
86 hypersparc_flush_cache_range:
87 #ifndef __SMP__
88         ld      [%o0 + AOFF_mm_context], %g1
89         cmp     %g1, -1
90         be      hypersparc_flush_cache_range_out
91 #endif
92         WINDOW_FLUSH(%g4, %g5)
94         sethi   %hi(vac_line_size), %g1
95         ld      [%g1 + %lo(vac_line_size)], %o4
96         sethi   %hi(vac_cache_size), %g2
97         ld      [%g2 + %lo(vac_cache_size)], %o3
99         /* Here comes the fun part... */
100         add     %o2, (PAGE_SIZE - 1), %o2
101         andn    %o1, (PAGE_SIZE - 1), %o1
102         add     %o4, %o4, %o5
103         andn    %o2, (PAGE_SIZE - 1), %o2
104         add     %o4, %o5, %g1
105         sub     %o2, %o1, %g4
106         add     %o4, %g1, %g2
107         sll     %o3, 2, %g5
108         add     %o4, %g2, %g3
109         cmp     %g4, %g5
110         add     %o4, %g3, %g4
111         blu     0f
112          add    %o4, %g4, %g5
113         add     %o4, %g5, %g7
115         /* Flush entire user space, believe it or not this is quicker
116          * than page at a time flushings for range > (cache_size<<2).
117          */
119         subcc   %o3, %g7, %o3
120         sta     %g0, [%o3 + %g0] ASI_M_FLUSH_USER
121         sta     %g0, [%o3 + %o4] ASI_M_FLUSH_USER
122         sta     %g0, [%o3 + %o5] ASI_M_FLUSH_USER
123         sta     %g0, [%o3 + %g1] ASI_M_FLUSH_USER
124         sta     %g0, [%o3 + %g2] ASI_M_FLUSH_USER
125         sta     %g0, [%o3 + %g3] ASI_M_FLUSH_USER
126         sta     %g0, [%o3 + %g4] ASI_M_FLUSH_USER
127         bne     1b
128          sta    %g0, [%o3 + %g5] ASI_M_FLUSH_USER
129         retl
130          nop
132         /* Below our threshold, flush one page at a time. */
134         ld      [%o0 + AOFF_mm_context], %o0
135         mov     SRMMU_CTX_REG, %g7
136         lda     [%g7] ASI_M_MMUREGS, %o3
137         sta     %o0, [%g7] ASI_M_MMUREGS
138         add     %o2, -PAGE_SIZE, %o0
140         or      %o0, 0x400, %g7
141         lda     [%g7] ASI_M_FLUSH_PROBE, %g7
142         orcc    %g7, 0, %g0
143         be,a    3f
144          mov    %o0, %o2
145         add     %o4, %g5, %g7
147         sub     %o2, %g7, %o2
148         sta     %g0, [%o2 + %g0] ASI_M_FLUSH_PAGE
149         sta     %g0, [%o2 + %o4] ASI_M_FLUSH_PAGE
150         sta     %g0, [%o2 + %o5] ASI_M_FLUSH_PAGE
151         sta     %g0, [%o2 + %g1] ASI_M_FLUSH_PAGE
152         sta     %g0, [%o2 + %g2] ASI_M_FLUSH_PAGE
153         sta     %g0, [%o2 + %g3] ASI_M_FLUSH_PAGE
154         andcc   %o2, 0xffc, %g0
155         sta     %g0, [%o2 + %g4] ASI_M_FLUSH_PAGE
156         bne     2b
157          sta    %g0, [%o2 + %g5] ASI_M_FLUSH_PAGE
159         cmp     %o2, %o1
160         bne     1b
161          add    %o2, -PAGE_SIZE, %o0
162         mov     SRMMU_FAULT_STATUS, %g5
163         lda     [%g5] ASI_M_MMUREGS, %g0
164         mov     SRMMU_CTX_REG, %g7
165         sta     %o3, [%g7] ASI_M_MMUREGS
166 hypersparc_flush_cache_range_out:
167         retl
168          nop
170         /* HyperSparc requires a valid mapping where we are about to flush
171          * in order to check for a physical tag match during the flush.
172          */
173         /* Verified, my ass... */
174 hypersparc_flush_cache_page:
175         ld      [%o0 + 0x0], %o0                /* XXX vma->vm_mm, GROSS XXX */
176         ld      [%o0 + AOFF_mm_context], %g2
177 #ifndef __SMP__
178         cmp     %g2, -1
179         be      hypersparc_flush_cache_page_out
180 #endif
181         WINDOW_FLUSH(%g4, %g5)
183         sethi   %hi(vac_line_size), %g1
184         ld      [%g1 + %lo(vac_line_size)], %o4
185         mov     SRMMU_CTX_REG, %o3
186         andn    %o1, (PAGE_SIZE - 1), %o1
187         lda     [%o3] ASI_M_MMUREGS, %o2
188         sta     %g2, [%o3] ASI_M_MMUREGS
189         or      %o1, 0x400, %o5
190         lda     [%o5] ASI_M_FLUSH_PROBE, %g1
191         orcc    %g0, %g1, %g0
192         be      2f
193          add    %o4, %o4, %o5
194         sub     %o1, -PAGE_SIZE, %o1
195         add     %o4, %o5, %g1
196         add     %o4, %g1, %g2
197         add     %o4, %g2, %g3
198         add     %o4, %g3, %g4
199         add     %o4, %g4, %g5
200         add     %o4, %g5, %g7
202         /* BLAMMO! */
204         sub     %o1, %g7, %o1
205         sta     %g0, [%o1 + %g0] ASI_M_FLUSH_PAGE
206         sta     %g0, [%o1 + %o4] ASI_M_FLUSH_PAGE
207         sta     %g0, [%o1 + %o5] ASI_M_FLUSH_PAGE
208         sta     %g0, [%o1 + %g1] ASI_M_FLUSH_PAGE
209         sta     %g0, [%o1 + %g2] ASI_M_FLUSH_PAGE
210         sta     %g0, [%o1 + %g3] ASI_M_FLUSH_PAGE
211         andcc   %o1, 0xffc, %g0
212         sta     %g0, [%o1 + %g4] ASI_M_FLUSH_PAGE
213         bne     1b
214          sta    %g0, [%o1 + %g5] ASI_M_FLUSH_PAGE
216         mov     SRMMU_FAULT_STATUS, %g7
217         mov     SRMMU_CTX_REG, %g4
218         lda     [%g7] ASI_M_MMUREGS, %g0
219         sta     %o2, [%g4] ASI_M_MMUREGS
220 hypersparc_flush_cache_page_out:
221         retl
222          nop
224 hypersparc_flush_sig_insns:
225         flush   %o1
226         retl
227          flush  %o1 + 4
229         /* HyperSparc is copy-back. */
230 hypersparc_flush_page_to_ram:
231 hypersparc_flush_chunk:
232         sethi   %hi(vac_line_size), %g1
233         ld      [%g1 + %lo(vac_line_size)], %o4
234         andn    %o0, (PAGE_SIZE - 1), %o0
235         add     %o4, %o4, %o5
236         or      %o0, 0x400, %g7
237         lda     [%g7] ASI_M_FLUSH_PROBE, %g5
238         add     %o4, %o5, %g1
239         orcc    %g5, 0, %g0
240         be      2f
241          add    %o4, %g1, %g2
242         add     %o4, %g2, %g3
243         sub     %o0, -PAGE_SIZE, %o0
244         add     %o4, %g3, %g4
245         add     %o4, %g4, %g5
246         add     %o4, %g5, %g7
248         /* BLAMMO! */
250         sub     %o0, %g7, %o0
251         sta     %g0, [%o0 + %g0] ASI_M_FLUSH_PAGE
252         sta     %g0, [%o0 + %o4] ASI_M_FLUSH_PAGE
253         sta     %g0, [%o0 + %o5] ASI_M_FLUSH_PAGE
254         sta     %g0, [%o0 + %g1] ASI_M_FLUSH_PAGE
255         sta     %g0, [%o0 + %g2] ASI_M_FLUSH_PAGE
256         sta     %g0, [%o0 + %g3] ASI_M_FLUSH_PAGE
257         andcc   %o0, 0xffc, %g0
258         sta     %g0, [%o0 + %g4] ASI_M_FLUSH_PAGE
259         bne     1b
260          sta    %g0, [%o0 + %g5] ASI_M_FLUSH_PAGE
262         mov     SRMMU_FAULT_STATUS, %g1
263         retl
264          lda    [%g1] ASI_M_MMUREGS, %g0
266         /* HyperSparc is IO cache coherent. */
267 hypersparc_flush_page_for_dma:
268         retl
269          nop
271         /* It was noted that at boot time a TLB flush all in a delay slot
272          * can deliver an illegal instruction to the processor if the timing
273          * is just right...
274          */
275 hypersparc_flush_tlb_all:
276         mov     0x400, %g1
277         sta     %g0, [%g1] ASI_M_FLUSH_PROBE
278         retl
279          nop
281 hypersparc_flush_tlb_mm:
282         mov     SRMMU_CTX_REG, %g1
283         ld      [%o0 + AOFF_mm_context], %o1
284         lda     [%g1] ASI_M_MMUREGS, %g5
285 #ifndef __SMP__
286         cmp     %o1, -1
287         be      hypersparc_flush_tlb_mm_out
288 #endif
289          mov    0x300, %g2
290         sta     %o1, [%g1] ASI_M_MMUREGS
291         sta     %g0, [%g2] ASI_M_FLUSH_PROBE
292 hypersparc_flush_tlb_mm_out:
293         retl
294          sta    %g5, [%g1] ASI_M_MMUREGS
296 hypersparc_flush_tlb_range:
297         mov     SRMMU_CTX_REG, %g1
298         ld      [%o0 + AOFF_mm_context], %o3
299         lda     [%g1] ASI_M_MMUREGS, %g5
300 #ifndef __SMP__
301         cmp     %o3, -1
302         be      hypersparc_flush_tlb_range_out
303 #endif
304          sethi  %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4
305         sta     %o3, [%g1] ASI_M_MMUREGS
306         and     %o1, %o4, %o1
307         add     %o1, 0x200, %o1
308         sta     %g0, [%o1] ASI_M_FLUSH_PROBE
310         sub     %o1, %o4, %o1
311         cmp     %o1, %o2
312         blu,a   1b
313          sta    %g0, [%o1] ASI_M_FLUSH_PROBE
314 hypersparc_flush_tlb_range_out:
315         retl
316          sta    %g5, [%g1] ASI_M_MMUREGS
318 hypersparc_flush_tlb_page:
319         ld      [%o0 + 0x00], %o0       /* XXX vma->vm_mm GROSS XXX */
320         mov     SRMMU_CTX_REG, %g1
321         ld      [%o0 + AOFF_mm_context], %o3
322         andn    %o1, (PAGE_SIZE - 1), %o1
323 #ifndef __SMP__
324         cmp     %o3, -1
325         be      hypersparc_flush_tlb_page_out
326 #endif
327          lda    [%g1] ASI_M_MMUREGS, %g5
328         sta     %o3, [%g1] ASI_M_MMUREGS
329         sta     %g0, [%o1] ASI_M_FLUSH_PROBE
330 hypersparc_flush_tlb_page_out:
331         retl
332          sta    %g5, [%g1] ASI_M_MMUREGS
334         __INIT
335         
336         /* High speed page clear/copy. */
337 hypersparc_bzero_1page:
338 /* NOTE: This routine has to be shorter than 40insns --jj */
339         clr     %g1
340         mov     32, %g2
341         mov     64, %g3
342         mov     96, %g4
343         mov     128, %g5
344         mov     160, %g7
345         mov     192, %o2
346         mov     224, %o3
347         mov     16, %o1
349         stda    %g0, [%o0 + %g0] ASI_M_BFILL
350         stda    %g0, [%o0 + %g2] ASI_M_BFILL
351         stda    %g0, [%o0 + %g3] ASI_M_BFILL
352         stda    %g0, [%o0 + %g4] ASI_M_BFILL
353         stda    %g0, [%o0 + %g5] ASI_M_BFILL
354         stda    %g0, [%o0 + %g7] ASI_M_BFILL
355         stda    %g0, [%o0 + %o2] ASI_M_BFILL
356         stda    %g0, [%o0 + %o3] ASI_M_BFILL
357         subcc   %o1, 1, %o1
358         bne     1b
359          add    %o0, 256, %o0
361         retl
362          nop
364 hypersparc_copy_1page:
365 /* NOTE: This routine has to be shorter than 70insns --jj */
366         sub     %o1, %o0, %o2           ! difference
367         mov     16, %g1
369         sta     %o0, [%o0 + %o2] ASI_M_BCOPY
370         add     %o0, 32, %o0
371         sta     %o0, [%o0 + %o2] ASI_M_BCOPY
372         add     %o0, 32, %o0
373         sta     %o0, [%o0 + %o2] ASI_M_BCOPY
374         add     %o0, 32, %o0
375         sta     %o0, [%o0 + %o2] ASI_M_BCOPY
376         add     %o0, 32, %o0
377         sta     %o0, [%o0 + %o2] ASI_M_BCOPY
378         add     %o0, 32, %o0
379         sta     %o0, [%o0 + %o2] ASI_M_BCOPY
380         add     %o0, 32, %o0
381         sta     %o0, [%o0 + %o2] ASI_M_BCOPY
382         add     %o0, 32, %o0
383         sta     %o0, [%o0 + %o2] ASI_M_BCOPY
384         subcc   %g1, 1, %g1
385         bne     1b
386          add    %o0, 32, %o0
388         retl
389          nop
391         .globl  hypersparc_setup_blockops
392 hypersparc_setup_blockops:
393         sethi   %hi(bzero_1page), %o0
394         or      %o0, %lo(bzero_1page), %o0
395         sethi   %hi(hypersparc_bzero_1page), %o1
396         or      %o1, %lo(hypersparc_bzero_1page), %o1
397         sethi   %hi(hypersparc_copy_1page), %o2
398         or      %o2, %lo(hypersparc_copy_1page), %o2
399         ld      [%o1], %o4
401         add     %o1, 4, %o1
402         st      %o4, [%o0]
403         add     %o0, 4, %o0
404         cmp     %o1, %o2
405         bne     1b
406          ld     [%o1], %o4
407         sethi   %hi(__copy_1page), %o0
408         or      %o0, %lo(__copy_1page), %o0
409         sethi   %hi(hypersparc_setup_blockops), %o2
410         or      %o2, %lo(hypersparc_setup_blockops), %o2
411         ld      [%o1], %o4
413         add     %o1, 4, %o1
414         st      %o4, [%o0]
415         add     %o0, 4, %o0
416         cmp     %o1, %o2
417         bne     1b
418          ld     [%o1], %o4
419         sta     %g0, [%g0] ASI_M_FLUSH_IWHOLE
420         retl
421          nop