Linux-2.6.12-rc2
[linux-2.6.git] / arch / parisc / kernel / pacache.S
1 /*
2  *  PARISC TLB and cache flushing support
3  *  Copyright (C) 2000-2001 Hewlett-Packard (John Marvin)
4  *  Copyright (C) 2001 Matthew Wilcox (willy at parisc-linux.org)
5  *  Copyright (C) 2002 Richard Hirst (rhirst with parisc-linux.org)
6  *
7  *    This program is free software; you can redistribute it and/or modify
8  *    it under the terms of the GNU General Public License as published by
9  *    the Free Software Foundation; either version 2, or (at your option)
10  *    any later version.
11  *
12  *    This program is distributed in the hope that it will be useful,
13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *    GNU General Public License for more details.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with this program; if not, write to the Free Software
19  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 /*
23  * NOTE: fdc,fic, and pdc instructions that use base register modification
24  *       should only use index and base registers that are not shadowed,
25  *       so that the fast path emulation in the non access miss handler
26  *       can be used.
27  */
28
29 #ifdef __LP64__
30 #define ADDIB   addib,*
31 #define CMPB    cmpb,*
32 #define ANDCM   andcm,*
33
34         .level  2.0w
35 #else
36 #define ADDIB   addib,
37 #define CMPB    cmpb,
38 #define ANDCM   andcm
39
40         .level  2.0
41 #endif
42
43 #include <asm/assembly.h>
44 #include <asm/psw.h>
45 #include <asm/pgtable.h>
46 #include <asm/cache.h>
47
48         .text
49         .align  128
50
51         .export flush_tlb_all_local,code
52
53 flush_tlb_all_local:
54         .proc
55         .callinfo NO_CALLS
56         .entry
57
58         /*
59          * The pitlbe and pdtlbe instructions should only be used to
60          * flush the entire tlb. Also, there needs to be no intervening
61          * tlb operations, e.g. tlb misses, so the operation needs
62          * to happen in real mode with all interruptions disabled.
63          */
64
65         /*
66          * Once again, we do the rfi dance ... some day we need examine
67          * all of our uses of this type of code and see what can be
68          * consolidated.
69          */
70
71         rsm             PSW_SM_I, %r19          /* relied upon translation! PA 2.0 Arch. F-5 */
72         nop
73         nop
74         nop
75         nop
76         nop
77         nop
78         nop
79         
80         rsm             PSW_SM_Q, %r0           /* Turn off Q bit to load iia queue */
81         ldil            L%REAL_MODE_PSW, %r1
82         ldo             R%REAL_MODE_PSW(%r1), %r1
83         mtctl           %r1, %cr22
84         mtctl           %r0, %cr17              /* Clear IIASQ tail */
85         mtctl           %r0, %cr17              /* Clear IIASQ head */
86         ldil            L%PA(1f), %r1
87         ldo             R%PA(1f)(%r1), %r1
88         mtctl           %r1, %cr18              /* IIAOQ head */
89         ldo             4(%r1), %r1
90         mtctl           %r1, %cr18              /* IIAOQ tail */
91         rfi
92         nop
93
94 1:      ldil            L%PA(cache_info), %r1
95         ldo             R%PA(cache_info)(%r1), %r1
96
97         /* Flush Instruction Tlb */
98
99         LDREG           ITLB_SID_BASE(%r1), %r20
100         LDREG           ITLB_SID_STRIDE(%r1), %r21
101         LDREG           ITLB_SID_COUNT(%r1), %r22
102         LDREG           ITLB_OFF_BASE(%r1), %arg0
103         LDREG           ITLB_OFF_STRIDE(%r1), %arg1
104         LDREG           ITLB_OFF_COUNT(%r1), %arg2
105         LDREG           ITLB_LOOP(%r1), %arg3
106
107         ADDIB=          -1, %arg3, fitoneloop   /* Preadjust and test */
108         movb,<,n        %arg3, %r31, fitdone    /* If loop < 0, skip */
109         copy            %arg0, %r28             /* Init base addr */
110
111 fitmanyloop:                                    /* Loop if LOOP >= 2 */
112         mtsp            %r20, %sr1
113         add             %r21, %r20, %r20        /* increment space */
114         copy            %arg2, %r29             /* Init middle loop count */
115
116 fitmanymiddle:                                  /* Loop if LOOP >= 2 */
117         ADDIB>          -1, %r31, fitmanymiddle /* Adjusted inner loop decr */
118         pitlbe          0(%sr1, %r28)
119         pitlbe,m        %arg1(%sr1, %r28)       /* Last pitlbe and addr adjust */
120         ADDIB>          -1, %r29, fitmanymiddle /* Middle loop decr */
121         copy            %arg3, %r31             /* Re-init inner loop count */
122
123         movb,tr         %arg0, %r28, fitmanyloop /* Re-init base addr */
124         ADDIB<=,n       -1, %r22, fitdone       /* Outer loop count decr */
125
126 fitoneloop:                                     /* Loop if LOOP = 1 */
127         mtsp            %r20, %sr1
128         copy            %arg0, %r28             /* init base addr */
129         copy            %arg2, %r29             /* init middle loop count */
130
131 fitonemiddle:                                   /* Loop if LOOP = 1 */
132         ADDIB>          -1, %r29, fitonemiddle  /* Middle loop count decr */
133         pitlbe,m        %arg1(%sr1, %r28)       /* pitlbe for one loop */
134
135         ADDIB>          -1, %r22, fitoneloop    /* Outer loop count decr */
136         add             %r21, %r20, %r20                /* increment space */
137
138 fitdone:
139
140         /* Flush Data Tlb */
141
142         LDREG           DTLB_SID_BASE(%r1), %r20
143         LDREG           DTLB_SID_STRIDE(%r1), %r21
144         LDREG           DTLB_SID_COUNT(%r1), %r22
145         LDREG           DTLB_OFF_BASE(%r1), %arg0
146         LDREG           DTLB_OFF_STRIDE(%r1), %arg1
147         LDREG           DTLB_OFF_COUNT(%r1), %arg2
148         LDREG           DTLB_LOOP(%r1), %arg3
149
150         ADDIB=          -1, %arg3, fdtoneloop   /* Preadjust and test */
151         movb,<,n        %arg3, %r31, fdtdone    /* If loop < 0, skip */
152         copy            %arg0, %r28             /* Init base addr */
153
154 fdtmanyloop:                                    /* Loop if LOOP >= 2 */
155         mtsp            %r20, %sr1
156         add             %r21, %r20, %r20        /* increment space */
157         copy            %arg2, %r29             /* Init middle loop count */
158
159 fdtmanymiddle:                                  /* Loop if LOOP >= 2 */
160         ADDIB>          -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */
161         pdtlbe          0(%sr1, %r28)
162         pdtlbe,m        %arg1(%sr1, %r28)       /* Last pdtlbe and addr adjust */
163         ADDIB>          -1, %r29, fdtmanymiddle /* Middle loop decr */
164         copy            %arg3, %r31             /* Re-init inner loop count */
165
166         movb,tr         %arg0, %r28, fdtmanyloop /* Re-init base addr */
167         ADDIB<=,n       -1, %r22,fdtdone        /* Outer loop count decr */
168
169 fdtoneloop:                                     /* Loop if LOOP = 1 */
170         mtsp            %r20, %sr1
171         copy            %arg0, %r28             /* init base addr */
172         copy            %arg2, %r29             /* init middle loop count */
173
174 fdtonemiddle:                                   /* Loop if LOOP = 1 */
175         ADDIB>          -1, %r29, fdtonemiddle  /* Middle loop count decr */
176         pdtlbe,m        %arg1(%sr1, %r28)       /* pdtlbe for one loop */
177
178         ADDIB>          -1, %r22, fdtoneloop    /* Outer loop count decr */
179         add             %r21, %r20, %r20        /* increment space */
180
181 fdtdone:
182
183         /* Switch back to virtual mode */
184
185         rsm             PSW_SM_Q, %r0           /* clear Q bit to load iia queue */
186         ldil            L%KERNEL_PSW, %r1
187         ldo             R%KERNEL_PSW(%r1), %r1
188         or              %r1, %r19, %r1          /* Set I bit if set on entry */
189         mtctl           %r1, %cr22
190         mtctl           %r0, %cr17              /* Clear IIASQ tail */
191         mtctl           %r0, %cr17              /* Clear IIASQ head */
192         ldil            L%(2f), %r1
193         ldo             R%(2f)(%r1), %r1
194         mtctl           %r1, %cr18              /* IIAOQ head */
195         ldo             4(%r1), %r1
196         mtctl           %r1, %cr18              /* IIAOQ tail */
197         rfi
198         nop
199
200 2:      bv              %r0(%r2)
201         nop
202         .exit
203
204         .procend
205
206         .export flush_instruction_cache_local,code
207         .import cache_info,data
208
209 flush_instruction_cache_local:
210         .proc
211         .callinfo NO_CALLS
212         .entry
213
214         mtsp            %r0, %sr1
215         ldil            L%cache_info, %r1
216         ldo             R%cache_info(%r1), %r1
217
218         /* Flush Instruction Cache */
219
220         LDREG           ICACHE_BASE(%r1), %arg0
221         LDREG           ICACHE_STRIDE(%r1), %arg1
222         LDREG           ICACHE_COUNT(%r1), %arg2
223         LDREG           ICACHE_LOOP(%r1), %arg3
224         rsm             PSW_SM_I, %r22          /* No mmgt ops during loop*/
225         ADDIB=          -1, %arg3, fioneloop    /* Preadjust and test */
226         movb,<,n        %arg3, %r31, fisync     /* If loop < 0, do sync */
227
228 fimanyloop:                                     /* Loop if LOOP >= 2 */
229         ADDIB>          -1, %r31, fimanyloop    /* Adjusted inner loop decr */
230         fice            0(%sr1, %arg0)
231         fice,m          %arg1(%sr1, %arg0)      /* Last fice and addr adjust */
232         movb,tr         %arg3, %r31, fimanyloop /* Re-init inner loop count */
233         ADDIB<=,n       -1, %arg2, fisync       /* Outer loop decr */
234
235 fioneloop:                                      /* Loop if LOOP = 1 */
236         ADDIB>          -1, %arg2, fioneloop    /* Outer loop count decr */
237         fice,m          %arg1(%sr1, %arg0)      /* Fice for one loop */
238
239 fisync:
240         sync
241         mtsm            %r22
242         bv              %r0(%r2)
243         nop
244         .exit
245
246         .procend
247
248         .export flush_data_cache_local, code
249         .import cache_info, data
250
251 flush_data_cache_local:
252         .proc
253         .callinfo NO_CALLS
254         .entry
255
256         mtsp            %r0, %sr1
257         ldil            L%cache_info, %r1
258         ldo             R%cache_info(%r1), %r1
259
260         /* Flush Data Cache */
261
262         LDREG           DCACHE_BASE(%r1), %arg0
263         LDREG           DCACHE_STRIDE(%r1), %arg1
264         LDREG           DCACHE_COUNT(%r1), %arg2
265         LDREG           DCACHE_LOOP(%r1), %arg3
266         rsm             PSW_SM_I, %r22
267         ADDIB=          -1, %arg3, fdoneloop    /* Preadjust and test */
268         movb,<,n        %arg3, %r31, fdsync     /* If loop < 0, do sync */
269
270 fdmanyloop:                                     /* Loop if LOOP >= 2 */
271         ADDIB>          -1, %r31, fdmanyloop    /* Adjusted inner loop decr */
272         fdce            0(%sr1, %arg0)
273         fdce,m          %arg1(%sr1, %arg0)      /* Last fdce and addr adjust */
274         movb,tr         %arg3, %r31, fdmanyloop /* Re-init inner loop count */
275         ADDIB<=,n       -1, %arg2, fdsync       /* Outer loop decr */
276
277 fdoneloop:                                      /* Loop if LOOP = 1 */
278         ADDIB>          -1, %arg2, fdoneloop    /* Outer loop count decr */
279         fdce,m          %arg1(%sr1, %arg0)      /* Fdce for one loop */
280
281 fdsync:
282         syncdma
283         sync
284         mtsm            %r22
285         bv              %r0(%r2)
286         nop
287         .exit
288
289         .procend
290
291         .export copy_user_page_asm,code
292         .align  16
293
294 copy_user_page_asm:
295         .proc
296         .callinfo NO_CALLS
297         .entry
298
299 #ifdef __LP64__
300         /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
301          * Unroll the loop by hand and arrange insn appropriately.
302          * GCC probably can do this just as well.
303          */
304
305         ldd             0(%r25), %r19
306         ldi             32, %r1                 /* PAGE_SIZE/128 == 32 */
307         ldw             64(%r25), %r0           /* prefetch 1 cacheline ahead */
308         ldw             128(%r25), %r0          /* prefetch 2 */
309
310 1:      ldd             8(%r25), %r20
311         ldw             192(%r25), %r0          /* prefetch 3 */
312         ldw             256(%r25), %r0          /* prefetch 4 */
313
314         ldd             16(%r25), %r21
315         ldd             24(%r25), %r22
316         std             %r19, 0(%r26)
317         std             %r20, 8(%r26)
318
319         ldd             32(%r25), %r19
320         ldd             40(%r25), %r20
321         std             %r21, 16(%r26)
322         std             %r22, 24(%r26)
323
324         ldd             48(%r25), %r21
325         ldd             56(%r25), %r22
326         std             %r19, 32(%r26)
327         std             %r20, 40(%r26)
328
329         ldd             64(%r25), %r19
330         ldd             72(%r25), %r20
331         std             %r21, 48(%r26)
332         std             %r22, 56(%r26)
333
334         ldd             80(%r25), %r21
335         ldd             88(%r25), %r22
336         std             %r19, 64(%r26)
337         std             %r20, 72(%r26)
338
339         ldd              96(%r25), %r19
340         ldd             104(%r25), %r20
341         std             %r21, 80(%r26)
342         std             %r22, 88(%r26)
343
344         ldd             112(%r25), %r21
345         ldd             120(%r25), %r22
346         std             %r19, 96(%r26)
347         std             %r20, 104(%r26)
348
349         ldo             128(%r25), %r25
350         std             %r21, 112(%r26)
351         std             %r22, 120(%r26)
352         ldo             128(%r26), %r26
353
354         ADDIB>          -1, %r1, 1b             /* bundle 10 */
355         ldd             0(%r25), %r19           /* start next loads */
356
357 #else
358
359         /*
360          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
361          * bundles (very restricted rules for bundling).
362          * Note that until (if) we start saving
363          * the full 64 bit register values on interrupt, we can't
364          * use ldd/std on a 32 bit kernel.
365          */
366         ldi             64, %r1         /* PAGE_SIZE/64 == 64 */
367
368 1:
369         ldw             0(%r25), %r19
370         ldw             4(%r25), %r20
371         ldw             8(%r25), %r21
372         ldw             12(%r25), %r22
373         stw             %r19, 0(%r26)
374         stw             %r20, 4(%r26)
375         stw             %r21, 8(%r26)
376         stw             %r22, 12(%r26)
377         ldw             16(%r25), %r19
378         ldw             20(%r25), %r20
379         ldw             24(%r25), %r21
380         ldw             28(%r25), %r22
381         stw             %r19, 16(%r26)
382         stw             %r20, 20(%r26)
383         stw             %r21, 24(%r26)
384         stw             %r22, 28(%r26)
385         ldw             32(%r25), %r19
386         ldw             36(%r25), %r20
387         ldw             40(%r25), %r21
388         ldw             44(%r25), %r22
389         stw             %r19, 32(%r26)
390         stw             %r20, 36(%r26)
391         stw             %r21, 40(%r26)
392         stw             %r22, 44(%r26)
393         ldw             48(%r25), %r19
394         ldw             52(%r25), %r20
395         ldw             56(%r25), %r21
396         ldw             60(%r25), %r22
397         stw             %r19, 48(%r26)
398         stw             %r20, 52(%r26)
399         stw             %r21, 56(%r26)
400         stw             %r22, 60(%r26)
401         ldo             64(%r26), %r26
402         ADDIB>          -1, %r1, 1b
403         ldo             64(%r25), %r25
404 #endif
405         bv              %r0(%r2)
406         nop
407         .exit
408
409         .procend
410
411 /*
412  * NOTE: Code in clear_user_page has a hard coded dependency on the
413  *       maximum alias boundary being 4 Mb. We've been assured by the
414  *       parisc chip designers that there will not ever be a parisc
415  *       chip with a larger alias boundary (Never say never :-) ).
416  *
417  *       Subtle: the dtlb miss handlers support the temp alias region by
418  *       "knowing" that if a dtlb miss happens within the temp alias
419  *       region it must have occurred while in clear_user_page. Since
420  *       this routine makes use of processor local translations, we
421  *       don't want to insert them into the kernel page table. Instead,
422  *       we load up some general registers (they need to be registers
423  *       which aren't shadowed) with the physical page numbers (preshifted
424  *       for tlb insertion) needed to insert the translations. When we
425  *       miss on the translation, the dtlb miss handler inserts the
426  *       translation into the tlb using these values:
427  *
428  *          %r26 physical page (shifted for tlb insert) of "to" translation
429  *          %r23 physical page (shifted for tlb insert) of "from" translation
430  */
431
432 #if 0
433
434         /*
435          * We can't do this since copy_user_page is used to bring in
436          * file data that might have instructions. Since the data would
437          * then need to be flushed out so the i-fetch can see it, it
438          * makes more sense to just copy through the kernel translation
439          * and flush it.
440          *
441          * I'm still keeping this around because it may be possible to
442          * use it if more information is passed into copy_user_page().
443          * Have to do some measurements to see if it is worthwhile to
444          * lobby for such a change.
445          */
446
447         .export copy_user_page_asm,code
448
449 copy_user_page_asm:
450         .proc
451         .callinfo NO_CALLS
452         .entry
453
454         ldil            L%(__PAGE_OFFSET), %r1
455         sub             %r26, %r1, %r26
456         sub             %r25, %r1, %r23         /* move physical addr into non shadowed reg */
457
458         ldil            L%(TMPALIAS_MAP_START), %r28
459 #ifdef __LP64__
460         extrd,u         %r26,56,32, %r26                /* convert phys addr to tlb insert format */
461         extrd,u         %r23,56,32, %r23                /* convert phys addr to tlb insert format */
462         depd            %r24,63,22, %r28                /* Form aliased virtual address 'to' */
463         depdi           0, 63,12, %r28          /* Clear any offset bits */
464         copy            %r28, %r29
465         depdi           1, 41,1, %r29           /* Form aliased virtual address 'from' */
466 #else
467         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
468         extrw,u         %r23, 24,25, %r23       /* convert phys addr to tlb insert format */
469         depw            %r24, 31,22, %r28       /* Form aliased virtual address 'to' */
470         depwi           0, 31,12, %r28          /* Clear any offset bits */
471         copy            %r28, %r29
472         depwi           1, 9,1, %r29            /* Form aliased virtual address 'from' */
473 #endif
474
475         /* Purge any old translations */
476
477         pdtlb           0(%r28)
478         pdtlb           0(%r29)
479
480         ldi             64, %r1
481
482         /*
483          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
484          * bundles (very restricted rules for bundling). It probably
485          * does OK on PCXU and better, but we could do better with
486          * ldd/std instructions. Note that until (if) we start saving
487          * the full 64 bit register values on interrupt, we can't
488          * use ldd/std on a 32 bit kernel.
489          */
490
491
492 1:
493         ldw             0(%r29), %r19
494         ldw             4(%r29), %r20
495         ldw             8(%r29), %r21
496         ldw             12(%r29), %r22
497         stw             %r19, 0(%r28)
498         stw             %r20, 4(%r28)
499         stw             %r21, 8(%r28)
500         stw             %r22, 12(%r28)
501         ldw             16(%r29), %r19
502         ldw             20(%r29), %r20
503         ldw             24(%r29), %r21
504         ldw             28(%r29), %r22
505         stw             %r19, 16(%r28)
506         stw             %r20, 20(%r28)
507         stw             %r21, 24(%r28)
508         stw             %r22, 28(%r28)
509         ldw             32(%r29), %r19
510         ldw             36(%r29), %r20
511         ldw             40(%r29), %r21
512         ldw             44(%r29), %r22
513         stw             %r19, 32(%r28)
514         stw             %r20, 36(%r28)
515         stw             %r21, 40(%r28)
516         stw             %r22, 44(%r28)
517         ldw             48(%r29), %r19
518         ldw             52(%r29), %r20
519         ldw             56(%r29), %r21
520         ldw             60(%r29), %r22
521         stw             %r19, 48(%r28)
522         stw             %r20, 52(%r28)
523         stw             %r21, 56(%r28)
524         stw             %r22, 60(%r28)
525         ldo             64(%r28), %r28
526         ADDIB>          -1, %r1,1b
527         ldo             64(%r29), %r29
528
529         bv              %r0(%r2)
530         nop
531         .exit
532
533         .procend
534 #endif
535
536         .export __clear_user_page_asm,code
537
538 __clear_user_page_asm:
539         .proc
540         .callinfo NO_CALLS
541         .entry
542
543         tophys_r1       %r26
544
545         ldil            L%(TMPALIAS_MAP_START), %r28
546 #ifdef __LP64__
547 #if (TMPALIAS_MAP_START >= 0x80000000)
548         depdi           0, 31,32, %r28          /* clear any sign extension */
549 #endif
550         extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
551         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
552         depdi           0, 63,12, %r28          /* Clear any offset bits */
553 #else
554         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
555         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
556         depwi           0, 31,12, %r28          /* Clear any offset bits */
557 #endif
558
559         /* Purge any old translation */
560
561         pdtlb           0(%r28)
562
563 #ifdef __LP64__
564         ldi             32, %r1                 /* PAGE_SIZE/128 == 32 */
565
566         /* PREFETCH (Write) has not (yet) been proven to help here */
567 /* #define      PREFETCHW_OP    ldd             256(%0), %r0 */
568
569 1:      std             %r0, 0(%r28)
570         std             %r0, 8(%r28)
571         std             %r0, 16(%r28)
572         std             %r0, 24(%r28)
573         std             %r0, 32(%r28)
574         std             %r0, 40(%r28)
575         std             %r0, 48(%r28)
576         std             %r0, 56(%r28)
577         std             %r0, 64(%r28)
578         std             %r0, 72(%r28)
579         std             %r0, 80(%r28)
580         std             %r0, 88(%r28)
581         std             %r0, 96(%r28)
582         std             %r0, 104(%r28)
583         std             %r0, 112(%r28)
584         std             %r0, 120(%r28)
585         ADDIB>          -1, %r1, 1b
586         ldo             128(%r28), %r28
587
588 #else   /* ! __LP64 */
589
590         ldi             64, %r1                 /* PAGE_SIZE/64 == 64 */
591
592 1:
593         stw             %r0, 0(%r28)
594         stw             %r0, 4(%r28)
595         stw             %r0, 8(%r28)
596         stw             %r0, 12(%r28)
597         stw             %r0, 16(%r28)
598         stw             %r0, 20(%r28)
599         stw             %r0, 24(%r28)
600         stw             %r0, 28(%r28)
601         stw             %r0, 32(%r28)
602         stw             %r0, 36(%r28)
603         stw             %r0, 40(%r28)
604         stw             %r0, 44(%r28)
605         stw             %r0, 48(%r28)
606         stw             %r0, 52(%r28)
607         stw             %r0, 56(%r28)
608         stw             %r0, 60(%r28)
609         ADDIB>          -1, %r1, 1b
610         ldo             64(%r28), %r28
611 #endif  /* __LP64 */
612
613         bv              %r0(%r2)
614         nop
615         .exit
616
617         .procend
618
619         .export flush_kernel_dcache_page
620
621 flush_kernel_dcache_page:
622         .proc
623         .callinfo NO_CALLS
624         .entry
625
626         ldil            L%dcache_stride, %r1
627         ldw             R%dcache_stride(%r1), %r23
628
629 #ifdef __LP64__
630         depdi,z         1, 63-PAGE_SHIFT,1, %r25
631 #else
632         depwi,z         1, 31-PAGE_SHIFT,1, %r25
633 #endif
634         add             %r26, %r25, %r25
635         sub             %r25, %r23, %r25
636
637
638 1:      fdc,m           %r23(%r26)
639         fdc,m           %r23(%r26)
640         fdc,m           %r23(%r26)
641         fdc,m           %r23(%r26)
642         fdc,m           %r23(%r26)
643         fdc,m           %r23(%r26)
644         fdc,m           %r23(%r26)
645         fdc,m           %r23(%r26)
646         fdc,m           %r23(%r26)
647         fdc,m           %r23(%r26)
648         fdc,m           %r23(%r26)
649         fdc,m           %r23(%r26)
650         fdc,m           %r23(%r26)
651         fdc,m           %r23(%r26)
652         fdc,m           %r23(%r26)
653         CMPB<<          %r26, %r25,1b
654         fdc,m           %r23(%r26)
655
656         sync
657         bv              %r0(%r2)
658         nop
659         .exit
660
661         .procend
662         
663         .export flush_user_dcache_page
664
665 flush_user_dcache_page:
666         .proc
667         .callinfo NO_CALLS
668         .entry
669
670         ldil            L%dcache_stride, %r1
671         ldw             R%dcache_stride(%r1), %r23
672
673 #ifdef __LP64__
674         depdi,z         1,63-PAGE_SHIFT,1, %r25
675 #else
676         depwi,z         1,31-PAGE_SHIFT,1, %r25
677 #endif
678         add             %r26, %r25, %r25
679         sub             %r25, %r23, %r25
680
681
682 1:      fdc,m           %r23(%sr3, %r26)
683         fdc,m           %r23(%sr3, %r26)
684         fdc,m           %r23(%sr3, %r26)
685         fdc,m           %r23(%sr3, %r26)
686         fdc,m           %r23(%sr3, %r26)
687         fdc,m           %r23(%sr3, %r26)
688         fdc,m           %r23(%sr3, %r26)
689         fdc,m           %r23(%sr3, %r26)
690         fdc,m           %r23(%sr3, %r26)
691         fdc,m           %r23(%sr3, %r26)
692         fdc,m           %r23(%sr3, %r26)
693         fdc,m           %r23(%sr3, %r26)
694         fdc,m           %r23(%sr3, %r26)
695         fdc,m           %r23(%sr3, %r26)
696         fdc,m           %r23(%sr3, %r26)
697         CMPB<<          %r26, %r25,1b
698         fdc,m           %r23(%sr3, %r26)
699
700         sync
701         bv              %r0(%r2)
702         nop
703         .exit
704
705         .procend
706
707         .export flush_user_icache_page
708
709 flush_user_icache_page:
710         .proc
711         .callinfo NO_CALLS
712         .entry
713
714         ldil            L%dcache_stride, %r1
715         ldw             R%dcache_stride(%r1), %r23
716
717 #ifdef __LP64__
718         depdi,z         1, 63-PAGE_SHIFT,1, %r25
719 #else
720         depwi,z         1, 31-PAGE_SHIFT,1, %r25
721 #endif
722         add             %r26, %r25, %r25
723         sub             %r25, %r23, %r25
724
725
726 1:      fic,m           %r23(%sr3, %r26)
727         fic,m           %r23(%sr3, %r26)
728         fic,m           %r23(%sr3, %r26)
729         fic,m           %r23(%sr3, %r26)
730         fic,m           %r23(%sr3, %r26)
731         fic,m           %r23(%sr3, %r26)
732         fic,m           %r23(%sr3, %r26)
733         fic,m           %r23(%sr3, %r26)
734         fic,m           %r23(%sr3, %r26)
735         fic,m           %r23(%sr3, %r26)
736         fic,m           %r23(%sr3, %r26)
737         fic,m           %r23(%sr3, %r26)
738         fic,m           %r23(%sr3, %r26)
739         fic,m           %r23(%sr3, %r26)
740         fic,m           %r23(%sr3, %r26)
741         CMPB<<          %r26, %r25,1b
742         fic,m           %r23(%sr3, %r26)
743
744         sync
745         bv              %r0(%r2)
746         nop
747         .exit
748
749         .procend
750
751
752         .export purge_kernel_dcache_page
753
754 purge_kernel_dcache_page:
755         .proc
756         .callinfo NO_CALLS
757         .entry
758
759         ldil            L%dcache_stride, %r1
760         ldw             R%dcache_stride(%r1), %r23
761
762 #ifdef __LP64__
763         depdi,z         1, 63-PAGE_SHIFT,1, %r25
764 #else
765         depwi,z         1, 31-PAGE_SHIFT,1, %r25
766 #endif
767         add             %r26, %r25, %r25
768         sub             %r25, %r23, %r25
769
770 1:      pdc,m           %r23(%r26)
771         pdc,m           %r23(%r26)
772         pdc,m           %r23(%r26)
773         pdc,m           %r23(%r26)
774         pdc,m           %r23(%r26)
775         pdc,m           %r23(%r26)
776         pdc,m           %r23(%r26)
777         pdc,m           %r23(%r26)
778         pdc,m           %r23(%r26)
779         pdc,m           %r23(%r26)
780         pdc,m           %r23(%r26)
781         pdc,m           %r23(%r26)
782         pdc,m           %r23(%r26)
783         pdc,m           %r23(%r26)
784         pdc,m           %r23(%r26)
785         CMPB<<          %r26, %r25, 1b
786         pdc,m           %r23(%r26)
787
788         sync
789         bv              %r0(%r2)
790         nop
791         .exit
792
793         .procend
794
795 #if 0
796         /* Currently not used, but it still is a possible alternate
797          * solution.
798          */
799
800         .export flush_alias_page
801
802 flush_alias_page:
803         .proc
804         .callinfo NO_CALLS
805         .entry
806
807         tophys_r1               %r26
808
809         ldil            L%(TMPALIAS_MAP_START), %r28
810 #ifdef __LP64__
811         extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
812         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
813         depdi           0, 63,12, %r28          /* Clear any offset bits */
814 #else
815         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
816         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
817         depwi           0, 31,12, %r28          /* Clear any offset bits */
818 #endif
819
820         /* Purge any old translation */
821
822         pdtlb           0(%r28)
823
824         ldil            L%dcache_stride, %r1
825         ldw             R%dcache_stride(%r1), %r23
826
827 #ifdef __LP64__
828         depdi,z         1, 63-PAGE_SHIFT,1, %r29
829 #else
830         depwi,z         1, 31-PAGE_SHIFT,1, %r29
831 #endif
832         add             %r28, %r29, %r29
833         sub             %r29, %r23, %r29
834
835 1:      fdc,m           %r23(%r28)
836         fdc,m           %r23(%r28)
837         fdc,m           %r23(%r28)
838         fdc,m           %r23(%r28)
839         fdc,m           %r23(%r28)
840         fdc,m           %r23(%r28)
841         fdc,m           %r23(%r28)
842         fdc,m           %r23(%r28)
843         fdc,m           %r23(%r28)
844         fdc,m           %r23(%r28)
845         fdc,m           %r23(%r28)
846         fdc,m           %r23(%r28)
847         fdc,m           %r23(%r28)
848         fdc,m           %r23(%r28)
849         fdc,m           %r23(%r28)
850         CMPB<<          %r28, %r29, 1b
851         fdc,m           %r23(%r28)
852
853         sync
854         bv              %r0(%r2)
855         nop
856         .exit
857
858         .procend
859 #endif
860
861         .export flush_user_dcache_range_asm
862
863 flush_user_dcache_range_asm:
864         .proc
865         .callinfo NO_CALLS
866         .entry
867
868         ldil            L%dcache_stride, %r1
869         ldw             R%dcache_stride(%r1), %r23
870         ldo             -1(%r23), %r21
871         ANDCM           %r26, %r21, %r26
872
873 1:      CMPB<<,n        %r26, %r25, 1b
874         fdc,m           %r23(%sr3, %r26)
875
876         sync
877         bv              %r0(%r2)
878         nop
879         .exit
880
881         .procend
882
883         .export flush_kernel_dcache_range_asm
884
885 flush_kernel_dcache_range_asm:
886         .proc
887         .callinfo NO_CALLS
888         .entry
889
890         ldil            L%dcache_stride, %r1
891         ldw             R%dcache_stride(%r1), %r23
892         ldo             -1(%r23), %r21
893         ANDCM           %r26, %r21, %r26
894
895 1:      CMPB<<,n        %r26, %r25,1b
896         fdc,m           %r23(%r26)
897
898         sync
899         syncdma
900         bv              %r0(%r2)
901         nop
902         .exit
903
904         .procend
905
906         .export flush_user_icache_range_asm
907
908 flush_user_icache_range_asm:
909         .proc
910         .callinfo NO_CALLS
911         .entry
912
913         ldil            L%icache_stride, %r1
914         ldw             R%icache_stride(%r1), %r23
915         ldo             -1(%r23), %r21
916         ANDCM           %r26, %r21, %r26
917
918 1:      CMPB<<,n        %r26, %r25,1b
919         fic,m           %r23(%sr3, %r26)
920
921         sync
922         bv              %r0(%r2)
923         nop
924         .exit
925
926         .procend
927
928         .export flush_kernel_icache_page
929
930 flush_kernel_icache_page:
931         .proc
932         .callinfo NO_CALLS
933         .entry
934
935         ldil            L%icache_stride, %r1
936         ldw             R%icache_stride(%r1), %r23
937
938 #ifdef __LP64__
939         depdi,z         1, 63-PAGE_SHIFT,1, %r25
940 #else
941         depwi,z         1, 31-PAGE_SHIFT,1, %r25
942 #endif
943         add             %r26, %r25, %r25
944         sub             %r25, %r23, %r25
945
946
947 1:      fic,m           %r23(%r26)
948         fic,m           %r23(%r26)
949         fic,m           %r23(%r26)
950         fic,m           %r23(%r26)
951         fic,m           %r23(%r26)
952         fic,m           %r23(%r26)
953         fic,m           %r23(%r26)
954         fic,m           %r23(%r26)
955         fic,m           %r23(%r26)
956         fic,m           %r23(%r26)
957         fic,m           %r23(%r26)
958         fic,m           %r23(%r26)
959         fic,m           %r23(%r26)
960         fic,m           %r23(%r26)
961         fic,m           %r23(%r26)
962         CMPB<<          %r26, %r25, 1b
963         fic,m           %r23(%r26)
964
965         sync
966         bv              %r0(%r2)
967         nop
968         .exit
969
970         .procend
971
972         .export flush_kernel_icache_range_asm
973
974 flush_kernel_icache_range_asm:
975         .proc
976         .callinfo NO_CALLS
977         .entry
978
979         ldil            L%icache_stride, %r1
980         ldw             R%icache_stride(%r1), %r23
981         ldo             -1(%r23), %r21
982         ANDCM           %r26, %r21, %r26
983
984 1:      CMPB<<,n        %r26, %r25, 1b
985         fic,m           %r23(%r26)
986
987         sync
988         bv              %r0(%r2)
989         nop
990         .exit
991
992         .procend
993
994         .align  128
995
996         .export disable_sr_hashing_asm,code
997
998 disable_sr_hashing_asm:
999         .proc
1000         .callinfo NO_CALLS
1001         .entry
1002
1003         /* Switch to real mode */
1004
1005         ssm             0, %r0                  /* relied upon translation! */
1006         nop
1007         nop
1008         nop
1009         nop
1010         nop
1011         nop
1012         nop
1013         
1014         rsm             (PSW_SM_Q|PSW_SM_I), %r0 /* disable Q&I to load the iia queue */
1015         ldil            L%REAL_MODE_PSW, %r1
1016         ldo             R%REAL_MODE_PSW(%r1), %r1
1017         mtctl           %r1, %cr22
1018         mtctl           %r0, %cr17              /* Clear IIASQ tail */
1019         mtctl           %r0, %cr17              /* Clear IIASQ head */
1020         ldil            L%PA(1f), %r1
1021         ldo             R%PA(1f)(%r1), %r1
1022         mtctl           %r1, %cr18              /* IIAOQ head */
1023         ldo             4(%r1), %r1
1024         mtctl           %r1, %cr18              /* IIAOQ tail */
1025         rfi
1026         nop
1027
1028 1:      cmpib,=,n       SRHASH_PCXST, %r26,srdis_pcxs
1029         cmpib,=,n       SRHASH_PCXL, %r26,srdis_pcxl
1030         cmpib,=,n       SRHASH_PA20, %r26,srdis_pa20
1031         b,n             srdis_done
1032
1033 srdis_pcxs:
1034
1035         /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
1036
1037         .word           0x141c1a00              /* mfdiag %dr0, %r28 */
1038         .word           0x141c1a00              /* must issue twice */
1039         depwi           0,18,1, %r28            /* Clear DHE (dcache hash enable) */
1040         depwi           0,20,1, %r28            /* Clear IHE (icache hash enable) */
1041         .word           0x141c1600              /* mtdiag %r28, %dr0 */
1042         .word           0x141c1600              /* must issue twice */
1043         b,n             srdis_done
1044
1045 srdis_pcxl:
1046
1047         /* Disable Space Register Hashing for PCXL */
1048
1049         .word           0x141c0600              /* mfdiag %dr0, %r28 */
1050         depwi           0,28,2, %r28            /* Clear DHASH_EN & IHASH_EN */
1051         .word           0x141c0240              /* mtdiag %r28, %dr0 */
1052         b,n             srdis_done
1053
1054 srdis_pa20:
1055
1056         /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+ */
1057
1058         .word           0x144008bc              /* mfdiag %dr2, %r28 */
1059         depdi           0, 54,1, %r28           /* clear DIAG_SPHASH_ENAB (bit 54) */
1060         .word           0x145c1840              /* mtdiag %r28, %dr2 */
1061
1062 srdis_done:
1063
1064         /* Switch back to virtual mode */
1065
1066         rsm             PSW_SM_Q, %r0           /* clear Q bit to load iia queue */
1067         ldil            L%KERNEL_PSW, %r1
1068         ldo             R%KERNEL_PSW(%r1), %r1
1069         mtctl           %r1, %cr22
1070         mtctl           %r0, %cr17              /* Clear IIASQ tail */
1071         mtctl           %r0, %cr17              /* Clear IIASQ head */
1072         ldil            L%(2f), %r1
1073         ldo             R%(2f)(%r1), %r1
1074         mtctl           %r1, %cr18              /* IIAOQ head */
1075         ldo             4(%r1), %r1
1076         mtctl           %r1, %cr18              /* IIAOQ tail */
1077         rfi
1078         nop
1079
1080 2:      bv              %r0(%r2)
1081         nop
1082         .exit
1083
1084         .procend
1085
1086         .end