Merge branch 'akpm'
[linux-2.6/next.git] / arch / parisc / kernel / pacache.S
blob93ff3d90edd1edc8a0d5d41ecc4adae27efe45f3
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  */
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  */
29 #ifdef CONFIG_64BIT
30         .level  2.0w
31 #else
32         .level  2.0
33 #endif
35 #include <asm/psw.h>
36 #include <asm/assembly.h>
37 #include <asm/pgtable.h>
38 #include <asm/cache.h>
39 #include <linux/linkage.h>
41         .text
42         .align  128
44 ENTRY(flush_tlb_all_local)
45         .proc
46         .callinfo NO_CALLS
47         .entry
49         /*
50          * The pitlbe and pdtlbe instructions should only be used to
51          * flush the entire tlb. Also, there needs to be no intervening
52          * tlb operations, e.g. tlb misses, so the operation needs
53          * to happen in real mode with all interruptions disabled.
54          */
56         /* pcxt_ssm_bug - relied upon translation! PA 2.0 Arch. F-4 and F-5 */
57         rsm             PSW_SM_I, %r19          /* save I-bit state */
58         load32          PA(1f), %r1
59         nop
60         nop
61         nop
62         nop
63         nop
65         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
66         mtctl           %r0, %cr17              /* Clear IIASQ tail */
67         mtctl           %r0, %cr17              /* Clear IIASQ head */
68         mtctl           %r1, %cr18              /* IIAOQ head */
69         ldo             4(%r1), %r1
70         mtctl           %r1, %cr18              /* IIAOQ tail */
71         load32          REAL_MODE_PSW, %r1
72         mtctl           %r1, %ipsw
73         rfi
74         nop
76 1:      load32          PA(cache_info), %r1
78         /* Flush Instruction Tlb */
80         LDREG           ITLB_SID_BASE(%r1), %r20
81         LDREG           ITLB_SID_STRIDE(%r1), %r21
82         LDREG           ITLB_SID_COUNT(%r1), %r22
83         LDREG           ITLB_OFF_BASE(%r1), %arg0
84         LDREG           ITLB_OFF_STRIDE(%r1), %arg1
85         LDREG           ITLB_OFF_COUNT(%r1), %arg2
86         LDREG           ITLB_LOOP(%r1), %arg3
88         addib,COND(=)           -1, %arg3, fitoneloop   /* Preadjust and test */
89         movb,<,n        %arg3, %r31, fitdone    /* If loop < 0, skip */
90         copy            %arg0, %r28             /* Init base addr */
92 fitmanyloop:                                    /* Loop if LOOP >= 2 */
93         mtsp            %r20, %sr1
94         add             %r21, %r20, %r20        /* increment space */
95         copy            %arg2, %r29             /* Init middle loop count */
97 fitmanymiddle:                                  /* Loop if LOOP >= 2 */
98         addib,COND(>)           -1, %r31, fitmanymiddle /* Adjusted inner loop decr */
99         pitlbe          0(%sr1, %r28)
100         pitlbe,m        %arg1(%sr1, %r28)       /* Last pitlbe and addr adjust */
101         addib,COND(>)           -1, %r29, fitmanymiddle /* Middle loop decr */
102         copy            %arg3, %r31             /* Re-init inner loop count */
104         movb,tr         %arg0, %r28, fitmanyloop /* Re-init base addr */
105         addib,COND(<=),n        -1, %r22, fitdone       /* Outer loop count decr */
107 fitoneloop:                                     /* Loop if LOOP = 1 */
108         mtsp            %r20, %sr1
109         copy            %arg0, %r28             /* init base addr */
110         copy            %arg2, %r29             /* init middle loop count */
112 fitonemiddle:                                   /* Loop if LOOP = 1 */
113         addib,COND(>)           -1, %r29, fitonemiddle  /* Middle loop count decr */
114         pitlbe,m        %arg1(%sr1, %r28)       /* pitlbe for one loop */
116         addib,COND(>)           -1, %r22, fitoneloop    /* Outer loop count decr */
117         add             %r21, %r20, %r20                /* increment space */
119 fitdone:
121         /* Flush Data Tlb */
123         LDREG           DTLB_SID_BASE(%r1), %r20
124         LDREG           DTLB_SID_STRIDE(%r1), %r21
125         LDREG           DTLB_SID_COUNT(%r1), %r22
126         LDREG           DTLB_OFF_BASE(%r1), %arg0
127         LDREG           DTLB_OFF_STRIDE(%r1), %arg1
128         LDREG           DTLB_OFF_COUNT(%r1), %arg2
129         LDREG           DTLB_LOOP(%r1), %arg3
131         addib,COND(=)           -1, %arg3, fdtoneloop   /* Preadjust and test */
132         movb,<,n        %arg3, %r31, fdtdone    /* If loop < 0, skip */
133         copy            %arg0, %r28             /* Init base addr */
135 fdtmanyloop:                                    /* Loop if LOOP >= 2 */
136         mtsp            %r20, %sr1
137         add             %r21, %r20, %r20        /* increment space */
138         copy            %arg2, %r29             /* Init middle loop count */
140 fdtmanymiddle:                                  /* Loop if LOOP >= 2 */
141         addib,COND(>)           -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */
142         pdtlbe          0(%sr1, %r28)
143         pdtlbe,m        %arg1(%sr1, %r28)       /* Last pdtlbe and addr adjust */
144         addib,COND(>)           -1, %r29, fdtmanymiddle /* Middle loop decr */
145         copy            %arg3, %r31             /* Re-init inner loop count */
147         movb,tr         %arg0, %r28, fdtmanyloop /* Re-init base addr */
148         addib,COND(<=),n        -1, %r22,fdtdone        /* Outer loop count decr */
150 fdtoneloop:                                     /* Loop if LOOP = 1 */
151         mtsp            %r20, %sr1
152         copy            %arg0, %r28             /* init base addr */
153         copy            %arg2, %r29             /* init middle loop count */
155 fdtonemiddle:                                   /* Loop if LOOP = 1 */
156         addib,COND(>)           -1, %r29, fdtonemiddle  /* Middle loop count decr */
157         pdtlbe,m        %arg1(%sr1, %r28)       /* pdtlbe for one loop */
159         addib,COND(>)           -1, %r22, fdtoneloop    /* Outer loop count decr */
160         add             %r21, %r20, %r20        /* increment space */
163 fdtdone:
164         /*
165          * Switch back to virtual mode
166          */
167         /* pcxt_ssm_bug */
168         rsm             PSW_SM_I, %r0
169         load32          2f, %r1
170         nop
171         nop
172         nop
173         nop
174         nop
176         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
177         mtctl           %r0, %cr17              /* Clear IIASQ tail */
178         mtctl           %r0, %cr17              /* Clear IIASQ head */
179         mtctl           %r1, %cr18              /* IIAOQ head */
180         ldo             4(%r1), %r1
181         mtctl           %r1, %cr18              /* IIAOQ tail */
182         load32          KERNEL_PSW, %r1
183         or              %r1, %r19, %r1  /* I-bit to state on entry */
184         mtctl           %r1, %ipsw      /* restore I-bit (entire PSW) */
185         rfi
186         nop
188 2:      bv              %r0(%r2)
189         nop
191         .exit
192         .procend
193 ENDPROC(flush_tlb_all_local)
195         .import cache_info,data
197 ENTRY(flush_instruction_cache_local)
198         .proc
199         .callinfo NO_CALLS
200         .entry
202         mtsp            %r0, %sr1
203         load32          cache_info, %r1
205         /* Flush Instruction Cache */
207         LDREG           ICACHE_BASE(%r1), %arg0
208         LDREG           ICACHE_STRIDE(%r1), %arg1
209         LDREG           ICACHE_COUNT(%r1), %arg2
210         LDREG           ICACHE_LOOP(%r1), %arg3
211         rsm             PSW_SM_I, %r22          /* No mmgt ops during loop*/
212         addib,COND(=)           -1, %arg3, fioneloop    /* Preadjust and test */
213         movb,<,n        %arg3, %r31, fisync     /* If loop < 0, do sync */
215 fimanyloop:                                     /* Loop if LOOP >= 2 */
216         addib,COND(>)           -1, %r31, fimanyloop    /* Adjusted inner loop decr */
217         fice            %r0(%sr1, %arg0)
218         fice,m          %arg1(%sr1, %arg0)      /* Last fice and addr adjust */
219         movb,tr         %arg3, %r31, fimanyloop /* Re-init inner loop count */
220         addib,COND(<=),n        -1, %arg2, fisync       /* Outer loop decr */
222 fioneloop:                                      /* Loop if LOOP = 1 */
223         addib,COND(>)           -1, %arg2, fioneloop    /* Outer loop count decr */
224         fice,m          %arg1(%sr1, %arg0)      /* Fice for one loop */
226 fisync:
227         sync
228         mtsm            %r22                    /* restore I-bit */
229         bv              %r0(%r2)
230         nop
231         .exit
233         .procend
234 ENDPROC(flush_instruction_cache_local)
237         .import cache_info, data
238 ENTRY(flush_data_cache_local)
239         .proc
240         .callinfo NO_CALLS
241         .entry
243         mtsp            %r0, %sr1
244         load32          cache_info, %r1
246         /* Flush Data Cache */
248         LDREG           DCACHE_BASE(%r1), %arg0
249         LDREG           DCACHE_STRIDE(%r1), %arg1
250         LDREG           DCACHE_COUNT(%r1), %arg2
251         LDREG           DCACHE_LOOP(%r1), %arg3
252         rsm             PSW_SM_I, %r22
253         addib,COND(=)           -1, %arg3, fdoneloop    /* Preadjust and test */
254         movb,<,n        %arg3, %r31, fdsync     /* If loop < 0, do sync */
256 fdmanyloop:                                     /* Loop if LOOP >= 2 */
257         addib,COND(>)           -1, %r31, fdmanyloop    /* Adjusted inner loop decr */
258         fdce            %r0(%sr1, %arg0)
259         fdce,m          %arg1(%sr1, %arg0)      /* Last fdce and addr adjust */
260         movb,tr         %arg3, %r31, fdmanyloop /* Re-init inner loop count */
261         addib,COND(<=),n        -1, %arg2, fdsync       /* Outer loop decr */
263 fdoneloop:                                      /* Loop if LOOP = 1 */
264         addib,COND(>)           -1, %arg2, fdoneloop    /* Outer loop count decr */
265         fdce,m          %arg1(%sr1, %arg0)      /* Fdce for one loop */
267 fdsync:
268         syncdma
269         sync
270         mtsm            %r22                    /* restore I-bit */
271         bv              %r0(%r2)
272         nop
273         .exit
275         .procend
276 ENDPROC(flush_data_cache_local)
278         .align  16
280 ENTRY(copy_user_page_asm)
281         .proc
282         .callinfo NO_CALLS
283         .entry
285 #ifdef CONFIG_64BIT
286         /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
287          * Unroll the loop by hand and arrange insn appropriately.
288          * GCC probably can do this just as well.
289          */
291         ldd             0(%r25), %r19
292         ldi             (PAGE_SIZE / 128), %r1
294         ldw             64(%r25), %r0           /* prefetch 1 cacheline ahead */
295         ldw             128(%r25), %r0          /* prefetch 2 */
297 1:      ldd             8(%r25), %r20
298         ldw             192(%r25), %r0          /* prefetch 3 */
299         ldw             256(%r25), %r0          /* prefetch 4 */
301         ldd             16(%r25), %r21
302         ldd             24(%r25), %r22
303         std             %r19, 0(%r26)
304         std             %r20, 8(%r26)
306         ldd             32(%r25), %r19
307         ldd             40(%r25), %r20
308         std             %r21, 16(%r26)
309         std             %r22, 24(%r26)
311         ldd             48(%r25), %r21
312         ldd             56(%r25), %r22
313         std             %r19, 32(%r26)
314         std             %r20, 40(%r26)
316         ldd             64(%r25), %r19
317         ldd             72(%r25), %r20
318         std             %r21, 48(%r26)
319         std             %r22, 56(%r26)
321         ldd             80(%r25), %r21
322         ldd             88(%r25), %r22
323         std             %r19, 64(%r26)
324         std             %r20, 72(%r26)
326         ldd              96(%r25), %r19
327         ldd             104(%r25), %r20
328         std             %r21, 80(%r26)
329         std             %r22, 88(%r26)
331         ldd             112(%r25), %r21
332         ldd             120(%r25), %r22
333         std             %r19, 96(%r26)
334         std             %r20, 104(%r26)
336         ldo             128(%r25), %r25
337         std             %r21, 112(%r26)
338         std             %r22, 120(%r26)
339         ldo             128(%r26), %r26
341         /* conditional branches nullify on forward taken branch, and on
342          * non-taken backward branch. Note that .+4 is a backwards branch.
343          * The ldd should only get executed if the branch is taken.
344          */
345         addib,COND(>),n -1, %r1, 1b             /* bundle 10 */
346         ldd             0(%r25), %r19           /* start next loads */
348 #else
350         /*
351          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
352          * bundles (very restricted rules for bundling).
353          * Note that until (if) we start saving
354          * the full 64 bit register values on interrupt, we can't
355          * use ldd/std on a 32 bit kernel.
356          */
357         ldw             0(%r25), %r19
358         ldi             (PAGE_SIZE / 64), %r1
361         ldw             4(%r25), %r20
362         ldw             8(%r25), %r21
363         ldw             12(%r25), %r22
364         stw             %r19, 0(%r26)
365         stw             %r20, 4(%r26)
366         stw             %r21, 8(%r26)
367         stw             %r22, 12(%r26)
368         ldw             16(%r25), %r19
369         ldw             20(%r25), %r20
370         ldw             24(%r25), %r21
371         ldw             28(%r25), %r22
372         stw             %r19, 16(%r26)
373         stw             %r20, 20(%r26)
374         stw             %r21, 24(%r26)
375         stw             %r22, 28(%r26)
376         ldw             32(%r25), %r19
377         ldw             36(%r25), %r20
378         ldw             40(%r25), %r21
379         ldw             44(%r25), %r22
380         stw             %r19, 32(%r26)
381         stw             %r20, 36(%r26)
382         stw             %r21, 40(%r26)
383         stw             %r22, 44(%r26)
384         ldw             48(%r25), %r19
385         ldw             52(%r25), %r20
386         ldw             56(%r25), %r21
387         ldw             60(%r25), %r22
388         stw             %r19, 48(%r26)
389         stw             %r20, 52(%r26)
390         ldo             64(%r25), %r25
391         stw             %r21, 56(%r26)
392         stw             %r22, 60(%r26)
393         ldo             64(%r26), %r26
394         addib,COND(>),n -1, %r1, 1b
395         ldw             0(%r25), %r19
396 #endif
397         bv              %r0(%r2)
398         nop
399         .exit
401         .procend
402 ENDPROC(copy_user_page_asm)
405  * NOTE: Code in clear_user_page has a hard coded dependency on the
406  *       maximum alias boundary being 4 Mb. We've been assured by the
407  *       parisc chip designers that there will not ever be a parisc
408  *       chip with a larger alias boundary (Never say never :-) ).
410  *       Subtle: the dtlb miss handlers support the temp alias region by
411  *       "knowing" that if a dtlb miss happens within the temp alias
412  *       region it must have occurred while in clear_user_page. Since
413  *       this routine makes use of processor local translations, we
414  *       don't want to insert them into the kernel page table. Instead,
415  *       we load up some general registers (they need to be registers
416  *       which aren't shadowed) with the physical page numbers (preshifted
417  *       for tlb insertion) needed to insert the translations. When we
418  *       miss on the translation, the dtlb miss handler inserts the
419  *       translation into the tlb using these values:
421  *          %r26 physical page (shifted for tlb insert) of "to" translation
422  *          %r23 physical page (shifted for tlb insert) of "from" translation
423  */
425 #if 0
427         /*
428          * We can't do this since copy_user_page is used to bring in
429          * file data that might have instructions. Since the data would
430          * then need to be flushed out so the i-fetch can see it, it
431          * makes more sense to just copy through the kernel translation
432          * and flush it.
433          *
434          * I'm still keeping this around because it may be possible to
435          * use it if more information is passed into copy_user_page().
436          * Have to do some measurements to see if it is worthwhile to
437          * lobby for such a change.
438          */
440 ENTRY(copy_user_page_asm)
441         .proc
442         .callinfo NO_CALLS
443         .entry
445         ldil            L%(__PAGE_OFFSET), %r1
446         sub             %r26, %r1, %r26
447         sub             %r25, %r1, %r23         /* move physical addr into non shadowed reg */
449         ldil            L%(TMPALIAS_MAP_START), %r28
450         /* FIXME for different page sizes != 4k */
451 #ifdef CONFIG_64BIT
452         extrd,u         %r26,56,32, %r26                /* convert phys addr to tlb insert format */
453         extrd,u         %r23,56,32, %r23                /* convert phys addr to tlb insert format */
454         depd            %r24,63,22, %r28                /* Form aliased virtual address 'to' */
455         depdi           0, 63,12, %r28          /* Clear any offset bits */
456         copy            %r28, %r29
457         depdi           1, 41,1, %r29           /* Form aliased virtual address 'from' */
458 #else
459         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
460         extrw,u         %r23, 24,25, %r23       /* convert phys addr to tlb insert format */
461         depw            %r24, 31,22, %r28       /* Form aliased virtual address 'to' */
462         depwi           0, 31,12, %r28          /* Clear any offset bits */
463         copy            %r28, %r29
464         depwi           1, 9,1, %r29            /* Form aliased virtual address 'from' */
465 #endif
467         /* Purge any old translations */
469         pdtlb           0(%r28)
470         pdtlb           0(%r29)
472         ldi             64, %r1
474         /*
475          * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
476          * bundles (very restricted rules for bundling). It probably
477          * does OK on PCXU and better, but we could do better with
478          * ldd/std instructions. Note that until (if) we start saving
479          * the full 64 bit register values on interrupt, we can't
480          * use ldd/std on a 32 bit kernel.
481          */
485         ldw             0(%r29), %r19
486         ldw             4(%r29), %r20
487         ldw             8(%r29), %r21
488         ldw             12(%r29), %r22
489         stw             %r19, 0(%r28)
490         stw             %r20, 4(%r28)
491         stw             %r21, 8(%r28)
492         stw             %r22, 12(%r28)
493         ldw             16(%r29), %r19
494         ldw             20(%r29), %r20
495         ldw             24(%r29), %r21
496         ldw             28(%r29), %r22
497         stw             %r19, 16(%r28)
498         stw             %r20, 20(%r28)
499         stw             %r21, 24(%r28)
500         stw             %r22, 28(%r28)
501         ldw             32(%r29), %r19
502         ldw             36(%r29), %r20
503         ldw             40(%r29), %r21
504         ldw             44(%r29), %r22
505         stw             %r19, 32(%r28)
506         stw             %r20, 36(%r28)
507         stw             %r21, 40(%r28)
508         stw             %r22, 44(%r28)
509         ldw             48(%r29), %r19
510         ldw             52(%r29), %r20
511         ldw             56(%r29), %r21
512         ldw             60(%r29), %r22
513         stw             %r19, 48(%r28)
514         stw             %r20, 52(%r28)
515         stw             %r21, 56(%r28)
516         stw             %r22, 60(%r28)
517         ldo             64(%r28), %r28
518         addib,COND(>)           -1, %r1,1b
519         ldo             64(%r29), %r29
521         bv              %r0(%r2)
522         nop
523         .exit
525         .procend
526 ENDPROC(copy_user_page_asm)
527 #endif
529 ENTRY(__clear_user_page_asm)
530         .proc
531         .callinfo NO_CALLS
532         .entry
534         tophys_r1       %r26
536         ldil            L%(TMPALIAS_MAP_START), %r28
537 #ifdef CONFIG_64BIT
538 #if (TMPALIAS_MAP_START >= 0x80000000)
539         depdi           0, 31,32, %r28          /* clear any sign extension */
540         /* FIXME: page size dependend */
541 #endif
542         extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
543         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
544         depdi           0, 63,12, %r28          /* Clear any offset bits */
545 #else
546         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
547         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
548         depwi           0, 31,12, %r28          /* Clear any offset bits */
549 #endif
551         /* Purge any old translation */
553         pdtlb           0(%r28)
555 #ifdef CONFIG_64BIT
556         ldi             (PAGE_SIZE / 128), %r1
558         /* PREFETCH (Write) has not (yet) been proven to help here */
559         /* #define      PREFETCHW_OP    ldd             256(%0), %r0 */
561 1:      std             %r0, 0(%r28)
562         std             %r0, 8(%r28)
563         std             %r0, 16(%r28)
564         std             %r0, 24(%r28)
565         std             %r0, 32(%r28)
566         std             %r0, 40(%r28)
567         std             %r0, 48(%r28)
568         std             %r0, 56(%r28)
569         std             %r0, 64(%r28)
570         std             %r0, 72(%r28)
571         std             %r0, 80(%r28)
572         std             %r0, 88(%r28)
573         std             %r0, 96(%r28)
574         std             %r0, 104(%r28)
575         std             %r0, 112(%r28)
576         std             %r0, 120(%r28)
577         addib,COND(>)           -1, %r1, 1b
578         ldo             128(%r28), %r28
580 #else   /* ! CONFIG_64BIT */
581         ldi             (PAGE_SIZE / 64), %r1
584         stw             %r0, 0(%r28)
585         stw             %r0, 4(%r28)
586         stw             %r0, 8(%r28)
587         stw             %r0, 12(%r28)
588         stw             %r0, 16(%r28)
589         stw             %r0, 20(%r28)
590         stw             %r0, 24(%r28)
591         stw             %r0, 28(%r28)
592         stw             %r0, 32(%r28)
593         stw             %r0, 36(%r28)
594         stw             %r0, 40(%r28)
595         stw             %r0, 44(%r28)
596         stw             %r0, 48(%r28)
597         stw             %r0, 52(%r28)
598         stw             %r0, 56(%r28)
599         stw             %r0, 60(%r28)
600         addib,COND(>)           -1, %r1, 1b
601         ldo             64(%r28), %r28
602 #endif  /* CONFIG_64BIT */
604         bv              %r0(%r2)
605         nop
606         .exit
608         .procend
609 ENDPROC(__clear_user_page_asm)
611 ENTRY(flush_dcache_page_asm)
612         .proc
613         .callinfo NO_CALLS
614         .entry
616         ldil            L%(TMPALIAS_MAP_START), %r28
617 #ifdef CONFIG_64BIT
618 #if (TMPALIAS_MAP_START >= 0x80000000)
619         depdi           0, 31,32, %r28          /* clear any sign extension */
620         /* FIXME: page size dependend */
621 #endif
622         extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
623         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
624         depdi           0, 63,12, %r28          /* Clear any offset bits */
625 #else
626         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
627         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
628         depwi           0, 31,12, %r28          /* Clear any offset bits */
629 #endif
631         /* Purge any old translation */
633         pdtlb           0(%r28)
635         ldil            L%dcache_stride, %r1
636         ldw             R%dcache_stride(%r1), %r1
638 #ifdef CONFIG_64BIT
639         depdi,z         1, 63-PAGE_SHIFT,1, %r25
640 #else
641         depwi,z         1, 31-PAGE_SHIFT,1, %r25
642 #endif
643         add             %r28, %r25, %r25
644         sub             %r25, %r1, %r25
647 1:      fdc,m           %r1(%r28)
648         fdc,m           %r1(%r28)
649         fdc,m           %r1(%r28)
650         fdc,m           %r1(%r28)
651         fdc,m           %r1(%r28)
652         fdc,m           %r1(%r28)
653         fdc,m           %r1(%r28)
654         fdc,m           %r1(%r28)
655         fdc,m           %r1(%r28)
656         fdc,m           %r1(%r28)
657         fdc,m           %r1(%r28)
658         fdc,m           %r1(%r28)
659         fdc,m           %r1(%r28)
660         fdc,m           %r1(%r28)
661         fdc,m           %r1(%r28)
662         cmpb,COND(<<)           %r28, %r25,1b
663         fdc,m           %r1(%r28)
665         sync
666         bv              %r0(%r2)
667         pdtlb           (%r25)
668         .exit
670         .procend
671 ENDPROC(flush_dcache_page_asm)
673 ENTRY(flush_icache_page_asm)
674         .proc
675         .callinfo NO_CALLS
676         .entry
678         ldil            L%(TMPALIAS_MAP_START), %r28
679 #ifdef CONFIG_64BIT
680 #if (TMPALIAS_MAP_START >= 0x80000000)
681         depdi           0, 31,32, %r28          /* clear any sign extension */
682         /* FIXME: page size dependend */
683 #endif
684         extrd,u         %r26, 56,32, %r26       /* convert phys addr to tlb insert format */
685         depd            %r25, 63,22, %r28       /* Form aliased virtual address 'to' */
686         depdi           0, 63,12, %r28          /* Clear any offset bits */
687 #else
688         extrw,u         %r26, 24,25, %r26       /* convert phys addr to tlb insert format */
689         depw            %r25, 31,22, %r28       /* Form aliased virtual address 'to' */
690         depwi           0, 31,12, %r28          /* Clear any offset bits */
691 #endif
693         /* Purge any old translation */
695         pitlb           (%sr0,%r28)
697         ldil            L%icache_stride, %r1
698         ldw             R%icache_stride(%r1), %r1
700 #ifdef CONFIG_64BIT
701         depdi,z         1, 63-PAGE_SHIFT,1, %r25
702 #else
703         depwi,z         1, 31-PAGE_SHIFT,1, %r25
704 #endif
705         add             %r28, %r25, %r25
706         sub             %r25, %r1, %r25
709 1:      fic,m           %r1(%r28)
710         fic,m           %r1(%r28)
711         fic,m           %r1(%r28)
712         fic,m           %r1(%r28)
713         fic,m           %r1(%r28)
714         fic,m           %r1(%r28)
715         fic,m           %r1(%r28)
716         fic,m           %r1(%r28)
717         fic,m           %r1(%r28)
718         fic,m           %r1(%r28)
719         fic,m           %r1(%r28)
720         fic,m           %r1(%r28)
721         fic,m           %r1(%r28)
722         fic,m           %r1(%r28)
723         fic,m           %r1(%r28)
724         cmpb,COND(<<)           %r28, %r25,1b
725         fic,m           %r1(%r28)
727         sync
728         bv              %r0(%r2)
729         pitlb           (%sr0,%r25)
730         .exit
732         .procend
733 ENDPROC(flush_icache_page_asm)
735 ENTRY(flush_kernel_dcache_page_asm)
736         .proc
737         .callinfo NO_CALLS
738         .entry
740         ldil            L%dcache_stride, %r1
741         ldw             R%dcache_stride(%r1), %r23
743 #ifdef CONFIG_64BIT
744         depdi,z         1, 63-PAGE_SHIFT,1, %r25
745 #else
746         depwi,z         1, 31-PAGE_SHIFT,1, %r25
747 #endif
748         add             %r26, %r25, %r25
749         sub             %r25, %r23, %r25
752 1:      fdc,m           %r23(%r26)
753         fdc,m           %r23(%r26)
754         fdc,m           %r23(%r26)
755         fdc,m           %r23(%r26)
756         fdc,m           %r23(%r26)
757         fdc,m           %r23(%r26)
758         fdc,m           %r23(%r26)
759         fdc,m           %r23(%r26)
760         fdc,m           %r23(%r26)
761         fdc,m           %r23(%r26)
762         fdc,m           %r23(%r26)
763         fdc,m           %r23(%r26)
764         fdc,m           %r23(%r26)
765         fdc,m           %r23(%r26)
766         fdc,m           %r23(%r26)
767         cmpb,COND(<<)           %r26, %r25,1b
768         fdc,m           %r23(%r26)
770         sync
771         bv              %r0(%r2)
772         nop
773         .exit
775         .procend
776 ENDPROC(flush_kernel_dcache_page_asm)
778 ENTRY(purge_kernel_dcache_page)
779         .proc
780         .callinfo NO_CALLS
781         .entry
783         ldil            L%dcache_stride, %r1
784         ldw             R%dcache_stride(%r1), %r23
786 #ifdef CONFIG_64BIT
787         depdi,z         1, 63-PAGE_SHIFT,1, %r25
788 #else
789         depwi,z         1, 31-PAGE_SHIFT,1, %r25
790 #endif
791         add             %r26, %r25, %r25
792         sub             %r25, %r23, %r25
794 1:      pdc,m           %r23(%r26)
795         pdc,m           %r23(%r26)
796         pdc,m           %r23(%r26)
797         pdc,m           %r23(%r26)
798         pdc,m           %r23(%r26)
799         pdc,m           %r23(%r26)
800         pdc,m           %r23(%r26)
801         pdc,m           %r23(%r26)
802         pdc,m           %r23(%r26)
803         pdc,m           %r23(%r26)
804         pdc,m           %r23(%r26)
805         pdc,m           %r23(%r26)
806         pdc,m           %r23(%r26)
807         pdc,m           %r23(%r26)
808         pdc,m           %r23(%r26)
809         cmpb,COND(<<)           %r26, %r25, 1b
810         pdc,m           %r23(%r26)
812         sync
813         bv              %r0(%r2)
814         nop
815         .exit
817         .procend
818 ENDPROC(purge_kernel_dcache_page)
820 ENTRY(flush_user_dcache_range_asm)
821         .proc
822         .callinfo NO_CALLS
823         .entry
825         ldil            L%dcache_stride, %r1
826         ldw             R%dcache_stride(%r1), %r23
827         ldo             -1(%r23), %r21
828         ANDCM           %r26, %r21, %r26
830 1:      cmpb,COND(<<),n %r26, %r25, 1b
831         fdc,m           %r23(%sr3, %r26)
833         sync
834         bv              %r0(%r2)
835         nop
836         .exit
838         .procend
839 ENDPROC(flush_user_dcache_range_asm)
841 ENTRY(flush_kernel_dcache_range_asm)
842         .proc
843         .callinfo NO_CALLS
844         .entry
846         ldil            L%dcache_stride, %r1
847         ldw             R%dcache_stride(%r1), %r23
848         ldo             -1(%r23), %r21
849         ANDCM           %r26, %r21, %r26
851 1:      cmpb,COND(<<),n %r26, %r25,1b
852         fdc,m           %r23(%r26)
854         sync
855         syncdma
856         bv              %r0(%r2)
857         nop
858         .exit
860         .procend
861 ENDPROC(flush_kernel_dcache_range_asm)
863 ENTRY(flush_user_icache_range_asm)
864         .proc
865         .callinfo NO_CALLS
866         .entry
868         ldil            L%icache_stride, %r1
869         ldw             R%icache_stride(%r1), %r23
870         ldo             -1(%r23), %r21
871         ANDCM           %r26, %r21, %r26
873 1:      cmpb,COND(<<),n %r26, %r25,1b
874         fic,m           %r23(%sr3, %r26)
876         sync
877         bv              %r0(%r2)
878         nop
879         .exit
881         .procend
882 ENDPROC(flush_user_icache_range_asm)
884 ENTRY(flush_kernel_icache_page)
885         .proc
886         .callinfo NO_CALLS
887         .entry
889         ldil            L%icache_stride, %r1
890         ldw             R%icache_stride(%r1), %r23
892 #ifdef CONFIG_64BIT
893         depdi,z         1, 63-PAGE_SHIFT,1, %r25
894 #else
895         depwi,z         1, 31-PAGE_SHIFT,1, %r25
896 #endif
897         add             %r26, %r25, %r25
898         sub             %r25, %r23, %r25
901 1:      fic,m           %r23(%sr4, %r26)
902         fic,m           %r23(%sr4, %r26)
903         fic,m           %r23(%sr4, %r26)
904         fic,m           %r23(%sr4, %r26)
905         fic,m           %r23(%sr4, %r26)
906         fic,m           %r23(%sr4, %r26)
907         fic,m           %r23(%sr4, %r26)
908         fic,m           %r23(%sr4, %r26)
909         fic,m           %r23(%sr4, %r26)
910         fic,m           %r23(%sr4, %r26)
911         fic,m           %r23(%sr4, %r26)
912         fic,m           %r23(%sr4, %r26)
913         fic,m           %r23(%sr4, %r26)
914         fic,m           %r23(%sr4, %r26)
915         fic,m           %r23(%sr4, %r26)
916         cmpb,COND(<<)           %r26, %r25, 1b
917         fic,m           %r23(%sr4, %r26)
919         sync
920         bv              %r0(%r2)
921         nop
922         .exit
924         .procend
925 ENDPROC(flush_kernel_icache_page)
927 ENTRY(flush_kernel_icache_range_asm)
928         .proc
929         .callinfo NO_CALLS
930         .entry
932         ldil            L%icache_stride, %r1
933         ldw             R%icache_stride(%r1), %r23
934         ldo             -1(%r23), %r21
935         ANDCM           %r26, %r21, %r26
937 1:      cmpb,COND(<<),n %r26, %r25, 1b
938         fic,m           %r23(%sr4, %r26)
940         sync
941         bv              %r0(%r2)
942         nop
943         .exit
944         .procend
945 ENDPROC(flush_kernel_icache_range_asm)
947         /* align should cover use of rfi in disable_sr_hashing_asm and
948          * srdis_done.
949          */
950         .align  256
951 ENTRY(disable_sr_hashing_asm)
952         .proc
953         .callinfo NO_CALLS
954         .entry
956         /*
957          * Switch to real mode
958          */
959         /* pcxt_ssm_bug */
960         rsm             PSW_SM_I, %r0
961         load32          PA(1f), %r1
962         nop
963         nop
964         nop
965         nop
966         nop
968         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
969         mtctl           %r0, %cr17              /* Clear IIASQ tail */
970         mtctl           %r0, %cr17              /* Clear IIASQ head */
971         mtctl           %r1, %cr18              /* IIAOQ head */
972         ldo             4(%r1), %r1
973         mtctl           %r1, %cr18              /* IIAOQ tail */
974         load32          REAL_MODE_PSW, %r1
975         mtctl           %r1, %ipsw
976         rfi
977         nop
979 1:      cmpib,=,n       SRHASH_PCXST, %r26,srdis_pcxs
980         cmpib,=,n       SRHASH_PCXL, %r26,srdis_pcxl
981         cmpib,=,n       SRHASH_PA20, %r26,srdis_pa20
982         b,n             srdis_done
984 srdis_pcxs:
986         /* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
988         .word           0x141c1a00              /* mfdiag %dr0, %r28 */
989         .word           0x141c1a00              /* must issue twice */
990         depwi           0,18,1, %r28            /* Clear DHE (dcache hash enable) */
991         depwi           0,20,1, %r28            /* Clear IHE (icache hash enable) */
992         .word           0x141c1600              /* mtdiag %r28, %dr0 */
993         .word           0x141c1600              /* must issue twice */
994         b,n             srdis_done
996 srdis_pcxl:
998         /* Disable Space Register Hashing for PCXL */
1000         .word           0x141c0600              /* mfdiag %dr0, %r28 */
1001         depwi           0,28,2, %r28            /* Clear DHASH_EN & IHASH_EN */
1002         .word           0x141c0240              /* mtdiag %r28, %dr0 */
1003         b,n             srdis_done
1005 srdis_pa20:
1007         /* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+,PCXW2 */
1009         .word           0x144008bc              /* mfdiag %dr2, %r28 */
1010         depdi           0, 54,1, %r28           /* clear DIAG_SPHASH_ENAB (bit 54) */
1011         .word           0x145c1840              /* mtdiag %r28, %dr2 */
1014 srdis_done:
1015         /* Switch back to virtual mode */
1016         rsm             PSW_SM_I, %r0           /* prep to load iia queue */
1017         load32          2f, %r1
1018         nop
1019         nop
1020         nop
1021         nop
1022         nop
1024         rsm             PSW_SM_Q, %r0           /* prep to load iia queue */
1025         mtctl           %r0, %cr17              /* Clear IIASQ tail */
1026         mtctl           %r0, %cr17              /* Clear IIASQ head */
1027         mtctl           %r1, %cr18              /* IIAOQ head */
1028         ldo             4(%r1), %r1
1029         mtctl           %r1, %cr18              /* IIAOQ tail */
1030         load32          KERNEL_PSW, %r1
1031         mtctl           %r1, %ipsw
1032         rfi
1033         nop
1035 2:      bv              %r0(%r2)
1036         nop
1037         .exit
1039         .procend
1040 ENDPROC(disable_sr_hashing_asm)
1042         .end